Expo-AV Video组件无法渲染合并视频URI,需重启应用才可显示
解决Expo AV Video组件无法加载FFmpegKit刚合并的视频问题
问题分析
你遇到的Loading finished before preparation is complete报错,核心原因是FFmpeg合并视频的异步操作未完全完成,就触发了Video组件加载文件——此时文件可能还在写入磁盘,或系统未更新文件元数据,导致组件无法正确解析视频内容。重启后文件已完全写入,再次合并同名文件时直接读取已存在的完整文件,因此能正常显示。
解决方案
1. 等待FFmpeg合并完成后再更新状态
必须确保FFmpeg执行成功且文件完全写入后,再更新mergedVideo状态。通过监听FFmpeg的返回码判断执行结果:
const mergeVideos = async () => { const outputPath = `${FileSystem.documentDirectory}merged.mp4`; // 示例FFmpeg合并命令,根据你的实际需求调整 const ffmpegCommand = `-i ${videoPath1} -i ${videoPath2} -c copy ${outputPath}`; const session = await FFmpegKit.execute(ffmpegCommand); const returnCode = await session.getReturnCode(); // 确认合并成功 if (returnCode.isSuccess()) { // 后续执行文件刷新和状态更新 await handlePostMerge(outputPath); } else { console.error('视频合并失败:', await session.getFailStackTrace()); } };
2. 刷新文件系统缓存(Android专属)
Android系统在文件写入后可能不会立即更新元数据,Expo FileSystem提供refreshAssetsAsync方法强制刷新,让系统识别新生成的文件:
const handlePostMerge = async (outputPath) => { // 刷新文件缓存 await FileSystem.refreshAssetsAsync(outputPath); // 更新状态 setMergedVideo(outputPath); };
3. 强制重置Video组件的源
如果使用同名文件覆盖旧文件,Expo AV可能会缓存旧文件内容。可以先将源设为null,短暂延迟后再设置新路径,触发组件重新加载:
const handlePostMerge = async (outputPath) => { await FileSystem.refreshAssetsAsync(outputPath); // 先清空源,再设置新路径 setMergedVideo(null); setTimeout(() => { setMergedVideo(outputPath); }, 100); // 100ms延迟确保组件重置完成 };
4. 避免同名文件覆盖(可选)
每次合并生成唯一文件名,彻底避免缓存和覆盖问题:
const generateUniquePath = () => { const timestamp = Date.now(); return `${FileSystem.documentDirectory}merged_${timestamp}.mp4`; }; // 在合并函数中使用 const outputPath = generateUniquePath();
验证要点
- 确认
outputPath使用的是Expo有权限访问的目录(优先用FileSystem.documentDirectory) - 检查FFmpeg命令是否正确,确保生成的视频文件本身无损坏(可手动在模拟器文件管理器中打开验证)
- 确保
mergedVideo状态确实在FFmpeg完成后才更新(可通过console.log打印状态变化时间点)
内容的提问来源于stack exchange,提问作者Jym Nkana
相关产品推荐
相关产品推荐

