You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:10:50