使用 webcodecs api 直接编码 webgl 帧为 h.264,并手动构建 mp4 容器,是当前浏览器端最高效、原生支持、跨平台(含 android chrome)的视频生成方案。
在 Web 应用中将 WebGL 渲染画面实时录制为 MP4 视频,长期以来受限于性能与兼容性——WASM 版 FFmpeg 体积大、启动慢、移动端耗电高;老旧的第三方 MP4 封装库(如已归档的 wasm-mp4-encoder)缺乏维护,且在现代 Android Chrome(v110+)中因 WebAssembly 线程或内存模型变更而失效。真正高性能、低延迟、可生产落地的解法,是拥抱浏览器原生能力:WebCodecs API + 手动 MP4 muxing。
避免 readPixels 后冗余转换。推荐直接使用 canvas> 元素作为 VideoFrame 输入源(无需 ImageData 中转):
// 假设 yourWebGLCanvas 已渲染完毕
const frame = new VideoFrame(yourWebGLCanvas, {
timestamp: performance.now() * 1000, // μs 精度时间戳
visibleRect: new DOMRect(0, 0, canvas.width, canvas.height)
});⚠️ 注意:确保 Canvas 的 alpha: false(WebGL 上下文创建时设置),否则透明通道会强制启用 BGRA 转换,降低性能。
关键配置决定质量与性能平衡:
const encoder = new VideoEncoder({
output: handleChunk,
error: e => console.error("Encoder error:", e.message)
});
encoder.configure({
codec: "a
vc1.42C01E", // H.264 Baseline Profile Level 3.0 (兼容性最佳)
width: canvas.width,
height: canvas.height,
bitrateMode: "variable",
bitrate: 2_000_000, // 2 Mbps(按需调整)
framerate: 30,
latencyMode: "realtime", // 必选!启用低延迟编码路径
avc: { format: "annexb" } // 输出带 NALU 起始码(00 00 00 01),MP4 muxing 必需
});MP4 本质是“盒子嵌套”结构。最小可播放 MP4 至少需以下原子:
你无需实现全部——可复用成熟轻量库完成核心 muxing:
使用 MP4Box.js 封装示例:
import MP4Box from 'mp4box';
const mp4boxFile = MP4Box.createFile();
mp4boxFile.enableLogging(false);
// 添加 H.264 轨道(传入 SPS/PPS 及编码参数)
const track = mp4boxFile.addTrack("video/h264", {
width: canvas.width,
height: canvas.height,
timescale: 1000,
bitrate: 2_000_000
});
// 在 handleChunk 中注入帧数据
function handleChunk(encodedFrame, metadata) {
if (metadata.decoderConfig) {
// 注入 SPS/PPS(仅首次)
const sps = new Uint8Array(metadata.decoderConfig.description);
mp4boxFile.setVideoTrackMetadata(track.id, sps, null);
}
// 添加帧(自动处理关键帧标记、时间戳)
const sample = {
data: encodedFrame,
pts: encodedFrame.timestamp, // μs
cts: 0,
dts: encodedFrame.timestamp,
is_sync: metadata.keyFrame || false,
duration: 1000 / 30 * 1000 // 30fps → 33333 μs/frame
};
mp4boxFile.addSample(track.id, sample);
}
// 结束后导出 Blob
function exportMP4() {
const buffer = mp4boxFile.flush();
const blob = new Blob([buffer], { type: "video/mp4" });
const url = URL.createObjectURL(blob);
// 下载或播放...
}放弃臃肿的 WASM FFmpeg,拥抱 WebCodecs 是浏览器端视频编码的范式升级。它以原生性能、低延迟、高兼容性,成为 WebGL 录屏、实时可视化导出、Web 游戏录像等场景的首选技术栈。结合 MP4Box.js 这类专业 muxing 库,你能在 200 行核心代码内,构建出媲美桌面软件的 Web 视频生成能力——轻量、可靠、面向未来。