阶段 8 · 采集编码进阶28 分钟
WebCodecs:直接面对帧、队列与编解码器
VideoFrame、Encoder Queue 与显式资源释放
创建并检查 VideoFrame,理解 WebCodecs 为何比媒体元素更底层,以及队列背压与 close() 的重要性。
LEARNING GOALS
先明确本课目标
1
从 Canvas 创建 VideoFrame
2
读取帧尺寸、时间戳与颜色信息
3
理解编码队列背压和 close()
MENTAL MODEL · 再建立心智模型
HTMLMediaElement 交付完整播放器,WebCodecs 交付编解码零件;你得到更直接的帧控制,也必须自己负责容器、队列、时间戳和资源回收。
MINIMAL EXAMPLE
一个普通 JavaScript 对象为什么必须手动 close?
VideoFrame 可能引用解码器表面、GPU 纹理或大块像素内存;垃圾回收何时发生不可预测,close() 能在处理完成后立即释放底层资源引用。
javascriptconst frame = new VideoFrame(canvas, {
timestamp: Math.round(performance.now() * 1000),
});
context.drawImage(frame, 0, 0);
console.log(frame.displayWidth, frame.displayHeight);
frame.close();- 创建带时间戳的帧 WebCodecs 时间戳通常以微秒表达,必须来自明确时间轴。
- 完成同步消费 帧可作为 Canvas 图像源,也可送入 VideoEncoder。
- 立即释放资源 消费完成就 close,不要等待不确定的垃圾回收。
逐帧循环拥有清晰的资源边界,长时间运行也不会因为遗留帧引用持续增加内存压力。
OPTIONAL · 按需查阅完整术语表与概念边界遇到陌生术语时再展开,不打断主线实验。
展开⌄
音视频基础Codec把原始音视频压缩成编码数据并负责反向解码的算法与实现,例如 Opus、AV1、H.264。音视频基础Video Frame带尺寸、时间戳和颜色信息的一张视频画面,可来自解码器、视频元素、Canvas 或 WebCodecs。音视频基础WebCodecs向 JavaScript 暴露原始帧、编码块与音视频编解码队列的底层 API,不负责媒体容器解析与封装。音视频基础Backpressure当帧生产速度超过处理或编码速度时,用等待、降帧或降质限制队列继续增长的控制机制。音视频基础Media Chunk录制器或编码器分批交付的一段媒体数据;多个 Chunk 需保持顺序并结合容器或协议信息才能组成可使用的连续媒体。音视频基础EncodedVideoChunkWebCodecs 中承载一段已编码视频字节、时间戳、时长和关键帧类型的对象,不包含容器轨道结构。音视频基础Encoder QueueWebCodecs 编码器尚未处理完的输入帧队列;encodeQueueSize 上升表示生产速度超过消费速度,需要背压或降载。音视频基础closeVideoFrame、AudioData 等 WebCodecs 资源显式释放底层媒体内存或硬件表面的操作;使用完应尽快调用。
LIVE EXPERIMENT · 先获得反馈
边改边运行
浏览器加载后会激活代码编辑器、独立运行环境与实时输出。
本课挑战
实现一个带队列上限的 Canvas → VideoEncoder → Chunk 流水线,并统计被主动丢弃的帧。
回到原理,解释刚才发生了什么
先用结果建立反馈,再按运行流程、核心原理和知识关系逐层深入。
CORE IDEA
核心讲解
Codec 不等于容器
WebCodecs 处理编码帧与原始帧,但不会自动解析 MP4/WebM 容器或完成网络传输。真实应用还需要 Demux/Mux 层。
帧可能持有昂贵资源
VideoFrame 可能引用 CPU 或 GPU 内存。处理完应立即 close;生产速度超过编码速度时,还要根据 encodeQueueSize 做背压。
OPTIONAL · 迁移时查阅Web 与原生实现对照主线实验完成后,再用完整映射处理跨平台或跨 API 迁移。
展开⌄
高层播放器隐藏队列与资源,WebCodecs 把这些责任交还给应用。
WebGL
WebCodecs 暴露原始帧、编码块和队列大小,应用负责背压、时间戳、容器与 close。
WebGPU
媒体元素自动协调解码、缓冲、音画同步、丢帧与资源释放。
先设计背压和资源所有权,再写逐帧循环;这是稳定 WebCodecs 管线的起点。