react-native 集成 FFmpeg 能力 - 使用 FFmpegKit(一)

相关文章:
react-native 集成 FFmpeg 能力 - 使用 FFmpegKit(二)
react-native 集成 FFmpeg 能力 - 使用 FFmpegKit(三)

这一篇主要记录对于 react-native 库的使用。

最近在做 react-native 的需求,需要做一些视频剪辑。ios 上使用的是 AVFoundation,询问了 AI 还比较顺利,功能实现了。Android 上使用的是 MediaCodec,就是怎么都调试不出来。AI 也直接建议用 FFmpeg 了。

一、现状调研

FFmpeg 也是个很知名很强大的音视频处理工具了,一般用在命令行。在这个基础上,网上有大佬封装适配了多个平台的库,其中也包括 react-native,仓库地址 ffmpeg-kit。很遗憾的是,今年年初因为人力资源问题,大佬停止了更新。

这里提到了:《Saying Goodbye to FFmpegKit》。感谢大佬们的用爱发电啊。

截止到当前,FFmpeg 版本是 7,FFmpegKit 封装的版本是 6。同时 FFmpegKit 也删除了 IOS 和 Android 仓库里的库,所以 react-native 的也用不了了。但是仓库源码还在。所以目前还想继续使用 FFmpegKit 的话,可以:

  1. 找之前网上保留过的资源,或者其他大佬私下打包出来分享的。
  2. 自己根据源码打包,因为不维护了,自己解决打包出现的问题。

二、资源准备

当然找到了资源包,也得自己引入,因为正常的安装流程已经报错了,得本地引入(自己打包放到网上仓库也可以),首先:

Android - aar 下载,然后在本地引入。
IOS - 参考文章,可以将 podFile 指向 FFmpegKit 原仓库的地址改成指向「别的地址」(其实就是这个文章作者大佬自己的仓库),保证能下载到依赖压缩包就行,也可以根据这份 podspec 文件里面指向的 zip 包地址,把依赖包下载下来,放在自己本地引入。

三、react-native 库引入使用

react-native 库:《ffmpeg-kit-react-native》,原《使用文档》,现在安装这个库会报已经废弃的警告。

现在在获得 IOS 和 Android 依赖包的情况下,进行本地引入,使得 react-native 库也能用起来。当然相应的 IOS 和 Android 库也能用。
首先在项目根目录放置两个依赖库(地址随意,用的时候正确使用就行):

ios 文件夹有一个 ffmpeg-kit-ios-video.podspec 文件,这不是资源包下载下来附带的,要自己添加,相当于依赖声明。

Android 端修复使用

Android 端的使用还是比较简单的,直接打 patch 修改 node_modules 里的文件内容就行:找到 node_modules/ffmpeg-kit-react-native/android/build.gradle 文件,修改成一下这样即可:

dependencies {
  api 'com.facebook.react:react-native:+'
  // 这句注释:implementation 'com.arthenica:ffmpeg-kit-' + safePackageName(safeExtGet('ffmpegKitPackage', 'https')) + ':' + safePackageVersion(safeExtGet('ffmpegKitPackage', 'https'))
  // 添加下面两句,引入本地依赖和其他依赖
  implementation files('../../../libs/android/ffmpeg-kit.aar')
  implementation 'com.arthenica:smart-exception-java:0.2.1'
}

IOS 端修复使用

1、

首先上面提到的 ffmpeg-kit-ios-video.podspec

Pod::Spec.new do |s|
  s.name         = 'ffmpeg-kit-ios-video'
  s.version      = '6.0'
  s.summary      = 'FFmpeg Kit for React Native'
  s.homepage     = 'https://github.com/arthenica/ffmpeg-kit'
  s.license      = 'LGPL-3.0'
  s.authors      = 'author'
  s.platform          = :ios
  s.requires_arc      = true
  s.static_framework  = true
  s.source       = { path: '.' }
  s.dependency "React-Core"
  s.vendored_frameworks = '*.xcframework'
end
2、

然后项目下找到 ios/Podfile 文件,修改:

// 备用:pod 'ffmpeg-kit-ios-full', :podspec => 'https://raw.githubusercontent.com/luthviar/ffmpeg-kit-ios-full/main/ffmpeg-kit-ios-full.podspec'
pod 'ffmpeg-kit-ios-video', :path => '../libs/ios/ffmpeg-kit-ios-video'
pod 'ffmpeg-kit-react-native', :subspecs => ['video'], :podspec => '../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec'
// 找到下面这一句,然后在这一句上面添加上面那两句,顺序严格
config = use_native_modules!(config_command)

注意:这里的依赖库名是 ffmpeg-kit-ios-video,是因为我自己本地打了个 video 包出来,所以命名为 video 后缀。如果自己打出来了别的包,或者网上找的包是 full 或者别的名字,只要把所有相应的名字改了就行。

比如 ffmpeg-kit-ios-video 全改成 ffmpeg-kit-ios-full,包括那个 libs/ios 下的 podspec 文件。
:subspecs => ['video'] 理论上应该也没影响了,不过也最好改一下,改成::subspecs => ['full']

3、

如果是 expo 项目,这里有个小问题。ios 文件夹都是每次 build 生成的,当然里面的 Podfile 文件也是,也就是每次重新创建文件,都要自己去打这个补丁。太麻烦了,所以得换另外方式。
注意下面示例我是用了 ffmpeg-kit-ios-full 的包,这个和自己本地引入的实际包名保持一致就好了。

用官方的工具 expo-build-properties,在 app.config.ts 文件加上:

const config = {
  // 其他省略
  plugins: [
    [
      'expo-build-properties',
      {
        ios: {
          extraPods: [
            {
              name: 'ffmpeg-kit-ios-full',
              path: '../libs/ios/ffmpeg-kit-ios-full', // 本地路径(相对于 ios/Podfile)
            },
            {
              name: 'ffmpeg-kit-react-native',
              podspec:
                  '../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec', // 本地路径(相对于 ios/Podfile)
            },
          ],
        },
      },
    ],
  ],
}

这样,每次 build 创建 ios/Podfile 文件时候,就会打上上面的补丁。可以看到上面是打了两份补丁,一个 ffmpeg-kit 本身,自己使用本地引入的。一个是对应的 react-native 库,指向了 node_modules 里的文件,但是这个 react-native 库 podspec 文件已经知道是有问题的。
所以还要再对 node_modules 的 ffmpeg-kit-react-native 依赖包再打一份针对 ios 的 patch:

Pod::Spec.new do |s|
  s.source       = { :git => "https://github.com/arthenica/ffmpeg-kit.git", :tag => "react.native.v#{s.version}" }
  s.dependency "React-Core"
  s.source_files      = '**/FFmpegKitReactNativeModule.m',
    '**/FFmpegKitReactNativeModule.h'
  s.dependency 'ffmpeg-kit-ios-full', "6.0"
  s.ios.deployment_target = '10'
end

四、测试使用

本地库和配置文件都准备完毕,因为改了原生依赖,所以最好重新编译一遍。我使用的是 expo 项目,可以执行:npx expo prebuild --clean 重新安装一遍。
如果用的纯 react-native 项目,就用 xcode 和 Android Studio 重新安装。

在代码里测试是否引用成功:

import { ReturnCode } from 'ffmpeg-kit-react-native';
FFmpegKitConfig.getFFmpegVersion().then(v => console.log('getFFmpegVersion', v))