使用MediaRecorder录制时如何按间隔获取可正常播放的分段视频?
MediaRecorder 分段录制上传解决方案
你当前的实现存在的问题是:MediaRecorder 输出的是连续的容器格式流,只有首次触发 ondataavailable 返回的分片携带完整的视频文件头,后续分片仅包含裸音视频帧数据,没有文件头信息,因此无法独立播放;同时每个单独分片没有容器尾标识,所以第一个分片播放时会抛出File ended prematurely的警告。
方案1:分片可独立播放(高容错场景)
适合要求录制中途断开后,已上传的所有分片都能单独正常使用的场景,无需后端拼接。
实现逻辑
每段分片录制完成后停止当前 MediaRecorder 实例,重新实例化新的录制器,每次停止触发的 ondataavailable 拿到的 blob 都是带完整文件头、尾的独立可播放文件。
代码示例
let mediaRecorder = null; const CHUNK_DURATION = 10000; // 10秒分片 let recordStream = null; // 全局保留录屏流,避免重复申请权限 // 启动录制入口 const handleRecord = function ({stream}) { recordStream = stream; startNewRecorderInstance(); }; // 启动新的录制器实例 const startNewRecorderInstance = () => { // 明确指定编码格式,避免不同浏览器默认值不一致导致兼容性问题 mediaRecorder = new MediaRecorder(recordStream, { mimeType: 'video/webm;codecs=vp8,opus' }); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) { uploadVideoPart(e.data); // 此处拿到的每个分片都是可独立播放的完整文件 } }; // 当前分片录制结束后,自动启动下一段录制 mediaRecorder.onstop = () => { if (recordStream.active) { startNewRecorderInstance(); } }; mediaRecorder.start(); // 到分片时长后停止当前录制 setTimeout(() => { if (mediaRecorder.state === 'recording') { mediaRecorder.stop(); } }, CHUNK_DURATION); }; // 停止整个录制流程 const stopFullRecord = () => { if (mediaRecorder?.state === 'recording') { mediaRecorder.stop(); } recordStream?.getTracks().forEach(track => track.stop()); };
优缺点
- 优点:每个分片独立完整,任意分片上传失败不影响其他分片,容错性极高
- 缺点:每次重启录制器会丢失几毫秒的帧数据,对录制连续性要求极高的场景不适用
方案2:分片需后端合并(高连续度场景)
适合要求录制无帧丢失,最终只需要一个完整视频文件的场景。
实现逻辑
无需重建 MediaRecorder 实例,保持原有间隔触发 ondataavailable 的逻辑,给每个分片增加递增序号,后端按序号将所有分片二进制拼接即可得到完整可播放的视频文件。
代码示例
const handleRecord = function ({stream}) { // 明确指定编码格式 const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp8,opus' }); let chunkIndex = 0; mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) { uploadVideoPart({ data: e.data, index: chunkIndex // 携带序号,后端按顺序拼接 }); chunkIndex++; } }; // 录制结束时给后端发送结束标记 mediaRecorder.onstop = () => { uploadVideoPart({ isEnd: true, totalChunks: chunkIndex }); }; mediaRecorder.start(10000); };
注意事项
- 第一个分片单独播放出现的提前结束警告是正常现象,拼接完成后警告会消失
- 必须保证分片按序号顺序拼接,乱序会导致完整文件损坏
- 这种方案无帧丢失,录制连续性好,但只要有一个分片丢失,整个视频就无法正常播放
内容的提问来源于stack exchange,提问作者fguillen
相关产品推荐
相关产品推荐

