以视频为源使用 drawImage 似乎只复制一个像素?

Using drawImage with a video as a source appears to only copy one pixel?

我有一个视频,它将视频的一部分流式传输到 MediaSource 中并播放。我有一个 canvas,我想在上面绘制视频,然后叠加一些效果。但是,在我的处理程序中,对 drawImage 的调用虽然有效,但似乎只复制了一个像素。视频本身播放正常。

我有一张来自我的应用程序的屏幕截图,源视频位于目标 canvas 元素旁边:

如您所见,canvas 的纯色是源视频第一个像素的颜色。

有问题的实际代码看起来与此类似:

  startWatch() {
    this.timer = setInterval(this.copyFrame.bind(this), 1000 / this.fps)
  }

  copyFrame() {
    const { width, height } = this.video.getBoundingClientRect()
    // I've tried the 3, 5, and 9 argument versions of this function
    // width is 300 and height is 168.75.
    this.ctx.drawImage(this.video, 0, 0, width, height, 0, 0, width, height)
  }

(其中 this.video 是一个 video 元素)

此代码确实“有效”,因为 canvas 的颜色会随着视频播放的时间而更新。但它始终只是初始像素。所以计时循环有效,但 drawImage 调用没有达到我的预期。

(1) 使用 const { width, height } 可能不正确。检查给定的值。
如果 console.log widthheight 值会发生什么,它们是 correct/expected 数字吗?

(2) "...但是 drawImage 调用没有达到我的预期。"

ctx.drawImage( someElement, 0, 0, A1, A2, 0, 0, B1, B2 );

考虑上面的代码,

  • 第一个width/height(A1/A2)是针对输入多少 来绘制(它必须匹配输入自身的大小 width/height,否则会发生裁剪或边距)。例如:A1 == 720 如果输入视频是 720 像素宽。

  • 第二个width/height(B1/B2)用于输出[=58]的调整大小=] 绘制。通常你想要填充整个 canvas 区域,所以 使用 canvas 尺寸 (长宽比留给编码人员根据首选实现)。

在您显示的代码中,您的 const { width, height }

  • 为 A1/A2 参数提供的数字太小(它采样一个像素)
  • 为 B1/B2 参数提供的数字过大(它将输出拉伸得如此之大以至于一个像素填满了 canvas)。

可能的解决方案:

尝试(如果必须使用边界矩形):

function copyFrame() 
{
    //# width is 300 and height is 168.75.
    //const { width, height } = this.video.getBoundingClientRect()
    
    let myRect = this.video.getBoundingClientRect();
    
    this.ctx.drawImage( this.video, 0, 0, 
                        this.video.videoWidth, this.video.videoHeight, 
                        0, 0, myRect.width, myRect.height);
}

或者,您可以将图片绘制成 canvas 尺寸:

function copyFrame() 
{
    //# assuming your Canvas is called "this.cnvs"
    this.ctx.drawImage( this.video, 0, 0, 
                        this.video.videoWidth, this.video.videoHeight, 
                        0, 0, this.cnvs.width, this.cnvs.height);
}

对于纵横比,您可以使用以下公式(将所有宽度和高度参考换成新的 drawn_width

myRatio = ( vid_height / vid_width ); 
drawn_height = ( myCanvas_width * myRatio );