WebCodecs API 实战:浏览器端低延迟音视频编解码
技术架构(更新于 2026年6月14日)
浏览器音视频处理的演进
| 方案 | 延迟 | 帧级控制 | 编解码 | 适用场景 |
|---|---|---|---|---|
<video> + MSE |
2-5s | ❌ | 封装格式 | 播放、流媒体 |
| FFmpeg.wasm | 1-3s | ✅ | 完整 | 转码(但体积大 30MB+) |
| WebCodecs | <100ms | ✅ | 原生 | 实时处理、低延迟转码 |
WebCodecs 提供对浏览器内置编解码器的直接访问,无需 WASM 封装,延迟降低 10-50 倍。
核心对象概览
VideoFrame ←→ VideoEncoder ←→ EncodedVideoChunk
↓ 网络传输 / 存储
AudioData ←→ AudioEncoder ←→ EncodedAudioChunk
↓
VideoFrame ←→ VideoDecoder ←→ EncodedVideoChunk
AudioData ←→ AudioDecoder ←→ EncodedAudioChunk
VideoFrame:零拷贝帧操作
// 从 canvas 创建 VideoFrame(零拷贝)
const frame = new VideoFrame(canvas, { timestamp: performance.now() * 1000 });
// 从 ImageBitmap 创建
const bitmap = await createImageBitmap(videoElement);
const frame2 = new VideoFrame(bitmap, { timestamp: 0 });
// 访问帧元数据
console.log(frame.width, frame.height, frame.duration, frame.timestamp);
// 用完必须关闭(否则 GPU 内存泄漏)
frame.close();
关键:VideoFrame 持有 GPU 纹理引用,必须调用
close()释放,否则会导致 GPU 内存泄漏。
VideoEncoder:视频编码
const encoder = new VideoEncoder({
output: (chunk, metadata) => {
// 编码后的数据块
const data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
handleEncodedChunk(chunk.type, data, chunk.timestamp, metadata);
},
error: (e) => console.error('编码错误:', e),
});
encoder.configure({
codec: 'avc1.64001E', // H.264 Main Profile
width: 1920,
height: 1080,
bitrate: 5_000_000, // 5 Mbps
framerate: 30,
});
// 编码一帧
encoder.encode(frame, { keyFrame: true });
frame.close();
支持的编解码器
| 编解码器 | codec 字符串 | 特点 |
|---|---|---|
| H.264 | avc1.64001E |
最广泛兼容 |
| H.265 | hev1.1.6.L93.B0 |
压缩率高 40%,兼容性差 |
| VP8 | vp8 |
WebM 格式 |
| VP9 | vp9 |
YouTube 默认 |
| AV1 | av01.0.01M.08 |
下一代,压缩率最高 |
VideoDecoder:视频解码
const decoder = new VideoDecoder({
output: (frame) => {
// 解码后的 VideoFrame
ctx.drawImage(frame, 0, 0);
frame.close(); // 必须关闭
},
error: (e) => console.error('解码错误:', e),
});
decoder.configure({
codec: 'avc1.64001E',
codedWidth: 1920,
codedHeight: 1080,
});
// 解码编码数据
const chunk = new EncodedVideoChunk({
type: isKeyFrame ? 'key' : 'delta',
timestamp: timestamp,
data: encodedData,
});
decoder.decode(chunk);
AudioEncoder / AudioDecoder
const audioEncoder = new AudioEncoder({
output: (chunk) => {
const data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
handleAudioChunk(data, chunk.timestamp);
},
error: (e) => console.error(e),
});
audioEncoder.configure({
codec: 'aac',
sampleRate: 48000,
numberOfChannels: 2,
bitrate: 128000,
});
// 编码音频数据
const audioData = new AudioData({
format: 'f32-planar',
sampleRate: 48000,
numberOfFrames: 1024,
numberOfChannels: 2,
timestamp: 0,
data: float32Array,
});
audioEncoder.encode(audioData);
audioData.close();
实战:视频格式转码管线
工具库 视频转换 的核心转码流程:
async function transcodeVideo(inputChunks: EncodedVideoChunk[], config: TranscodeConfig) {
const decodedFrames: VideoFrame[] = [];
// 1. 解码源视频
const decoder = new VideoDecoder({
output: (frame) => decodedFrames.push(frame),
error: (e) => { throw e; },
});
decoder.configure(inputConfig);
for (const chunk of inputChunks) {
decoder.decode(chunk);
}
await decoder.flush();
// 2. 编码为目标格式
const encoder = new VideoEncoder({
output: (chunk) => muxer.addChunk(chunk),
error: (e) => { throw e; },
});
encoder.configure(config.outputCodec);
for (const frame of decodedFrames) {
encoder.encode(frame);
frame.close();
}
await encoder.flush();
return muxer.finalize();
}
与 MSE 对比:低延迟场景
| 指标 | MSE (MediaSource) | WebCodecs |
|---|---|---|
| 首帧延迟 | 2-5s(缓冲策略) | <100ms |
| 帧级控制 | ❌ 只能 appendBuffer | ✅ 逐帧编解码 |
| 实时处理 | ❌ 需额外封装 | ✅ 原生支持 |
| 内存占用 | 高(缓冲队列) | 低(逐帧处理) |
| 适用 | 视频播放 | 实时通信、转码、分析 |
性能实测:视频压缩场景
对 1080p 30fps 60s 视频做 H.264→H.265 转码:
| 方案 | 转码耗时 | 输出体积 | 延迟 |
|---|---|---|---|
| FFmpeg.wasm | 180s | 12MB | 3s(WASM 初始化) |
| WebCodecs | 45s | 12MB | <100ms |
WebCodecs 利用浏览器原生编解码器,速度提升 4 倍,且无需下载 30MB+ 的 WASM。
常见问题
WebCodecs 支持哪些容器格式?
WebCodecs 只处理裸编解码数据(raw chunks),不处理容器封装。需要配合 mp4-muxer 或 webm-muxer 等库封装为 MP4/WebM。
如何获取视频的编码数据?
可通过 MP4 demuxer(如 mp4box.js)解封装 MP4 文件,提取 EncodedVideoChunk 后喂给 Decoder。
VideoFrame 可以跨 Worker 传输吗?
可以。VideoFrame 实现了 Transferable,可通过 postMessage(frame, [frame]) 零拷贝传输到 Worker 中处理。
总结
WebCodecs API 为浏览器提供了对音视频编解码器的直接访问,实现零拷贝帧处理和 <100ms 延迟的编解码。VideoEncoder/Decoder 处理视频,AudioEncoder/Decoder 处理音频,VideoFrame/AudioData 提供帧级操作。配合 demuxer/muxer 库,可在浏览器端构建完整的低延迟视频转码管线。
本站提供浏览器本地工具,免注册即可试用 →
#WebCodecs#视频编解码#AudioData#VideoFrame#低延迟