I am developing a video based timeline where each video will be played automatically while scrolling.
I'm only showing one video at a time when it scrolls into view, and then I'm removing DOM video node as it scrolls out and thats working perfectly fine.
{this.state.playing == key &&
<video autoPlay muted loop>
<source src={"/static/webm/videos/"+video.webm} />
</video>
}
The problem I have are slow networks, if a user has slow internet connection and keeps on scrolling every removed video they scrolled past even though no longer existing in the DOM tree continues to be downloaded which causes the website to very quickly come to a halt and waste my resources.
As you can see in here when I tested my site with dev tools and throttling enabled:
So my question is how do i stop video from being downloaded in the background after its been removed from the DOM before finishing the download?
If you use the built-in video support in the browser then there is no way to control the amount of data that's being buffered. It depends on the browser implementation and there is no API to control it.
Your best bet here is to use another player implementations which support these functionalities like dash.js, Bitmovin Player
Related
Probably a silly question but are there any ways to force playback of a HTML5 <video> earlier than the DOMcontentloaded event?
The video is hardcoded in a liquid file with the following attributes:
<video
poster="./poster.webp"
src="./545645660.sd.mp4"
loop muted playsinline autoplay preload="auto" type="video/mp4" disableRemotePlayback>
</video>
Since it's a hero background video, it needs to start playback as fast as possible but there's about a 2 second delay which looks bad. I've found that disabling JavaScript in Dev Tools will make it load instantaneously so it appears the large amounts of scripts are causing the delay but not sure if there's a way to prioritize playing back the video.
Browsers tend to delay videos downloading u til after all the JS, CSS, HTML, images - since these are required to load the page. Perhaps you can defer some of the scripts to load later?
You could also remove the poster - since that downloads BEFORE the video, and is probably never seen - as the video autoplays.
With the release of OSX High-Sierra*, one of the new features in Safari is that videos on websites will not auto play anymore and scripts can't start it either, just like on iOS. As a user, I like the feature, but as a developer it puts a problem before me: I have an in-browser HTML5 game that contains video. The videos do not get automatically played anymore unless the user changes their settings. This messes up the game flow.
My question is, can I somehow use the players' interaction with the game as a trigger for the video to start playing automatically, even if said activity is not directly linked to the video element?
I cannot use jQuery or other frameworks, because of a restraint that my employer has put on our development. The one exception is pixi.js which - among all other animations - we are also using to play our videos inside a pixi container.
*The same restriction also applies on Mobile Chrome.
Yes, you can bind on event that are not directly ones triggered on the video element:
btn.onclick = e => vid.play();
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
So you can replace this button with any other splash screen requesting an user click, and you'll be granted access to play the video.
But to keep this ability, you must call at least once the video's play method inside the event handler itself.
Not working:
btn.onclick = e => {
// won't work, we're not in the event handler anymore
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Proper fix:
btn.onclick = e => {
vid.play().then(()=>vid.pause()); // grants full access to the video
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Ps: here is the list of trusted events as defined by the specs, I'm not sure if Safari limits itself to these, nor if it includes all of these.
Important note regarding Chrome and preparing multiple MediaElements
Chrome has a long-standing bug caused by the maximum simultaneous requests per host which does affect MediaElement playing in the page, limiting their number to 6.
This means that you can not use the method above to prepare more than 6 different MediaElements in your page.
At least two workarounds exist though:
It seems that once a MediaElement has been marked as user-approved, it will keep this state, even though you change its src. So you could prepare a maximum of MediaElements and then change their src when needed.
The Web Audio API, while also concerned by this user-gesture requirement can play any number of audio sources once allowed. So, thanks to the decodeAudioData() method, one could load all their audio resources as AudioBuffers, and even audio resources from videos medias, which images stream could just be displayed in a muted <video> element in parallel of the AudioBuffer.
In my case i was combining transparent video (with audio) with GSAP animation. The solution from Kaiido works perfectly!
First, on user interaction, start and pause the video:
videoPlayer.play().then(() => videoPlayer.pause());
After that you can play it whenever you want. Like this:
const tl = gsap.timeline();
tl.from('.element', {scale: 0, duration: 5);
tl.add(() => videoPlayer.play());
Video will play after the scale animation :).
Tested in Chrome, Safari on iPhone
With the release of OSX High-Sierra*, one of the new features in Safari is that videos on websites will not auto play anymore and scripts can't start it either, just like on iOS. As a user, I like the feature, but as a developer it puts a problem before me: I have an in-browser HTML5 game that contains video. The videos do not get automatically played anymore unless the user changes their settings. This messes up the game flow.
My question is, can I somehow use the players' interaction with the game as a trigger for the video to start playing automatically, even if said activity is not directly linked to the video element?
I cannot use jQuery or other frameworks, because of a restraint that my employer has put on our development. The one exception is pixi.js which - among all other animations - we are also using to play our videos inside a pixi container.
*The same restriction also applies on Mobile Chrome.
Yes, you can bind on event that are not directly ones triggered on the video element:
btn.onclick = e => vid.play();
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
So you can replace this button with any other splash screen requesting an user click, and you'll be granted access to play the video.
But to keep this ability, you must call at least once the video's play method inside the event handler itself.
Not working:
btn.onclick = e => {
// won't work, we're not in the event handler anymore
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Proper fix:
btn.onclick = e => {
vid.play().then(()=>vid.pause()); // grants full access to the video
setTimeout(()=> vid.play().catch(console.error), 5000);
}
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>
Ps: here is the list of trusted events as defined by the specs, I'm not sure if Safari limits itself to these, nor if it includes all of these.
Important note regarding Chrome and preparing multiple MediaElements
Chrome has a long-standing bug caused by the maximum simultaneous requests per host which does affect MediaElement playing in the page, limiting their number to 6.
This means that you can not use the method above to prepare more than 6 different MediaElements in your page.
At least two workarounds exist though:
It seems that once a MediaElement has been marked as user-approved, it will keep this state, even though you change its src. So you could prepare a maximum of MediaElements and then change their src when needed.
The Web Audio API, while also concerned by this user-gesture requirement can play any number of audio sources once allowed. So, thanks to the decodeAudioData() method, one could load all their audio resources as AudioBuffers, and even audio resources from videos medias, which images stream could just be displayed in a muted <video> element in parallel of the AudioBuffer.
In my case i was combining transparent video (with audio) with GSAP animation. The solution from Kaiido works perfectly!
First, on user interaction, start and pause the video:
videoPlayer.play().then(() => videoPlayer.pause());
After that you can play it whenever you want. Like this:
const tl = gsap.timeline();
tl.from('.element', {scale: 0, duration: 5);
tl.add(() => videoPlayer.play());
Video will play after the scale animation :).
Tested in Chrome, Safari on iPhone
I would like to display a webpage with a wall of very short videos:
The videos are 1-2s long and all the same size (about 100px wide)
They are display in the form of a matrix (e.g. 10x10)
Playing the videos is triggered by user interaction (click or hover)
So far, I have tried inserting video tags using jQuery but when I reach about 60 videos, my browser (Chrome) hangs.
My question: is there a trick to display such a large quantity of videos on a single web page and what issue should I look out for to make sure the videos are ready to play before the user starts to interact.
EDIT: I understand this isn't common practice, but this project is an art installation and I need to be able to trigger all the videos (or moving images) on demand and without delay. On the other hand, the initial loading time doesn't matter so much, as the user will be made aware of the heavy load.
Thanks :)
IMO "videos are ready (...) before the user starts to interact" contradicts a leightweight DOM. You cannot have both. I'd try to show thumbnails and initialize the video with the interaction.
you could try to use the
use the
<video width="320" height="240" controls>
<source src="embed Link" type="video/mp4">
Your browser does not support the video tag.
</video>
tag inside of html. then you can acces every object by giving it a tag
My website currently loads a video in the banner when a desktop user visits the webpage. Currently the video is hidden but will still download if the user is on a mobile device. I would like to keep the video from downloading if the screen size below a certain count. I'm not sure how to go about this, I know of the display:none that can go along with CSS but this still downloads the file which is something I'd rather not do if the video isn't going to show at all.
If jQuery is fine, here's something you can try:
$(function(){
if($(window).width()>640){ //add video only if screen width is above 640px
$("body").append(yourVideoHere);
}
});
You need to first check to see if the screen is the appropriate width and then load your video source. Something like this should get you started.
var videoElem = document.querySelector('video');
var yourThreshold = 600;
if (screen.availWidth >= yourThreshold) {
videoElem.append('<source src="yourVideo.mp4" type="video/mp4"');
}
You can of course decide how specific you want to be as far as targeting devices. Just the width alone might not suffice.
Depends how you are trying to load the video, I would recommend the HTML5 video element with the preload attribute set to none so the video does not automatically begin to download. You could also then look at using a script that allows you to swap out video files depending on screen resolution, so for mobile you could load a smaller video size, a script that can get you up and running quickly is enquire.js. Hope this helps.
<video poster="image-location.jpg" preload="none">
<source class="mp4" src="video-location.mp4" type="video/mp4">
<source class="webm" src="video-location.webm" type="video/webm">
<source class="ogg" src="video-location.ogv" type="video/ogg">
<!-- Fallback Content such as embed YouTube video-->
</video>
How to do it based on screen size
see the other answers, measure screen size with javascript and only add the video tag, or set the source, if the screen size is big enough.
There's a gotcha if you use jquery as the <video> functions like .play() are javascript functions and won't be available to a jquery object.
How to actually do it
The best current solution for the problem of avoiding sending large video files to devices that haven't got the available bandwidth to handle it is currently server side and relies on the much more reliable metric of actual bandwidth. This is what YouTube do.
Consider the following two scenarios:
I'm at home, I have my smart phone connected by wifi to my high speed internet connection and the signal is good, but my screen resolution is reported as 480px - why should I be denied a video?
I'm out of the house, I've connected to wifi on a train, but the signal is horrible, my screen size reports as 1600px so I get a huge video, your site doesn't load and I go visit your competitor.
You can find out more about this here at MDN, and about one of the key tools, ffmpeg here, or you can use Any Video Converter to do a similar thing in a desktop GUI if you have full control over the videos. It's complicated and difficult and you may be better off using a third party service.