一、先认识视频 Blob 的真面目

{
  size: 1024000,       // 字节大小
  type: "video/webm",  // MIME类型
  [Symbol(type)]: "Blob"
}

Blob 本身只是一个二进制容器,它不会直接告诉你分辨率、帧率,但这些信息其实都编码在它的内部数据里。

一个典型的视频 Blob,内部至少包含三层结构:

  1. 容器格式(Container)

    • WebM → EBML 头、Segment、Cluster
    • MP4 → ftyp、moov、mdat 等 atom
    • OGG → OggS 页头 + Theora
  2. 编码后的视频帧

    • I 帧(关键帧)
    • P / B 帧(预测帧)
    • 每一帧都带时间戳,用于音画同步
  3. 编码参数

    • 编码器:VP8 / VP9 / H264 / AV1
    • 分辨率、帧率、码率、色彩空间

二、直接看二进制:WebM 的文件头长什么样

很多人不知道的是:Blob 的前几十个字节,就是容器格式的“身份证”

FileReader 把它读出来:

const reader = new FileReader();
reader.onload = function () {
  const arrayBuffer = reader.result;
  const header = new Uint8Array(arrayBuffer, 0, 32);
  console.log('文件头:', header);
};
reader.readAsArrayBuffer(videoBlob);

打印结果(10 进制):

26, 69, 223, 163, 163, 66, 134, 129, 1, 66, 247, 129, 1,
66, 242, 129, 4, 66, 243, 129, 8, 66, 130, 136, 109, 97, 116, 114, 111, 115, 107, 97

这些数字说明了什么?

  • 0x1A 0x45EBML Header 的起始标识
  • 0x6D 0x61 0x74 0x72 0x6F 0x73 0x6B 0x61 → ASCII 解码后是:
    m a t r o s k a
    
    也就是 Matroska(WebM 的基础容器格式)

这说明:这个 Blob 是一个标准的 WebM 文件。


三、不读二进制,也能拿到的视频元数据

虽然二进制分析很硬核,但日常开发中,其实有更简单的办法:用 <video> 元素。

async function getVideoMetadata(blob) {
  return new Promise((resolve) => {
    const video = document.createElement('video');
    video.preload = 'metadata';

    video.onloadedmetadata = () => {
      resolve({
        duration: video.duration,
        width: video.videoWidth,
        height: video.videoHeight,
        mimeType: blob.type,
        size: blob.size
      });
    };

    video.src = URL.createObjectURL(blob);
  });
}

调用:

const metadata = await getVideoMetadata(videoBlob);
console.log(metadata);

可能得到:

{
  "duration": Infinity,
  "width": 1280,
  "height": 720,
  "mimeType": "video/x-matroska;codecs=avc1",
  "size": 389437
}

几个值得注意的点

  • duration: Infinity
    常见于还在录制的 MediaRecorder 流,或者尚未写入 duration 的 WebM 片段
  • mimeType 是容器 + 编码的组合
    • video/webm;codecs="vp9" → WebM + VP9
    • video/x-matroska;codecs=avc1 → Matroska + H.264

四、你可以主动控制的编码参数(VP9 实战)

如果你用 getUserMediaMediaRecorder 生成视频,其实可以“定制”编码器。

MIME 类型怎么看?

video/webm;codecs="vp9"

含义很直白:

  • 容器:WebM
  • 视频编码:VP9

高级约束示例(VP9 专用)

const advancedConstraints = {
  video: {
    width: 1920,
    height: 1080,
    frameRate: 30,
    advanced: [
      {
        video: {
          mimeType: 'video/webm',
          codecs: 'vp9',
          bitrateMode: 'variable', // 或 constant
          latencyMode: 'realtime',
          profile: '0',    // 8bit, 4:2:0
          level: '4.1',
          framerate: { exact: 30 }
        }
      }
    ]
  }
};

这些参数有什么用?

参数 作用
bitrateMode 直播建议 realtime + variable
profile 决定色彩位深和色度抽样
level 解码端兼容性
framerate 避免浏览器自动降帧

五、一句话总结

  • Blob 不是黑盒:它里面是完整的视频文件
  • 前 32 字节 = 容器身份证:WebM 是 EBML / Matroska
  • 元信息有两种拿法
    • 硬核:读 ArrayBuffer
    • 实用:<video>.onloadedmetadata
  • 编码不是浏览器随机选的:通过 mimeType + advanced,你可以控制 VP9/H264 的行为

如果你在做:

  • 前端录屏
  • 视频上传前的校验
  • WebRTC / 直播推流优化

这些知识基本都是必踩的点。

posted on 2026-08-13 15:24  羽丫头不乖  阅读(2)  评论(0)    收藏  举报