对于 html 视频元素,是否可以将流作为源添加到 html canvas 元素?

Sel*_*çuk 5 canvas stream media-source mediastream

根据 MDN:

HTMLMediaElement接口添加HTMLElement了支持音频和视频常见的基本媒体相关功能所需的属性和方法。

HTMLMediaElement.captureStream(). 它可以与<video><canvas>元素一起使用来捕获它们的流。

相反,一个可以添加一个视频流作为srcObject一个<video>元素,则它示出了它。是否有可能为<canvas>元素呢?

是否可以将流作为添加到 html<canvas>元素?

Kai*_*ido 5

不,任何 Canvas API 都不能使用 MediaStream。

画布 API 仅适用于原始像素,并且不包含任何类型的解码器。您必须使用能够进行此解码的 javascript 对象(例如 ImageBitmap)或 HTMLElements。

因此,在 MediaStream 的情况下,目前唯一能够解码其视频内容的对象将是 HTMLVideoElement,您将能够轻松地在画布绘制


2021 更新

WebCodecs API最近已经取得了很大进展,并正在成为越来越成熟了,它现在是作为一个解决方案中提到值得的。

这个 API 提供了一个名为VideoFrame的新接口,它将很快成为CanvasImageSources类型的一部分,这意味着我们可以直接使用它drawImagetexImage2D并且可以在任何地方使用这样的CanvasImageSource
MediaCapture变换W3C集团已开发出MediaStreamTrackProcessor,它从视频MediaStreamTrack退回这些VideoFrames。

所以我们现在有一种更直接的方法来将 MediaStream 渲染到画布上,该方法目前仅适用于带有#enable-experimental-web-platform-features标志的Chrome 浏览器...

if( window.MediaStreamTrackProcessor ) {
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const track = getCanvasTrack(); // MediaStream.getVideoTracks()[0]
  const processor = new MediaStreamTrackProcessor( track );
  const reader = processor.readable.getReader();
  readChunk();
  function readChunk() {
    reader.read().then( ({ done, value }) => {
      // the MediaStream video can have dynamic size
      if( canvas.width !== value.displayWidth || canvas.height !== value.displayHeight ) {
        canvas.width = value.displayWidth;
        canvas.height = value.displayHeight;
      }
      ctx.clearRect( 0, 0, canvas.width, canvas.height );
      // value is a VideoFrame
      ctx.drawImage( value, 0, 0 );
      value.close(); // close the VideoFrame when we're done with it
      if( !done ) {
        readChunk();
      }
    });
  }
}
else {
  console.error("Your browser doesn't support this API yet");
}

// We can't use getUserMedia in StackSnippets
// So here we use a simple canvas as source
// for our MediaStream.
function getCanvasTrack() {
  // just some noise...
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  const img = new ImageData(300, 150);
  const data = new Uint32Array(img.data.buffer);
  const track = canvas.captureStream().getVideoTracks()[0];

  anim();
  
  return track;
  
  function anim() {
    for( let i=0; i<data.length;i++ ) {
      data[i] = Math.random() * 0xFFFFFF + 0xFF000000;
    }
    ctx.putImageData(img, 0, 0);
    if( track.readyState === "live" ) {
      requestAnimationFrame(anim);
    }
  }
  
}
Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)

作为使用相机作为源的故障项目)。