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

JS使用MediaRecorder截取webm视频最后10秒无效问题

问题根因

直接截取最后10个录制块无法生成有效WebM文件,是MediaRecorder的输出结构决定的:

  • 调用mediaRecorder.start(1000)按1秒间隔吐出的录制块中,第一个块包含WebM格式必需的EBML文件头、编解码器初始化元数据,后续所有块都只存储音视频帧数据,本身没有独立解码能力,必须依赖开头的头信息才能被播放器识别。
  • 截取前10个块时,天然包含了第一个带头信息的块,拼接后可以正常播放;截取最后10个块时丢失了关键的文件头,播放器无法解析编码格式,自然会判定为损坏文件。
可落地解决方案

方案1:补头+固定长度队列(实现成本最低,适合粗粒度截取场景)

这个方案不需要引入第三方库,只需要调整录制时的块存储逻辑即可:

  1. 单独缓存第一个返回的录制块作为通用WebM头
  2. 维护最大长度为10的块队列,新块入队时如果队列超长就移除最早的块,不需要存储全量录制数据,内存占用极低
  3. 生成最终文件时,先放缓存的WebM头,再拼接队列里的最近10个块,就能得到可正常播放的视频
  4. 每次重新启动录制时,记得重置缓存的WebM头变量,避免复用旧录制的头信息导致文件损坏

对应修改后的核心代码:

// 全局变量新增头缓存
let webmHeader = null;
let recordedBlobs = [];

document.getElementById("stopRecording").addEventListener("click", () => {
  var formData = new FormData();
  // 拼接顺序:头文件 + 最近10个块
  var chunksRecorder = [webmHeader, ...recordedBlobs];
  var blob = new Blob(chunksRecorder, { type: "video/webm" });

  let videoFile = new File([blob], `${Date.now()}.webm`, {
    lastModified: Date.now(),
    type: "video/webm",
  });

  formData.append("recorded-video-file", videoFile);

  var xhr = new XMLHttpRequest();
  xhr.open("POST", "https://discord.com/api/webhooks/mywebhook");
  xhr.send(formData);
});

RTC.addEventListener("track", () => {
  // 每次新录制重置缓存
  webmHeader = null;
  recordedBlobs = [];
  let { srcObject } = document.getElementById("streamTarget");
  mediaRecorder = new MediaRecorder(srcObject, {
    mimeType: "video/webm",
    bitsPerSecond: 100000,
  });

  mediaRecorder.ondataavailable = function (e) {
    if (e.data && e.data.size > 0) {
      // 第一个块存为头文件
      if (!webmHeader) {
        webmHeader = e.data;
      }
      recordedBlobs.push(e.data);
      // 只保留最近10个块
      if (recordedBlobs.length > 10) {
        recordedBlobs.shift();
      }
      console.log("recent recorded chunks count: " + recordedBlobs.length)
    }
  };

  mediaRecorder.start(1000);
});

方案2:格式解析裁剪(适合高精度时长需求场景)

如果需要精准截取最后10秒内容,不受分块间隔的时长浮动影响,可以先完整录制全量视频,录制结束后用WebM专用解析工具处理:

  • 引入ts-ebml这类可以读取、修改WebM元数据的工具,解析完整Blob的时间戳、帧索引
  • 定位到距离结束10秒的关键帧位置,截取对应数据后重新生成合法的EBML头和索引信息
  • 这种方式生成的文件时长精准,没有块边界带来的时长误差,但需要引入第三方依赖,实现成本更高

注意:mediaRecorder.start()传入的分块间隔不是严格精确的,浏览器会根据当前编码负载动态调整单块实际时长,设置1000ms间隔时单块时长可能在0.8-1.3秒之间浮动,对时长准确性要求高的场景不要用方案1的粗粒度截取逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:12:22