Skip to content Skip to sidebar Skip to footer

Canvas.drawimage Of Autoplayed Video Only Works When Video Element Is Visible

I am trying to put some filters on a video by drawing it to a canvas. The problem is that when the video element is not in view it stops drawing. Ideally I would like to hide the v

Solution 1:

Yes, they do pause muted video appended to the document when it's not in screen.

Note that not appending this video at all inside the document will not expose this behavior:

(()=>{
  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)
  }
})();
<canvas id='can1' height=224px width=400px></canvas>

So if you really need that video element to be there too, you could feed the original video element with a MediaStream captured from an offscreen video and map its controls to this offscreen video.

visibleVid.srcObject = offscreenVid.captureStream();
visibleVid.onpause = e => offscreenVid.pause();
// ...

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;
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);
}
<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>

But that's a lot of overhead for the browser, and you will loose the possibility to seek from this element (since it now presents a stream).
So if you really need this, you may also consider doing your own controls, over an other canvas.

And finally, they obviously only do this for muted videos, so if you're ok with loosing the autoplay feature, you can also just go with removing that muted attribute and just set its volume to 0:

(() => {
  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)
   }
})();
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);
}
<canvas id='can1' height=224px width=400px></canvas>


<video autobuffer controls autoplay id='vid1'>
  <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">
</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>

Post a Comment for "Canvas.drawimage Of Autoplayed Video Only Works When Video Element Is Visible"