requestvideoframecallback 是同步回调api,需手动递归注册以维持帧流,避免丢帧;支持微秒级时间戳对齐、硬件加速yuv转换及frame.close()内存管理,但存在ios伪支持风险,须实测触发并备选timeupdate兜底。

requestVideoFrameCallback 不是异步 Promise API,它本身是同步回调机制,但能与异步环境(如 Web Worker、OffscreenCanvas、WebGL 渲染管线)高效协同,关键在于避免主线程阻塞、精准对齐帧节奏、及时释放资源。
必须手动递归注册,维持帧流连续性
该 API 默认只触发一次。若未在回调内立刻重注册,后续帧将完全丢失。
- 写法错误示例:
video.requestVideoFrameCallback(cb)—— 仅执行一帧 - 正确写法:在回调第一行就调用
video.requestVideoFrameCallback(cb),形成稳定链式调用 - 加防重入保护更稳妥:用布尔标志位防止异常导致重复注册(例如上一帧处理未完成时又收到新帧)
从 VideoFrame 安全提取像素数据,避开主线程瓶颈
VideoFrame 默认为 YUV 格式(format: "yuv420"),不能直接用于 canvas 或 WebGL;JS 层做 YUV→RGBA 转换会严重拖慢主线程。
- 优先使用
frame.copyTo(target, { format: 'rgba' }),浏览器内部启用硬件加速转换 - 目标 buffer 尺寸必须严格匹配
frame.displayWidth和frame.displayHeight(注意不是video.videoWidth,后者不含 letterboxing 缩放影响) - 若需 GPU 端实时处理,应跳过 copyTo,直接用 WebGL 2 的
copyTextureToBuffer+ 自定义着色器,在 GPU 内完成 YUV 解码与滤镜合成 -
务必调用
frame.close(),否则 VideoFrame 对象持续占用解码内存,数秒内即可引发明显卡顿或崩溃
与异步任务协调:不阻塞、不丢帧、带时间戳对齐
回调中禁止执行耗时操作(如大图 drawImage、复杂 JS 计算、同步 fetch),否则会延迟下帧注册,造成丢帧或帧率崩塌。
- 图像处理逻辑建议移交 Web Worker:将
frame.timestamp和像素 buffer 传入,处理完再 postMessage 回主线程 - UI 同步渲染应以回调参数
now(DOMHighResTimeStamp)和metadata.presentationTime为唯一时基,而非 requestAnimationFrame 的时间 - 需要测帧间隔或检测卡顿时,直接用连续两帧的
metadata.presentationTime相减,精度达微秒级,比timeupdate可靠得多
兼容性兜底与真实可用性验证
仅检测 "requestVideoFrameCallback" in HTMLVideoElement.prototype 不够——部分 iOS 设备存在“伪支持”:API 存在但永不触发回调。
- 实测触发才是硬标准:注册后启动视频播放,配合
setTimeout200ms 超时判断是否真正进入回调 - iOS 最低稳定版本为 15.4,但 15.4–15.6 仍有静默失败风险,生产环境建议 fallback 到
timeupdate + currentTime 差分检测组合方案 - Chrome 114+ / Edge 114+ / Firefox 125+ 支持完整且稳定;Safari 当前无支持计划










