如何为MediaRecorder生成的Blob转视频文件添加时长信息?
解决MediaRecorder录制MP4无时长信息的问题
问题原因
MediaRecorder生成的MP4文件默认采用流式写入,存储时长、轨道信息等关键元数据的moov块会被放在文件末尾。大部分播放器需要先读取moov块才能识别时长,因此会出现音画播放正常但无法读取时长的情况。另外,直接合并不同来源的音视频轨道时,MediaRecorder可能未正确同步轨道的时间戳元数据,也会导致时长识别失败。
解决方案
方案一:用FFmpeg.wasm在前端修复MP4元数据
这是最可靠的前端解决方案,通过FFmpeg重新封装MP4文件,将moov块移至文件开头,并补全标准的时长元数据,且不会重新编码视频(速度快)。
示例代码:
// 先在HTML中引入FFmpeg.wasm库 // <script src="https://unpkg.com/@ffmpeg/ffmpeg@0.12.6/dist/ffmpeg.min.js"></script> const { createFFmpeg, fetchFile } = FFmpeg; const ffmpeg = createFFmpeg({ log: true }); mediaRecorder.ondataavailable = async (ev) => { // 等待FFmpeg加载完成 if (!ffmpeg.isLoaded()) await ffmpeg.load(); // 将录制得到的Blob写入FFmpeg虚拟文件系统 ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(ev.data)); // 执行重新封装命令:复制原音视频流,生成moov前置的标准MP4 await ffmpeg.run('-i', 'input.mp4', '-c', 'copy', '-movflags', 'faststart', 'output.mp4'); // 读取修复后的文件 const data = ffmpeg.FS('readFile', 'output.mp4'); const fixedFile = new File([data.buffer], 'fixed-video.mp4', { type: 'video/mp4' }); // 触发下载 const link = document.createElement('a'); link.href = URL.createObjectURL(fixedFile); link.download = 'fixed-video.mp4'; document.body.appendChild(link); link.click(); document.body.removeChild(link); };
方案二:优化MediaRecorder录制参数(兼容性有限)
部分现代浏览器支持通过指定带参数的mimeType,强制生成符合标准的MP4文件,但该方法兼容性较差,仅在部分环境生效:
// 指定编码格式并要求生成moov前置的MP4 const mediaRecorder = new MediaRecorder(videoStream, { mimeType: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', videoBitsPerSecond: 2500000, audioBitsPerSecond: 128000 });
额外注意事项
- 你的原始代码存在拼写错误:
vidoStream应改为videoStream,需先修正避免录制失败 - 录制停止时,确保音频、视频轨道均正常结束,避免元数据缺失
- 使用FFmpeg.wasm时,需注意浏览器的CORS限制,建议使用同源CDN或本地部署库
内容的提问来源于stack exchange,提问作者Shahid Khan
相关产品推荐
相关产品推荐

