Chrome中隐藏HTMLCanvasElement经Web Worker的OffscreenCanvas绘制时捕获流卡顿是否正常
问题结论&已知状态
这是Chrome的已知未修复缺陷,根源是Chrome的渲染管道中,隐藏状态的主canvas绑定OffscreenCanvas+Worker绘制时,captureStream()的帧捕获触发器不会被Worker线程的绘制操作主动触发,因为默认只有主线程的canvas绘制、且canvas处于可见状态时才会主动推送新帧到捕获流。
可用解决方案
以下两种方案都可以在保留OffscreenCanvas Worker绘制能力的前提下解决流不刷新问题,性能损耗远低于回退到主线程绘制的方案:
- 方案1:主线程触发空绘制(跨浏览器兼容)
无需改动Worker侧绘制逻辑,只需在主线程中对绑定了captureStream()的原始canvas,按期望帧率定期执行无视觉影响的空绘制,即可主动触发流刷新,参考代码:
该方案性能损耗低于1%,不会干扰OffscreenCanvas的正常绘制结果。// 指向你调用captureStream方法的原始HTMLCanvasElement实例 const mainCanvas = document.querySelector('#source-canvas'); const mainCtx = mainCanvas.getContext('2d'); // 60FPS场景下每16ms触发一次,可按需调整间隔 setInterval(() => { mainCtx.fillStyle = 'rgba(0,0,0,0)'; mainCtx.fillRect(0, 0, 1, 1); }, 16); - 方案2:手动控制流帧推送(性能最优)
初始化捕获流时指定手动控帧模式,Worker每次绘制完成后发消息通知主线程调用Chrome提供的非标准requestFrame()方法推送新帧,参考代码:
主线程代码:
Worker侧每次绘制完成后发送通知即可:// 传0表示关闭自动帧推送,由开发者手动控制 const canvasStream = mainCanvas.captureStream(0); worker.onmessage = (e) => { if (e.data.type === 'draw-complete') { canvasStream.requestFrame(); } };
该方案同步开销极低,性能几乎无损耗,但仅支持Chromium内核浏览器。// OffscreenCanvas绘制逻辑执行完成后 self.postMessage({ type: 'draw-complete' });
内容的提问来源于stack exchange,提问作者Raphael Royer-Rivard
相关产品推荐
相关产品推荐

