如何用MediaRecorder将同配置双视频轨道合并为可播放WebM文件?
如何用MediaRecorder合并同配置不同轨道的WebM录制内容
我有一个包含视频和音频轨道的MediaStream,正在用MediaRecorder录制,每秒生成的Blob会发送到服务器并写入WebM文件(原本能正常播放)。但如果在替换同配置新轨道前暂停MediaRecorder,恢复录制后把Blob追加到同一文件,文件只能播放到暂停前的内容。想知道怎么让MediaRecorder把两个同配置的不同视频轨道生成一个可播放的完整WebM文件。
原代码示例
client.js
const videoStream = await getUserMedia({video: true}) const recorder = new MediaRecorder(videoStream, {mimeType: "video/webm; codecs=vp9"}); recorder.addEventListener('dataavailable', async function(blob) { const buffer = await blob.toArrayBuffer(); socket.emit('data', buffer); }) recorder.start(1000); // 一段时间后 recorder.pause(); recorder.requestData(); // 替换轨道 videoStream.removeTrack(oldVideoTrack); videoStream.addTrack(newVideoTrack); recorder.resume();
server.js
const file = 'file.webm' socket.on('data', function(buffer){ appendFile(file, new Uint8Array(buffer), function (err) { if (err) { throw err; } }); })
问题根源
WebM文件的头部元数据只记录了初始录制时的轨道信息,替换轨道后,原MediaRecorder恢复录制时不会更新文件的轨道元数据,播放器读取到暂停点后,无法识别后续属于新轨道的编码数据,导致播放终止。
解决方法
方法一:替换轨道后重建MediaRecorder(推荐实时场景)
不要直接复用原Recorder,而是在替换轨道后创建新的MediaRecorder实例,新实例会生成包含新轨道元数据的录制片段,确保播放器能识别完整内容:
// client.js 修改版 let videoStream = await getUserMedia({video: true}) let recorder = new MediaRecorder(videoStream, {mimeType: "video/webm; codecs=vp9"}); // 封装发送Blob到服务器的逻辑 const sendBlob = async (blob) => { const buffer = await blob.toArrayBuffer(); socket.emit('data', buffer); }; // 绑定原Recorder的事件 recorder.addEventListener('dataavailable', sendBlob); recorder.start(1000); // 需替换轨道时的流程 async function replaceTrackAndResume() { // 暂停原录制并获取最后一段数据 recorder.pause(); recorder.requestData(); // 等待最后一段数据发送完成 await new Promise(resolve => { recorder.addEventListener('dataavailable', resolve, { once: true }); }); // 停止原Recorder recorder.stop(); // 替换轨道 videoStream.removeTrack(oldVideoTrack); videoStream.addTrack(newVideoTrack); // 创建新Recorder继续录制 recorder = new MediaRecorder(videoStream, {mimeType: "video/webm; codecs=vp9"}); recorder.addEventListener('dataavailable', sendBlob); recorder.start(1000); } // 调用替换函数 replaceTrackAndResume();
方法二:事后用工具修复WebM文件(适合非实时场景)
如果必须复用原Recorder完成录制,可以在所有录制结束后,用ffmpeg重新生成包含完整轨道元数据的WebM文件:
ffmpeg -i file.webm -c copy fixed_file.webm
ffmpeg会重新梳理文件的轨道信息,修复播放器无法识别后续片段的问题。
内容的提问来源于stack exchange,提问作者Biki Deka
相关产品推荐
相关产品推荐

