react native 混合开发之引入ffmpeg(视频处理)参考

1,563 阅读2分钟

1 使用到的官方参考及项目地址

ffmpeg-kit仓库地址 ffmpeg-kit-test仓库地址 ffmpeg官方参考文档 ffmpeg-kit-Android使用参考 用 ffmpeg 压缩视频命令参考

2 FFmpegKit概述

FFmpegKit是一个封装了 FFmpeg 库的脚本

FFmpegKit是一个在应用程序中运行FFmpeg/FFprobe命令的包装库

支持安卓、iOS、macOS 和 tvOS 基于v4.4-dev带有可选系统和外部库的FFmpeg Github、Maven Central和CocoaPods 上提供了 8 个预构建的二进制包。 根据 许可LGPL 3.0,或者GPL v3.0如果启用了 GPL 许可的库

2 Android端引入

2.1 会遇到的错误

error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup.
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDebugNativeLibs'.
   > More than one file was found with OS independent path 'lib/armeabi-v7a/libc++_shared.so'. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake
   
* 错误说明:本地项目和第三方库引用的相同的.so文件,或者是两个第三方库引入了相同的.so文件,
导致编译的时候不知道以哪个为主

2.2 如何处理

  • 参考 www.freesion.com/article/502…

  • 根据启动RN项目是给到的提示 在这里插入图片描述

  • 在Android Studio 修改android/app目录的下的build.gradle文件的android{}中添加这样一行代码。然后点击Sync

 packagingOptions {
        pickFirst  'lib/x86/libc++_shared.so'
        pickFirst  'lib/arm64-v8a/libc++_shared.so'
        pickFirst  'lib/x86_64/libc++_shared.so'
        pickFirst  'lib/armeabi-v7a/libc++_shared.so'
    }

3 react native 传递ffmpe 命令给android原生层执行

3.1AndroidManifest.xml注册权限

  • 权限注册

3.2 使用react-native-image-crop-picker获取视频路径,生成ffmpe命令传递给andorid原生层执行

import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';
import ImagePicker from 'react-native-image-crop-picker';
import ToastExample from '../../native/ToastExample';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      path: ''
    };
  }

  /**
   * 从图库中选择视频
   */
  pickVideo = () => {
    ImagePicker.openPicker({
      mediaType: 'video'
    })
      .then((image) => {
        console.log(image);
        this.setState({ path: image.path });
      })
      .catch((error) => {
        console.log(error);
      });
  };

  toast = () => {
    const command = `-i ${ this.state.path } -r 20 /sdcard/$MuMu共享文件夹/1111.mp4`
    console.log(command)
    ToastExample.show(command);
  };

  render() {
    return (
      <View style={{ flex: 1 }}>
        <Text> videoPick </Text>
        <Button title="选择视频" onPress={this.pickVideo} />
        <Button title="toast" onPress={this.toast} />
      </View>
    );
  }
}

3.3 android 原生层代码实现

    @ReactMethod
    public void show(String message) {
        Log.d(TAG, message);
//        Toast.makeText(getReactApplicationContext(), message, duration).show();

        FFmpegSession session = FFmpegKit.execute(message);
        if (ReturnCode.isSuccess(session.getReturnCode())) {

            // SUCCESS
            Log.d(TAG, "show: SUCCESS"+ session.getOutput());

        } else if (ReturnCode.isCancel(session.getReturnCode())) {
            // CANCEL
            Log.d(TAG, "show: CANCEL");

        } else {
            // FAILURE
            Log.d(TAG, String.format("Command failed with state %s and rc %s.%s", session.getState(), session.getReturnCode(), session.getFailStackTrace()));
        }
    }

4 ffmpeg常用命令整理

4.1 视频压缩流程

  • 选择视频:android mp4
  • 压缩后的视频在上传后, 压缩 并 上传 (上传),压缩后的文件被删除掉

4.2 先 视频裁剪

ffmpeg -ss 00:00:00 -i video.mp4 -vcodec copy -acodec copy -t 00:00:31 output1.mp4

4.3 后 压缩

-i this.state.pathr20/sdcard/{ this.state.path } -r 20 /sdcard/MuMu共享文件夹/1111.mp4

4.4 提取音频(放到手机里)

 ffmpeg -i 人生若只如初见.flv -vn r.mp3
#-vn 解析  video no简写,忽略视频

4.5 压缩mp3

ffmpeg -i input.mp3 -ab 128 output.mp3 //这里将比特率设为128

H264 与h265 的区别

h265在视频运动,视频丢帧情况下更牛逼,更好