自动播放视频的 canvas.drawimage 仅在视频元素可见时有效

doo*_*son 5 html javascript google-chrome html5-video html5-canvas

我试图通过将视频绘制到画布上来在视频上添加一些滤镜。问题是,当视频元素不在视图中时,它会停止绘制。理想情况下,我想将视频元素全部隐藏起来。

我认为它只影响 Chrome 浏览器。另外,似乎如果您停止并用鼠标启动它,问题就会消失。

function drawToCanvas() {
  let vid = document.getElementById('vid1')
  let can = document.getElementById('can1')
  let ctx = can.getContext('2d')
  ctx.drawImage(vid, 0, 0, 400, 224)
  setTimeout(drawToCanvas, 30)
}

document.body.addEventListener("load", drawToCanvas(), false);
Run Code Online (Sandbox Code Playgroud)
html {
  padding: 20px 0;
  background-color: #efefef;
}

body {
  width: 400px;
  padding: 40px;
  margin: 0 auto;
  background: #fff;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
}

video {
  width: 400px;
  display: block;
}

#can1 {
  position: absolute;
  top: calc( 100vh + 100px);
}
Run Code Online (Sandbox Code Playgroud)
<canvas id='can1' height=224px width=400px></canvas>


<video autobuffer controls autoplay muted=true id='vid1'>
  <source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">
</video>
<br> Above is the Video element. 
<br> Below is the Canvas

<br><br><br> Why does the canvas below stop when the video is scrolled out of view
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
Run Code Online (Sandbox Code Playgroud)

Kai*_*ido 1

是的,当文档不在屏幕上时,他们确实会暂停附加到文档的静音视频。

请注意,根本不在文档中附加此视频不会暴露此行为:

(()=>{
  const vid = document.createElement('video');
  const ctx = document.getElementById('can1')
    .getContext('2d');
    
  ctx.filter = 'sepia(100%)';
  vid.muted = true;
  vid.src = "http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4";
  vid.play().then(anim);

  function anim() {
    requestAnimationFrame(anim);
    ctx.drawImage(vid, 0, 0, 400, 224)
  }
})();
Run Code Online (Sandbox Code Playgroud)
<canvas id='can1' height=224px width=400px></canvas>
Run Code Online (Sandbox Code Playgroud)

因此,如果您确实需要该视频元素也在那里,您可以使用从屏幕外视频捕获的 MediaStream 提供原始视频元素,并将其控件映射到该屏幕外视频。

visibleVid.srcObject = offscreenVid.captureStream();
visibleVid.onpause = e => offscreenVid.pause();
// ...
Run Code Online (Sandbox Code Playgroud)

visibleVid.srcObject = offscreenVid.captureStream();
visibleVid.onpause = e => offscreenVid.pause();
// ...
Run Code Online (Sandbox Code Playgroud)
function begin() {
  const visibleVid = document.getElementById('vid1');
  const offscreenVid = visibleVid.cloneNode(true);
  const can = document.getElementById('can1');
  const ctx = can.getContext('2d');
  ctx.filter = 'sepia(100%)';

  visibleVid.onpause = e => offscreenVid.pause();
  visibleVid.onplaying = e => offscreenVid.play();

  offscreenVid.play().then(() => {
    visibleVid.srcObject = offscreenVid.captureStream ?
      offscreenVid.captureStream() :
      offscreenVid.mozCaptureStream();
    visibleVid.play();
    anim();
  });

  function anim() {
    requestAnimationFrame(anim);
    ctx.drawImage(offscreenVid, 0, 0, 400, 224)
  }
}

onload = begin;
Run Code Online (Sandbox Code Playgroud)
html {
  padding: 20px 0;
  background-color: #efefef;
}

body {
  width: 400px;
  padding: 40px;
  margin: 0 auto;
  background: #fff;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
}

video {
  width: 400px;
  display: block;
}

#can1 {
  position: absolute;
  top: calc( 100vh + 100px);
}
Run Code Online (Sandbox Code Playgroud)

但这对于浏览器来说是很大的开销,并且您将失去从此元素中查找的可能性(因为它现在呈现一个流)。
因此,如果您确实需要这个,您也可以考虑在其他画布上进行自己的控件。

最后,他们显然只对静音视频执行此操作,因此如果您可以放弃自动播放功能,您也可以删除该muted属性并将其音量设置为0

<canvas id='can1' height=224px width=400px></canvas>


<video autobuffer controls autoplay muted=true id='vid1' crossorigin="anonymous">
  <!-- we need a crossorigin safe media -->
  <source id="mp4" src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" type="video/mp4">
https://stackoverflow.com/questions/55484353/canvas-drawimage-of-autoplayed-video-only-works-when-video-element-is-visible#</video>
<br> Above is the Video element.
<br> Below is the Canvas

<br><br><br> Why does the canvas below stop when the video is scrolled out of view
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
Run Code Online (Sandbox Code Playgroud)
(() => {
  let vid = document.getElementById('vid1');
  let can = document.getElementById('can1');
  let ctx = can.getContext('2d');

  vid.volume = 0;  // replace muted
  vid.play()
    .catch(() => {
      // in case we're not allowed to play, wait for user approval
      console.log('click anywhere to start playback');
      addEventListener('click',
        e => {console.clear();vid.play()},
        {once:true}
      )
    });
   anim();
   
   function anim() {
    requestAnimationFrame(anim);
    ctx.drawImage(vid, 0, 0, 400, 224)
   }
})();
Run Code Online (Sandbox Code Playgroud)
html {
  padding: 20px 0;
  background-color: #efefef;
}

body {
  width: 400px;
  padding: 40px;
  margin: 0 auto;
  background: #fff;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
}

video {
  width: 400px;
  display: block;
}

#can1 {
  position: absolute;
  top: calc( 100vh + 100px);
}
Run Code Online (Sandbox Code Playgroud)