requestvideoframecallback是目前最精准的视频帧同步方案,因其严格对齐视频真实帧率(如30fps约33ms、60fps约16.7ms触发),而非屏幕刷新率或不可控的timeupdate;需手动递归注册、防重入、避免耗时操作,并实测兼容性后降级至timeupdate+帧差检测。

直接用 requestVideoFrameCallback 替代 requestAnimationFrame 驱动视频帧同步绘制,是目前最精准的方案——它在浏览器真正把一帧视频提交给合成器时才触发回调,天然对齐视频输出节奏,而非屏幕刷新率。
为什么 requestVideoFrameCallback 更适合视频帧同步
它不是“大概每秒60次”的估算,而是严格绑定视频真实帧率:30fps 视频约每 33ms 触发一次,60fps 则接近 16.7ms。相比 timeupdate(通常 200–500ms 才触发一次、且与渲染脱钩)和 requestAnimationFrame(对齐屏幕刷新,常为 60Hz,易与视频帧错位),它是做逐帧绘制、分析、滤镜或视差拼接的可靠时基。
必须手动递归注册,否则只执行一次
这个 API 设计为单次回调。注册后仅在下一帧触发,之后自动注销。常见错误是写成一次性调用,结果只拿到第一帧就停了。
- 正确做法是在回调函数内部立刻再次调用
video.requestVideoFrameCallback(callback) - 建议加布尔标记防重入,避免异常导致重复注册
- 不要在回调里做耗时操作(如大图 drawImage、复杂计算),否则会挤压下帧注册窗口,引发丢帧
兼容性不能只靠特征检测,要实测触发
部分 iOS 15.4–15.6 设备虽返回 "requestVideoFrameCallback" in HTMLVideoElement.prototype === true,但回调永不执行,属于“伪支持”。
- 必须发起一次真实调用,并配合超时兜底(例如 200ms 内未触发则判定失败)
- 生产环境推荐 fallback 方案:
timeupdate+ 帧差检测(监控video.currentTime变化速率) - 稳定支持版本:Chrome 94+、Edge 94+、Firefox 114+;iOS 需 Safari 16.4+;Android WebView 需 Chrome 100+ 内核
搭配 Canvas 渲染时的关键细节
所有 Canvas 必须显式设置 width 和 height 属性(如 width="1920" height="1080"),不能只靠 CSS 缩放。否则默认 300×150 像素被拉伸,必然插值模糊。
- 隐藏主
<video></video>元素(position: fixed; visibility: hidden; z-index: -1),仅作解码源 - 每个
<canvas></canvas>用ctx.drawImage(video, ...)复制当前帧,再叠加图形或偏移定位 - 若实现三栏视差效果,用
translateX微调左右 Canvas 起始位置,实现视觉无缝拼接
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











