How to keep an HTML5 video rendering when out of view?

859 views Asked by At

On Chrome for Android (and in device emulation mode on desktop Chrome), when a <video> is scrolled out of view, the browser appears to pause rendering. But I need the video to keep going, since my code is continuously grabbing frames from the video to draw onto a <canvas> with real-time video effects, and the canvas could still be showing to the user even if the source video is scrolled out of view.

Below is an MCVE that shows the issue. The MCVE is written to simply copy the video onto the canvas without applying video effects.

The issue is that as soon as the video element scrolls out of view, the canvas appears to freeze since it's just rendering the same video frame over and over.

Is there a way to keep the video element playing even when it moves off-screen, or an alternative way to fix this?

const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

function drawFrame() {
    // In the real code, video effects are applied here
    ctx.drawImage(video, 0, 0);
    requestAnimationFrame(drawFrame);
}
drawFrame();

if (video.readyState >= 2) setup();
else video.addEventListener("loadeddata", drawFrame);
.spacer {
  height: 200px;
}
<p>Video Element:</p>
<video src="https://thumbs.gfycat.com/ExemplaryShadowyBuffalo-mobile.mp4" width="640" height="360" autoplay muted loop></video>
<div class="spacer"></div>
<p>Canvas Output Element (with video effects in the real code):</p>
<canvas width="640" height="360"></canvas>

1

There are 1 answers

0
Kaiido On

Videos with sound won't get auto-paused, so unmuting the video might do in some cases, but even setting the volume to 0 would make it behave as muted... so you'd also have to experience some noise.

But anyway, here your current video doesn't have any audio channel, so simply unmuting it won't do.

What will do however is to keep your drawing video out of the DOM:

// we do clone the visible element, and we keep that clone offscreen
const video = document.querySelector("video").cloneNode();
video.play();
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

function drawFrame() {
    // In the real code, video effects are applied here
    ctx.drawImage(video, 0, 0);
    requestAnimationFrame(drawFrame);
}
drawFrame();

if (video.readyState >= 2) setup();
else video.addEventListener("loadeddata", drawFrame);
.spacer {
  height: 200px;
}
<p>Video Element:</p>
<video src="https://thumbs.gfycat.com/ExemplaryShadowyBuffalo-mobile.mp4" width="640" height="360" autoplay muted loop></video>
<div class="spacer"></div>
<p>Canvas Output Element (with video effects in the real code):</p>
<canvas width="640" height="360"></canvas>