使用ffmpeg-kit-react-native在React Native/Expo中执行VP9视频编码失败
解决Expo + ffmpeg-kit-react-native转VP9编码失败的问题
核心问题排查与修复方案
1. 输出路径必须指定具体文件名
你的resultVideoURI是目录路径,FFmpeg需要明确的输出文件名。VP9通常推荐封装为WebM格式,修改路径如下:
const resultVideoURI = `${FileSystem.documentDirectory}video/output.webm`;
若要封装为MP4,可指定.mp4后缀,但需注意部分播放器不支持MP4容器的VP9编码。
2. 修正FFmpeg命令参数
原命令存在三个问题:用单引号导致变量未解析、缺少音频编码配置、未添加VP9优化参数,修正后的命令如下:
// 用反引号包裹命令以正确解析变量 const command = `-i ${sourceVideoURI} -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus ${resultVideoURI}`; FFmpegKit.execute(command).then(session => { const returnCode = FFmpegKitConfig.returnCode(session); if (ReturnCode.isSuccess(returnCode)) { // 转换成功逻辑 } else if (ReturnCode.isCancel(returnCode)) { // 任务取消逻辑 } else { // 打印日志排查错误 FFmpegKitConfig.printSessionLogs(session); } });
参数说明:
-crf 30:控制视频质量,值越小质量越高(范围0-63)-b:v 0:让FFmpeg完全基于CRF控制码率-c:a libopus:音频使用Opus编码,适配WebM容器
3. 转换Expo ImagePicker返回的URI格式
Expo返回的sourceVideoURI若为content://格式,FFmpeg无法直接访问,需转换为真实文件路径:
import * as MediaLibrary from 'expo-media-library'; async function getRealVideoPath(uri) { const asset = await MediaLibrary.getAssetInfoAsync(uri); return asset.localUri; // 返回file://开头的可访问路径 } // 使用示例 const realSourcePath = await getRealVideoPath(sourceVideoURI); const command = `-i ${realSourcePath} ...`;
4. 修正FFmpeg Kit配置(避免修改node_modules)
直接修改node_modules内的文件会在依赖更新后失效,在项目根目录的android/build.gradle中配置:
buildscript { ext { ffmpegKitPackage = "video" // 其他原有配置 } }
Expo 45环境下,建议使用expo-build-properties插件传递配置,安装后在app.json中添加:
{ "expo": { "plugins": [ [ "expo-build-properties", { "android": { "extraBuildGradleParams": { "ext.ffmpegKitPackage": "\"video\"" } } } ] ] } }
5. 申请文件读写权限
Android平台需申请存储权限才能读写视频文件:
import * as Permissions from 'expo-permissions'; async function requestStoragePermission() { const { status } = await Permissions.askAsync(Permissions.MEDIA_LIBRARY); if (status !== 'granted') { alert('需要存储权限才能完成视频转换'); } }
调试技巧
若问题仍存在,打印FFmpeg会话日志定位具体错误:
FFmpegKit.execute(command).then(session => { FFmpegKitConfig.printSessionLogs(session); FFmpegKitConfig.printSessionAllLogs(session); });
内容的提问来源于stack exchange,提问作者juejue
相关产品推荐
相关产品推荐

