VideoDecoder.configure()必须显式传入codec和codedWidth/codedHeight,否则解码静默失败;codec需精确匹配(如"avc1.42e01e"),大小写敏感;codedWidth/codedHeight为偶数且≥显示尺寸;VideoFrame须立即close防OOM;MP4需解封装提取sample再构EncodedVideoChunk。

VideoDecoder.configure() 必须传 codec 和 codedWidth/codedHeight
解码器初始化失败、decode() 静默不回调、控制台无报错但帧不出——八成是 configure() 漏了关键参数。浏览器不会从 EncodedVideoChunk 自动推断编码格式或分辨率,必须显式声明。
-
codec字符串要精确匹配(如"avc1.42e01e"),大小写敏感,不能简写为"avc1"或省略 profile-level-id;可用MP4Box.js解析 MP4 的track.codec获取真实值 -
codedWidth和codedHeight是编码流分辨率(不是 displayWidth/displayHeight),必须为偶数,且 ≥ 实际显示宽高;常见错误是直接填 canvas 宽高,结果解码失败 - 若视频存在分辨率切换(如自适应流),必须在切换前调用
configure()重配,否则后续帧 decode 报InvalidStateError
VideoFrame 必须手动 close(),否则几秒就 OOM
每个由 VideoDecoder.output 返回的 VideoFrame 都绑定 GPU 或系统内存资源,不释放就会持续累积。这不是可选操作,是硬性要求。
- 不要等“用完再 close”——应在 output 回调里第一时间调用
frame.close(),哪怕你接下来还要画到 canvas 或转ImageBitmap - 若需多处使用同一帧(如同时渲染 + WebAssembly 分析),必须先
frame.clone(),原帧仍要close();clone()不复制像素数据,只增加引用计数 - 在 Worker 中处理时,
VideoFrame不能直接 postMessage 传递,需先transferToImageBitmap()或用createImageBitmap()转成可转移对象
MP4 文件不能直接喂给 VideoDecoder
把整个 MP4 的 ArrayBuffer 当作编码帧传给 decode(),必然失败。VideoDecoder 只认标准的 EncodedVideoChunk,而 MP4 是容器格式,含 moov、mdat 等 box 结构。
- 必须用
MP4Box.js或类似工具解析 MP4,提取videoTrack.samples;每个sample.data才是一段有效编码帧(NALU) -
EncodedVideoChunk.timestamp必须用sample.cts(composition time stamp),单位是微秒;别用sample.dts,否则时间轴错乱 - 首帧必须是 key 帧(
sample.isSync === true),且其data需包含 SPS/PPS(H.264)或 AV1 Sequence Header(AV1),否则解码器卡在"unconfigured"
渲染黑屏?大概率没读 displayWidth/displayHeight
直接用 frame.width/frame.height 创建 OffscreenCanvas 或贴图,会导致拉伸、裁剪甚至全黑。WebCodecs 输出的解码尺寸常带 padding(如 1920×1088),而实际画面只占其中一部分。
立即学习“前端免费学习笔记(深入)”;
- 务必读取
frame.displayWidth和frame.displayHeight作为渲染区域尺寸,它们来自 SPS 中的pic_width_in_mbs_minus1等字段,反映真实显示范围 - 用 Canvas 2D 渲染时:
ctx.drawImage(frame, 0, 0, frame.displayWidth, frame.displayHeight) - 用 WebGL 时:传给
texImage2D()前,确保纹理尺寸与displayWidth/displayHeight一致,否则采样偏移



















