offscreencanvas 必须由主线程通过 transfercontroltooffscreen() 创建,worker 无法自行实例化;多路视频流需独立 offscreencanvas 和 worker(或共享 worker + streamid 路由);帧数据须预转 imagebitmap 后传输;渲染与分析结果分层回传,避免阻塞。

可以,但必须由主线程移交控制权,Worker 本身不能创建 OffscreenCanvas;多个视频流需分别绑定独立的 OffscreenCanvas 实例,并用独立 Worker 或共享 Worker + 消息路由管理。
主线程:为每个视频流准备离屏画布
每个视频流对应一个真实 <canvas></canvas> 元素(可隐藏),调用 .transferControlToOffscreen() 获取 OffscreenCanvas 实例。注意:
– 不要复用同一个 canvas 或 OffscreenCanvas 处理多路流,避免渲染冲突
– 若视频流数量动态变化,建议预建池(如 4–8 个 canvas 元素),按需分配与移交
– 移交后,该 canvas 在主线程中不可再用于 drawImage 或 getContext,否则报错
Worker 线程:按流隔离渲染与分析逻辑
推荐两种组织方式:
– 多 Worker 方案:每路流配一个专用 Worker,接收对应 OffscreenCanvas + 视频帧数据(如 ImageBitmap),各自执行解码→绘制→AI 推理→标注绘制
– 单 Worker 多上下文方案:Worker 收到多个 OffscreenCanvas 后,为每路维护独立 WebGL 上下文(需 { desynchronized: true })和纹理对象;通过 message 中的 streamId 路由帧数据
关键点:
– 所有视频帧必须先在主线程转成 ImageBitmap(用 createImageBitmap(videoFrame)),再 postMessage 传入 Worker
– Worker 中直接用 gl.texImage2D(..., imageBitmap) 上传,避免 fetch/Blob 解码开销
– 分析结果(如检测框坐标、类别)应精简为纯 JS 对象(非 DOM 或 canvas),通过 postMessage 回传
实时回传与合成显示
Worker 不直接操作页面,画面同步靠两层协作:
– 低频视觉输出:对每路流,Worker 定期调用 offscreenCanvas.transferToImageBitmap() 截帧(建议每 2–3 帧一次),发送 bitmap 到主线程;主线程用 ctx.drawImage(bitmap, x, y) 合成到主显示 canvas
– 高频分析叠加:主线程收到检测结果后,用 2D ctx 在对应区域动态绘制框线/文字(fillText 可用),不依赖 Worker 渲染帧,降低延迟
注意:
– transferToImageBitmap() 是耗时操作,频繁调用会拖慢 Worker 帧率
– 若某路流静止(如无运动),可暂停截帧,只传分析结果,节省带宽与 GPU 资源
避坑要点
常见失败原因:
– 忘记在 postMessage 第二个参数中传入 transfer list(如 [offscreen]),导致 Worker 收到 null 上下文
– 在 Worker 中尝试 new OffscreenCanvas() → 报 Illegal constructor
– Safari 当前(2026 年 4 月)仍不支持 OffscreenCanvas + WebGL,多流分析需降级为 2D 渲染或禁用该浏览器
– 视频帧未提前转 ImageBitmap,直接传 videoElement 或 Blob → Worker 中 texImage2D 静默失败











