RecordRTC技术问询:能否无需停止录制即可保存Blob数据?
Hey there! I get what you're trying to do—you want to save video segments every minute with RecordRTC without stopping the ongoing recording, right? The default approach of calling stopRecording() to fetch the blob does interrupt the session, so let's walk through two practical solutions to pull this off.
方法一:使用原生MediaRecorder(推荐)
RecordRTC under the hood often uses the browser's native MediaRecorder API, which has a built-in feature for periodic segment generation. You can use this directly to get blobs every minute without pausing your recording:
let mediaStream; async function initRecording() { // 获取媒体流 mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); // 初始化MediaRecorder,指定视频格式 const mediaRecorder = new MediaRecorder(mediaStream, { mimeType: 'video/webm' }); // 每隔1分钟(60000毫秒)触发一次数据可用事件 mediaRecorder.start(60 * 1000); // 当有片段数据可用时,处理保存/上传 mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) { // 避免空blob const fileName = generateRandomString() + '.webm'; const file = new File([event.data], fileName, { type: 'video/webm' }); // 调用你的上传函数 uploadFile(file, (responseText) => { console.log(responseText); }); } }; // 录制停止时清理资源 mediaRecorder.onstop = () => { mediaStream.getTracks().forEach(track => track.stop()); // 替代废弃的mediaStream.stop() }; } // 封装上传逻辑(兼容你原有的xhr函数) function uploadFile(file, callback) { const xhr = new XMLHttpRequest(); xhr.open('POST', '/uploadFile'); xhr.onload = () => { if (xhr.status === 200) { callback(xhr.responseText); } }; const formData = new FormData(); formData.append('file', file); xhr.send(formData); } // 你的随机字符串生成函数 function generateRandomString() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); }
为什么推荐这个方法?
- 原生API支持,性能更优,不需要额外创建多个RecordRTC实例
- 自动处理分段逻辑,无需手动管理定时器和临时录制实例
- 避免了克隆媒体流可能带来的资源占用问题
方法二:RecordRTC克隆流+临时录制实例
如果你必须依赖RecordRTC的特定功能(比如自定义编码、滤镜等),可以通过克隆媒体流创建临时录制实例来保存分段视频,同时保持主录制不中断:
let mainRecorder; let mediaStream; const segmentTimers = []; async function initRecording() { mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); // 初始化主录制实例(持续录制,如果你需要完整的长视频) mainRecorder = RecordRTC(mediaStream, { type: 'video', mimeType: 'video/webm' }); mainRecorder.startRecording(); // 立即启动第一个片段录制,之后每隔1分钟启动下一个 startSegmentRecording(); setInterval(startSegmentRecording, 60 * 1000); } function startSegmentRecording() { // 克隆当前媒体流,避免影响主录制 const clonedStream = mediaStream.clone(); // 创建临时录制实例处理当前片段 const segmentRecorder = RecordRTC(clonedStream, { type: 'video', mimeType: 'video/webm' }); segmentRecorder.startRecording(); // 1分钟后停止片段录制并上传 const timer = setTimeout(() => { segmentRecorder.stopRecording(() => { const blob = segmentRecorder.getBlob(); const fileName = generateRandomString() + '.webm'; const file = new File([blob], fileName, { type: 'video/webm' }); // 上传片段 uploadFile(file, (responseText) => { console.log(responseText); // 清理克隆流的资源,避免内存泄漏 clonedStream.getTracks().forEach(track => track.stop()); }); }); }, 60 * 1000); segmentTimers.push(timer); } // 复用之前的uploadFile和generateRandomString函数
注意事项
- 如果不需要完整的主视频,可以删除
mainRecorder相关代码,只保留分段录制逻辑 - 记得清理临时定时器和克隆流的资源,避免浏览器内存占用过高
- 克隆媒体流会占用额外的系统资源,若长时间录制,建议监控性能
最后补充
无论是哪种方法,都要确保测试不同浏览器的兼容性(比如Safari对WebM格式的支持有限,可能需要调整MIME类型为video/mp4)。
内容的提问来源于stack exchange,提问作者Saurabh Sharma

