一、先认识视频 Blob 的真面目
{
size: 1024000, // 字节大小
type: "video/webm", // MIME类型
[Symbol(type)]: "Blob"
}
Blob 本身只是一个二进制容器,它不会直接告诉你分辨率、帧率,但这些信息其实都编码在它的内部数据里。
一个典型的视频 Blob,内部至少包含三层结构:
-
容器格式(Container)
- WebM → EBML 头、Segment、Cluster
- MP4 → ftyp、moov、mdat 等 atom
- OGG → OggS 页头 + Theora
-
编码后的视频帧
- I 帧(关键帧)
- P / B 帧(预测帧)
- 每一帧都带时间戳,用于音画同步
-
编码参数
- 编码器: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 0x45→ EBML Header 的起始标识0x6D 0x61 0x74 0x72 0x6F 0x73 0x6B 0x61→ ASCII 解码后是:
也就是 Matroska(WebM 的基础容器格式)m a t r o s k a
这说明:这个 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 + VP9video/x-matroska;codecs=avc1→ Matroska + H.264
四、你可以主动控制的编码参数(VP9 实战)
如果你用 getUserMedia 或 MediaRecorder 生成视频,其实可以“定制”编码器。
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 / 直播推流优化
浙公网安备 33010602011771号