如何拼接MediaRecorder生成的多段视频切片?
视频切片拼接问题解决
问题背景
前端使用MediaRecorder每10秒生成一段视频切片并上传至后端,代码如下:
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' }); mediaRecorder.start(10000); mediaRecorder.ondataavailable = (e) => { const formData = new FormData(); formData.append('video', new Blob([e.data], { 'type' : 'video/webm;' })); fetch('http://localhost/api/session/12/video/stream', { method: 'POST', body: formData, }).then(() => { console.log('success') }).catch((e) => { console.log('error') console.log(e); }); };
后端保存的20秒录制文件包含两个切片:
erKa3MVTuDfnuDUQUhUd2huUaCKfihtm8thc0KX0.bin hAhJfVNxMEJK2MsyR99a7t7UkT3pjHkmdN1j2C9G.mkv
推测第一个切片为带容器头的WebM,后续切片为无容器的裸流,使用以下ffmpeg命令拼接时出错:
ffmpeg -i erKa3MVTuDfnuDUQUhUd2huUaCKfihtm8thc0KX0.bin -i hAhJfVNxMEJK2MsyR99a7t7UkT3pjHkmdN1j2C9G.mkv -filter_complex "concat=n=2:v=0:a=1" -vn -y final-video.mp4
错误核心信息:
Input #0, h264, from 'erKa3MVTuDfnuDUQUhUd2huUaCKfihtm8thc0KX0.bin': Stream #0:0: Video: h264 (Baseline), yuv420p(tv, bt709, progressive), 1920x1080, 25 fps, 25 tbr, 1200k tbn, 50 tbc Input #1, matroska,webm, from 'hAhJfVNxMEJK2MsyR99a7t7UkT3pjHkmdN1j2C9G.mkv': Stream #1:0(eng): Video: h264 (Baseline), yuv420p(tv, bt709, progressive), 1920x1080, SAR 1:1 DAR 16:9, 29.33 fps, 29.33 tbr, 1k tbn, 2k tbc (default) Cannot find a matching stream for unlabeled input pad 0 on filter Parsed_concat_0
问题分析
- 输入文件格式不统一:
.bin是裸H.264视频流,.mkv是带WebM/Matroska容器的视频文件,concat滤镜要求所有输入流的编码参数、格式完全一致,因此触发报错。 - 命令参数错误:指定
v=0:a=1表示忽略视频、拼接音频,但实际两个文件只有视频流,导致滤镜找不到匹配的音频流。
解决方案
方案1:后端直接二进制拼接切片(推荐)
WebM/Matroska格式支持流式拼接,只需将所有切片按录制顺序直接二进制合并,即可得到完整的WebM文件:
- 按录制时间顺序将
.bin和.mkv的内容依次写入同一个文件,命名为full.webm - 如需转成MP4格式,执行:
ffmpeg -i full.webm -c:v libx264 -c:a aac final-video.mp4
方案2:用ffmpeg统一格式后拼接
如果无法直接二进制合并,先将裸流包装成WebM容器,再用concat demuxer拼接:
- 将
.bin转成WebM容器:ffmpeg -f h264 -i erKa3MVTuDfnuDUQUhUd2huUaCKfihtm8thc0KX0.bin -c copy first.webm - 创建文件列表
filelist.txt,内容如下:file 'first.webm' file 'hAhJfVNxMEJK2MsyR99a7t7UkT3pjHkmdN1j2C9G.mkv' - 执行拼接命令:
ffmpeg -f concat -safe 0 -i filelist.txt -c copy temp.webm - 转成MP4(可选):
ffmpeg -i temp.webm -c:v libx264 -c:a aac final-video.mp4
关于MIME类型的疑问
不需要每次上传都额外处理MIME类型。MediaRecorder生成的第一个切片包含WebM容器头,后续切片是增量的裸流数据——这是API的正常行为。后端只需按顺序保存所有切片,最终合并即可,前端当前的Blob类型设置不影响切片的实际数据结构。
内容的提问来源于stack exchange,提问作者Bruno Francisco
相关产品推荐
相关产品推荐

