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

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>

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>

Related

Elements positioned over HTML5 video are invisible on iOS in battery saver mode

We are positioning some text over a HTML5 <video> which acts as a looping video background. However, the absolutely positioned elements are not visible on iOS' Safari, if the battery saver mode is active, regardless of any z-index settings. Example:
<div class="example">
<video playsinline muted loop autoplay>
<source type="…" src="…" title="…">
</video>
<div class="text">
Lorem ipsum dolor
</div>
</div>
.example {
position: relative;
}
video {
width: 100%;
height: auto;
}
.text {
position: absolute;
left: 2em;
top: 2em;
right: 2em;
}
This HTML and CSS code works fine, the text is overlayed over the video playing in the background. However, once the battery saver mode on an iOS device is activated, the text is not visible anymore - and cannot be made visible via a z-index either.
Is this somehow by design, so that the iOS user always has the opportunity to actually play the video (i.e. nothing obstructs it), since it will not automatically play in battery saver mode? Is there any way to prevent this behaviour? The video not playing automatically is fine (since that's what is supposed to happen in battery saver mode) - however we would want the text to be displayed.
I think the behaviour you are seeing is intended to allow the user the ability to play the video if they want in low power mode, as you suggest. It is possibly a use case that was not considered - i.e. to allow for something that is intended to be visible over the video so you could raise a bug request to check this.
In the meantime, as a workaround you can check if your video has been suspended and then make whatever changes you want yourself. See example listener below:
yourVideo = document.getElementById('your_video_id');
yourVideo.addEventListener('suspend', () => {
// Add code here as required
// e.g. hide the video and display
// an image and your text instead.
});
Suspend event info is here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/suspend_event

HTML5 video freezing and stuttering

I have a weird issue. I'm revisiting a project from just ~2 months ago that was working perfectly smoothly, using the following HTML5/canvas simple code:
<video id="video2" playsinline controls autoplay style="display: none;"">
<source src="exercise_media/video_dance_example.mp4" type="video/mp4" >
</video>
But now, the video is freezing every few seconds, then a few seconds later will skip forward to catch up to the current time. Audio works perfectly though.
Any ideas what could be going on here? I tested on both my IE explorer and Google Chrome, same issue.
Here is a short video clip to show what I mean with the stuttering of the video: https://imgur.com/a/Viv2Gix
The extra JavaScript stuff I do, namely the skeletal tracking, runs fine, and continues working even when the video frame is frozen, so it's not that part which is malfunctioning. It's just the HTML5 video itself.
This is a known regression in Chrome.
Given the bug report is marked as "started", we can hope it will get fixed soon enough.
[edit] And indeed it has been fixed soon enough. They even make the fix climb to the current stable 88, so you should not face this issue anymore.
For the time being, what you can do is to not hide that video element, but to cover it, e.g set a background-color to your body and set the z-index of your video to -1.
const ctx = canvas.getContext("2d");
btn.onclick = (evt) => {
btn.remove();
vid.play().then(() => {
canvas.width = vid.videoWidth;
canvas.height = vid.videoHeight;
draw();
});
};
function draw() {
ctx.drawImage(vid, 0, 0);
setTimeout(draw, 50);
}
html,body {
background: white;
}
:checked ~ #vid {
z-index: -1;
position: absolute;
}
canvas,video { width: 300px }
<button id="btn">begin</button>
<span>hide video:</span><input type=checkbox><br>
<canvas id="canvas"></canvas>
<video id="vid" muted src="https://s3.amazonaws.com/leccap-itech-opsrw/apps/demo/1381411844-011-O-c1-86-87-599-13.mp4"></video>
Ps: an other workaround I thought about is to capture a MediaStream from the <video> element (const stream = vid.captureStream()), however, while it indeed improves a little the issue, it doesn't fix it as well as covering the element (the frame rate still seems lower), and it will certainly cost at least as much in terms of performances.
when I attempt your code, I don't see any video, due to the "display:none" that you are applying. If I remove that - then I see the video. In general, if you are autoplaying a video, you should add the 'muted' param as well to ensure autoplay for all users.
In terms of the video you are playing - what is the size and bitrate (visit https://ffprobe.a.video - and enter the url of the video to find out)

Replace video with still image using CSS

I am creating a print-css file for HTML5 documents containing video files. The video tags inside of a table look like this:
<td class="dataKeyframe">
<video width="180" height="135" controls="controls" preload="none"
poster="../images/sequenzbild001.jpg">
<source type="video/mp4" src="../videos/mp4/E1.mp4"></source>
</video>
</td>
Printing with Chrome results in printing the controls-overlay on top of the video poster.
The question:
Is it possible to set the controls to kind of display:none; --OR-- replace the video with the jpeg defined in the poster attribute? Using CSS only and not touching the html document.
What you want to alter is the Shadow DOM of the element. There are some browser generated subtree elements to display all those controls, panels and buttons browser dependently. Those are not displayed (at least not in chrome) in the source code but you can still play with them.
#media print {
video::-webkit-media-controls {
display: none;
}
}
//css
#media print {
video{
display:none;
}
}
the above code will hide the video in print page.

How can I place an image on top of the YouTube player?

I would like to place a static image on top of the YouTube Video Player; however, it appears as if they somehow block this from occurring?
So far I have tried setting the z-index higher than the YouTube player but this does not work.
For example:
<img src="../example.png"/ width="100" height="100" class="image" />
<iframe width="420" height="315" src="http://www.youtube.com/embed/k6U-i4gXkLM" frameborder="0" allowfullscreen></iframe>
.image { position: absolute; z-index: 10000; }
Your code works perfectly. Just the slash after "../example.png" is unnecessary but it will work anyway.
You should be able to add wmode=transparent to the youtube iframe url. See:
Youtube iframe wmode issue
A working example:
http://www.parentmap.local/article/webinar-parents-guide-to-college-admissions
Notice how the flyout menu overlaps the video iframe.
If that won't work for some reason, you could load the youtube preview image using javascript, then put your overlay on top of that. Only load the real iframe when someone actually clicks the element.
Quick googling finds this on youtube images:
http://www.reelseo.com/youtube-thumbnail-image/
Example from that page of preview image URL:
http://img.youtube.com/vi/bQVoAWSP7k4/0.jpg

Full Background HTML5 Video Without Letterboxing

There are many questions on here regarding how to do background HTML5 video, but I have no issue with that, it works fine (except for a small issue where it will only play audio and not video until I select something on the page or resize it, see here for that issue: Chrome Only Plays Audio Until Resize
What I want to do is make the video fit the background so that it never has any letterboxing (the lines above/below or on the sides when the aspect ration doesn't match). That means fit width when the height is less than the ratio, and fit height when the width is less than the ratio.
This will cut off some of the video, but that's fine, I just want to get rid of the letterboxing. Is there any way to do this with just CSS, and if not what javascript/jQuery/whatever do I need to use?
My code so far:
#mashvid {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: auto;
min-width: 100%;
z-index: -5;
}
<video preload id="mashvid" poster="images/mashvid_poster.png">
<source src="http://www.mashwork.com/testsite/video/mashwork1080.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
<source src="http://www.mashwork.com/testsite/video/mashwork1080.ogv" type='video/ogg; codecs="theora, vorbis"'>
<source src="http://www.mashwork.com/testsite/video/mashwork1080.webm" type='video/webm; codecs="vp8, vorbis"'>
Your browser does not support the video tag.
</video>
I solved it like this, although I'm not sure how solid it is
function dimensionFunction() {
if ($('video').height() <= $(window).height()) {
$('video').height($(window).height());
$('video').width('auto');
} else {
$('video').width($(window).width());
$('video').height('auto');
}
if ($('video').width() <= $(window).width()) {
$('video').width($(window).width());
$('video').height('auto');
} else {
$('video').height($(window).height());
$('video').width('auto');
}
}
I have tried two (2) different jQuery plugins that do a fairly good job with this issue.
http://github.com/georgepaterson/jquery-videobackground
a nice plugin, with callbacks and nav/control functionas and styles, does not work on mobile "so-far-ee" but very nice on windows and osx lion.
and
http://syddev.com/jquery.videoBG/
a simpler plugin easier to customize, but also less robust, same issues with mobile safari but v ery capable otherwise.
the issue i have found is that scaling bg video or img bg attched to body will behave differently in smae browser on diff OS
bot safari and ie refuse to scale width to my liking on windows platforms but behave as expected on osx, your mileage may vary
=-)