You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

加载MediaRecorder旧Blob时MediaSource SourceBuffer报错问题

解决思路:让MediaRecorder生成的Blob可独立播放并支持回溯

1. 先搞定MediaRecorder的片段完整性问题

MediaRecorder默认录出的是增量媒体片段,没有完整的文件容器元数据(比如MP4的核心结构信息),单独播放自然无法解析。试试这么处理:

  • 每次分段录制结束时,必须调用MediaRecorder.stop(),此时dataavailable事件返回的Blob才带有完整元数据,能独立播放。如果怕直播断流,停录后立刻重启新的Recorder继续:
    let recorder;
    function startNewSegment() {
      if (recorder) recorder.stop();
      // 优先用MP4格式,兼容性最强
      recorder = new MediaRecorder(stream, { mimeType: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"' });
      recorder.ondataavailable = (e) => {
        if (e.data.size > 0) {
          // 存储带完整元数据的Blob到IndexedDB
          saveToDB(e.data);
        }
      };
      recorder.start();
      // 示例:每5分钟生成一个独立片段
      setTimeout(startNewSegment, 5 * 60 * 1000);
    }
    

2. 修复IndexedDB存储Blob的序列化坑

直接存Blob到IndexedDB容易出现序列化损坏,取出来的Blob就废了。换成存储ArrayBuffer:

// 存储时转成ArrayBuffer
async function saveToDB(blob) {
  const buffer = await blob.arrayBuffer();
  const db = await openMyDB(); // 自行实现的打开IndexedDB方法
  const tx = db.transaction('recordings', 'readwrite');
  await tx.store.add({ id: Date.now(), data: buffer, type: blob.type });
  await tx.done;
}

// 读取时转回Blob
async function getBlobFromDB(id) {
  const db = await openMyDB();
  const item = await db.get('recordings', id);
  return new Blob([item.data], { type: item.type });
}

3. 回溯播放时彻底重置所有资源

别试图复用旧的MediaSource、SourceBuffer或Video元素,直接全量重建:

async function playBack(id) {
  // 清理旧资源
  if (window.mediaSource) {
    mediaSource.endOfStream();
    window.mediaSource = null;
  }
  const video = document.getElementById('backtrack-video');
  video.src = '';
  video.load();

  // 新建MediaSource并关联Video
  const mediaSource = new MediaSource();
  window.mediaSource = mediaSource;
  video.src = URL.createObjectURL(mediaSource);
  
  mediaSource.addEventListener('sourceopen', async () => {
    const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
    const blob = await getBlobFromDB(id);
    const buffer = await blob.arrayBuffer();
    sourceBuffer.appendBuffer(buffer);
    
    sourceBuffer.addEventListener('updateend', () => {
      if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
        mediaSource.endOfStream();
        video.play();
      }
    });
  });
}

4. 先验证Blob本身的有效性

如果单独加载Blob都不行,先排查Blob是否损坏:

const testVideo = document.createElement('video');
testVideo.src = URL.createObjectURL(你的Blob实例);
testVideo.onloadedmetadata = () => {
  console.log('Blob有效,时长:', testVideo.duration);
};
testVideo.onerror = () => {
  console.error('Blob损坏,无法解析');
};
// 可临时添加到页面查看实际播放效果
document.body.appendChild(testVideo);

另外,尽量避开webm格式,部分浏览器对分段webm的元数据支持较差,优先用MP4更稳妥。


内容的提问来源于stack exchange,提问作者simondx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 16:02:45