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

  functionanim() {
    requestAnimationFrame(anim);
    ctx.drawImage(vid, 0, 0, 400, 224)
  }
})();
<canvasid='can1'height=224pxwidth=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();
// ...

functionbegin() {
  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();
  });

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

onload = begin;
html {
  padding: 20px0;
  background-color: #efefef;
}

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

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

#can1 {
  position: absolute;
  top: calc( 100vh + 100px);
}
<canvasid='can1'height=224pxwidth=400px></canvas><videoautobuffercontrolsautoplaymuted=trueid='vid1'crossorigin="anonymous"><!-- we need a crossorigin safe media --><sourceid="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 approvalconsole.log('click anywhere to start playback');
      addEventListener('click',
        e => {console.clear();vid.play()},
        {once:true}
      )
    });
   anim();
   
   functionanim() {
    requestAnimationFrame(anim);
    ctx.drawImage(vid, 0, 0, 400, 224)
   }
})();
html {
  padding: 20px0;
  background-color: #efefef;
}

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

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

#can1 {
  position: absolute;
  top: calc( 100vh + 100px);
}
<canvasid='can1'height=224pxwidth=400px></canvas><videoautobuffercontrolsautoplayid='vid1'><sourceid="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"