I am building a site with a video background. I have some javascript (shown below) which selects the most appropriate video source based on screen size and bandwidth. It starts by showing a default low-res version and then as soon as the bandwidth has been calculated, the highest quality that is appropriate is set as the new element source. However, this means that when the resolution is "upgraded" on the video.load(); command, the background flashes white. Is there a way of getting a less obtrusive transition, something like the video streaming sites changing resolution mid video.
<div class="video-container">
<video autoplay loop mob-hide id="video">
<source src="Images/Medium.mp4" type="video/mp4" />
Your browser does not support the video tag. I suggest you upgrade your browser.</video>
</div>
JS:
var video = document.getElementById('video');
if (screen.width > 992 && screen.width <= 1200) {
console.log(screen.width);
if (speedMbps > 0 && speedMbps <= 5) {
video.setAttribute("src", "Images/Medium.mp4");
}
if (speedMbps > 5 && speedMbps <= 10) {
video.setAttribute("src", "../Images/Large.mp4");
}
//more options etc.
}
video.load();
Related
I have a single video on a website that automatically plays when it scrolls into the viewport and pauses when it leaves the viewport. The video is muted so that it also works on mobile.
I'm using the Vimeo API to play and pause the video, and some JS to detect, on both load and when scrolling, whether the video is within the viewport.
This all works great, except that the user has the option to manually pause the video via the usual Vimeo playbar, as well as turn up the volume (the video's music soundtrack isn't essential for watching it, but some users might want to hear it).
The problem is that if the user manually pauses the video, and then starts scrolling, the script detects that the video is in viewport and starts playing it again, at least until the video has left the viewport.
This is not desirable, and it's especially undesirable if the user has turned up the volume and then paused the video, because now suddenly they will hear the video playing as they start scrolling down.
Is there a way to detect whether a user has interacted with the Vimeo player (to pause it) vs. when it's automatically paused from scrolling out of the viewport? I didn't see it when looking through the Vimeo API documentation (https://github.com/vimeo/player.js).
If that's possible, then I would simply add a conditional statement that says not to play the video when scrolled within viewport if it's currently paused by the user.
Or perhaps there's some other way to address? The only other requirement is that the solution be pure/vanilla JS.
Current code:
<div id="video-box">
<iframe id="i_video" src="https://player.vimeo.com/video/123456789?loop=1&muted=1&title=0&byline=0&portrait=0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="" width="530" height="298" frameborder="0"></iframe>
</div>
<script src="https://player.vimeo.com/api/player.js"></script>
<script>
var iframe = document.querySelector('iframe');
var player = new Vimeo.Player(iframe);
function vimeoPlay(){
player.play()
};
function vimeoPause(){
player.pause()
};
var dv = document.getElementById('video-box');
var v = document.getElementById('i_video');
function isAnyPartOfElementInViewport(dv) {
const rect = dv.getBoundingClientRect();
const windowHeight = (window.innerHeight || document.documentElement.clientHeight);
const windowWidth = (window.innerWidth || document.documentElement.clientWidth);
const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);
return (vertInView && horInView);
}
document.addEventListener("DOMContentLoaded", function(event) {
if (isAnyPartOfElementInViewport(dv)) {
vimeoPlay();
}
else {
vimeoPause();
}
}, false);
window.addEventListener('scroll', function (event) {
if (isAnyPartOfElementInViewport(dv)) {
vimeoPlay();
}
else {
vimeoPause();
}
}, false);
</script>
11/15/18 Edited to Add:
Inside if
(isAnyPartOfElementInViewport(dv)) {,
there is currently just
vimeoPlay(),
which means when in the viewport, no matter whether the user manually clicked pause on the Vimeo player, as soon as they start scrolling the video will play again.
What would you suggest for an inner conditional statement to place around vimeoPlay() such that it only plays if the user hasn't manually paused the player?
I can't just check to see if the video is paused using the API's getPaused() because I don't believe that distinguishes between whether it was paused automatically due to it being out of viewport or manually by clicking the pause button.
I guess if there were a way to ask "was this video paused while in viewport" and then only play the video if that condition is NOT true, that might help, but I'm not sure how to write that.
Here is the solution,
When User is paused the video, as per the Vimeo github docs
When a video is paused by User!.
Solution: Add this to your JS file
player.on('pause', function() {
console.log('paused the User!');
});
When a video is paused by scrolling
Solution:
window.addEventListener('scroll', function(event) {
if (isAnyPartOfElementInViewport(dv)) {
vimeoPlay();
} else {
console.log('paused by scrolling');
vimeoPause();
}
}, false);
Update: Attached Updated fiddler
Here is the working jsFiddle
Hope this helps!
I am developing a page with a full width / full height intro video (100vw / 100vh), looks "full screen" until you scroll down.
Currently I am using HTML5 <video> to accomplish this, but I've noticed the page can get a little choppy, particularly while scrolling. The video is about 4mb.
Would I see an increase in performance if I were to replace the <video> with a <canvas>, and load the video frames directly through the canvas object instead? both elements are GPU accelerated so I'd figure it shouldn't make a difference, but I'm not sure.
No, all the cost of decoding a video frame is still there. Using a canvas would in addition to that add more cost, not less.
If the video is without sound you could temporary pause the video while scrolling, as well as pause it permanently when out of view:
var vt;
window.onscroll = function() {
video.pause(); // pause video
clearTimeout(vt); // clear timer
vt = setTimeout(function() { // create a new timer
var r = video.getBoudingClientRect(); // abs. bound
if (window.scrollY < r.height) video.play(); // assumes video is in top
}, 70); // 70ms
...
};
Another key, although not of very much difference, is to make sure the video code is easy to decode. You can achieve this by removing noise, use flat colors and large surfaces, good lighting conditions, low depth-of-field to blur background as well as lower contrast and avoid too many details in the main subject(s) (this will also produce smaller files).
var video = document.querySelector("video"),
vt;
window.onscroll = function() {
video.pause();
clearTimeout(vt);
vt = setTimeout(function() {
var r = video.getBoundingClientRect();
if (window.scrollY < r.height) video.play();
}, 70);
};
html, body {width:100%; height: 2000px}
video {
width:100%;
height:auto;
}
<video muted width="500" height="280" autoplay="true">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm" type="video/webm">
<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv" type="video/ogg">
</video>
I am trying to skip a video ahead, using currentTime.
I set my video up like this:
<style>
#video-player {
display:inline-block;
width:500px;
height:358px;
margin-left:20px;
}
</style>
<video id="video-player" controls autoplay>
<source src="messi.mp4" type="video/mp4">
</video>
Later on, I have a click event set up on a button.
var video = document.getElementById('video-player');
video.currentTime = parseInt(video.currentTime) - 2;
All I want that button to do is to move the video back 2 seconds in time.
But when I click, it either moves the video to the beginning to freezes it up.
So this is very strange, but the issue went away when I tested my code on a live url.
I was testing using a local Python web server where I encountered the problem. Hope this helps someone.
I'm trying to achieve something with html5 video and haven't been able to find an answer elsewhere. Is it possible? Any help is much appreciated.
Here's the html:
<video autoplay="autoplay" poster="http://dummyimage.com/320x240/ffffff/fff">
<source src="videos/ship.mp4" type="video/mp4" />
</video>
I want to:
- on page load, display the video paused on the first frame (use poster?)
- at vertical scroll of X pixels, play the video once through (alternatively, inject it onto the page at X scroll?)
- then, when I scroll back beyond the X pixels value play the video again in reverse once through (does this work aMediaElement.playbackRate = -1; ?)
sadly the simplest solution playbackRate = -1 doesn't seem to be implemented anywhere yet.
you could fake it with some code like below to jump the currentTime back at whatever rate you need but from playing around it doesn't look very smooth.
my suggestion would be - if practical - to actually encode a a reversed version of the video if being able to play it backwards is the goal and then swap the source or toggle the visible <video> tag
Oh, and as usual... any video you're planning to stream on the web make sure you optimize and get the moov atom in the right place (see sample ffmpeg)
<script>
var intervalRewind = 0;
var v = document.getElementById("v")
function rewind() {
intervalRewind = setInterval(
function(){
v.playbackRate = 1.0;
if(v.currentTime == 0){
clearInterval(intervalRewind);
v.pause();
} else {
v.currentTime += -.1;
}
},30);
}
</script>
...
<video id="v" onclick="clearInterval(intervalRewind)" width="320" height="240" controls="controls">
<source type="video/mp4" src="video-fs.mp4" />
</video>
<button onclick="rewind()">Rewind</button>
I've got some fullscreen video backgrounds that I want to play once they're scrolled into view.
The code I'm using for the video running is as follows.
<video id="video_background" preload="false" autoplay="false" loop="loop" volume="0"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> Video not supported </video>
The full-screen side works great, the video plays and I'm very happy with how it all looks but I've got a couple of issues.
Even at the point I'm at, the video isn't taking into account the autoplay="false" attribute. It's instantly playing as soon as the page loads.
Can someone point me in the right direction to play html5 video when the section is scrolled into view? I'm using sections such as the following for each bit.
<div class="container"><video id="video_background" preload="false" autoplay="false" loop="loop" volume="0"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> Video not supported </video></div></section>
I can't find anything that will let me start a section when it scrolls into view.
Any ideas?
According to w3schools.com the autoplay must be coded just if you want autoplay, and ignore if you don't want autoplay.
To know when some element appears in the viewport yo can use jquery.appear plugin:
$('someselector').on('appear', function(event, $all_appeared_elements) {
// this element is now inside browser viewport: play video
});
$('someselector').on('disappear', function(event, $all_disappeared_elements) {
// this element is now outside browser viewpor: Pause/stop video?
});
If you don't want to use this jQuery plugin, in this StackOverflow question the accepted response to know where some element is scrolled into view is:
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}