有没有一种方法可以将视频标签/媒体流的视频数据发送到离屏画布(OffscreenCanvas)?

5
基本上,我希望能够有效地执行相同的代码:

const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

const draw = () => {
  context.drawImage(video, 0, 0);
  requestAnimationFrame(draw);
}

video.onplay = () => {
  requestAnimationFrame(draw);
}

只能使用离屏画布。我可以将图像通过消息发送到离屏画布所在的工作线程,但无法发送视频,因为它直接连接到 HTMLElement。目前是否有一种方法可以在离屏画布中仍然呈现视频数据或 MediaStream


1
你最终解决了这个问题吗?我也有同样的问题。 - hoodsy
1个回答

21

您可以通过对脚本进行以下更改,将视频的帧发送到Web Worker中的OffscreenCanvas:

const worker = new Worker('my-worker.js');
const video = document.getElementById('video');
const stream = video.captureStream();
const [track] = stream.getVideoTracks();
const imageCapture = new ImageCapture(track);
const canvas = document.getElementById('canvas');
const offscreen = canvas.transferControlToOffscreen();

worker.postMessage({ offscreen }, [offscreen]);

const draw = () => {
  imageCapture.grabFrame().then(imageBitmap => {
    worker.postMessage({ imageBitmap }, [imageBitmap]);
  });

  requestAnimationFrame(draw);
};

video.onplay = () => {
  requestAnimationFrame(draw);
};

我的工作人员.js

let canvas;
let context;

addEventListener('message', event => {
  if (event.data.offscreen) {
    canvas = event.data.offscreen;
    context = canvas.getContext('2d');
  } else if (event.data.imageBitmap && context) {
    context.drawImage(event.data.imageBitmap, 0, 0);
    // do something with frame
  }
});

参考资料


谢谢回复,但我想找到一种通过使用离屏画布来卸载requestAnimationFrame调用的方法,因为当标签被模糊时,浏览器会对其进行限制。这解决了我的原始问题,但是否有任何方法可以在没有计时器/ requestAnimationFrame调用的情况下将视频传输到离屏画布? - Jacob Greenway
@JacobGreenway 取决于视频的 src。但是当生成它们的选项卡失去焦点时,requestAnimationFrame() 在 Web Worker 中也会被限制,因此您需要比仅在 Web Worker 中运行原始代码更聪明一些。 - Patrick Roberts
很不幸,目前仅在Blink浏览器中支持,对于FF,您可以使用createImageBitmap方法传递一个<video>消费者。对于您最初的问题@JacobGreenway,您可能会对我的这个旧技巧感兴趣,它确实允许拥有非受限循环,但是浏览器仍然会限制很多东西,因此其实用性相当有限... - Kaiido
如果工作者不处理动画,这样做的好处是什么? - hoodsy
1
@hoodsy 在DOM线程中使用Transferable对象调用grabFrame()postMessage()并不会消耗太多计算资源,因此它有很多空闲时间来处理用户事件和重绘,而drawImage()和其他画布上下文方法的昂贵工作则被推到了一个工作线程中,在那里不会对网页的响应性产生负面影响。 - Patrick Roberts
@PatrickRoberts 的 transferControlToOffscreen 在浏览器上的支持较低。 - Alexufo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接