HTML5 video freezing and stuttering - html

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)

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

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

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>

Video causes Firefox to lag?

So one page of my website is quite video heavy. It has a big one as the background and like ~4 small ones in boxes. In Chrome this works wonderful and without any problems. But in Firefox its laggy and makes the entire interface frustrating to work with.
Now, I suspect this might be due to the fact that Firefox doesn't use the GPU, but im of course not sure, it could also be the code.
Im using mp4 videos. This is the code:
.video {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1;
opacity:0.2;
transform: translateX(-50%) translateY(-50%);
}
<video loop muted autoplay poser="bootstrap/img/lp_header.png" class="video">
<source src="bootstrap/video/game_hub_bg2.webm" type="video/webm">
</video>
There is not a code-able solution to this, however there are some alternatives.
Decrease your file size, using Javascript you can call a lower quality video on firefox (not going to provide an example since that's not what the question has asked).
Restrict your website for chrome use, this is a code-able solution.
Get a better computer.
Enable Firefox to use the GPU by hovering Options > Advanced > General > Browsing > Enable Tick. (#Marcos Perez Gude in the comments provided this alternative, shoutout to you).

HTML <video> placeholder is black on ipad. Can we change it?

I must place a <video> element in a web page. When accessed from the ipad, the page displays a black placeholder until the visitor hits the play button.
Is it possible to make it white, like one would normally do "background-color: white" in css?
edit: A 'hack' to work this around: Cover the video with an opaque .shield layer and have a .play button to start the vid.
$('#intro_video .play').selectable({
start: function(){
$('#intro_video .play').fadeOut();
$('#vid').get(0).play();
setTimeout(function(){
// See HACK03
$('#intro_video .shield').fadeOut('slow');
}, 200);
}
});
Can be nice to wrap inside a browser check to only affect mobile Safari:
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { ... }
Thanks,
You could put an element over the top that has an image of a play button, and script it to disappear on touch. Not so elegant maybe, but it works.

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