I was watching a youtube where the content creator used GSAP to animate the switching between videos, which was very smooth, and I'd like to create something similar, but with a spinner that is shown until 2 seconds of each video has been loaded, that way the experience is smooth. How would we go about reacting once 2 seconds of N videos has been preloaded?
You can tell when a single video have been preloaded 2 seconds using the progress
event and the buffered
property.
Example:
const video = document.getElementById('myVideo');
function checkForBuffer(seconds) {
if (video.buffered.length > 0) {
const bufferedEnd = video.buffered.end(video.buffered.length - 1);
if (bufferedEnd >= seconds) {
console.log(`Video has preloaded at least ${seconds} seconds.`);
video.removeEventListener('progress', foo);
}
}
};
const foo = () => checkForBuffer(2);
video.addEventListener('progress', foo);
<video id="myVideo" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" preload="auto" controls width="200"></video>
In order to identify when N
videos have been preloaded, you can use a Promise approach.
Let's write a simple Promise.
function getVideoPreloadChecker(videoElement, secondsToBuffer) {
return new Promise((resolve, reject) => {
const progressHandler = () => {
if (videoElement.buffered.length > 0) {
const bufferedEnd = videoElement.buffered.end(videoElement.buffered.length - 1);
if (bufferedEnd >= secondsToBuffer) {
videoElement.removeEventListener('progress', progressHandler);
resolve();
}
}
};
videoElement.addEventListener('progress', progressHandler);
progressHandler();
});
}
async function main() {
var video = document.getElementById("myVideo");
var seconds = 2
await getVideoPreloadChecker(video, seconds)
console.log(`been preloaded ${seconds} seconds`)
}
main();
<video id="myVideo" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" preload="auto" controls width="200"></video>
And for the case of N:
function getVideoPreloadChecker(videoElement, secondsToBuffer) {
return new Promise((resolve, reject) => {
const progressHandler = () => {
if (videoElement.buffered.length > 0) {
const bufferedEnd = videoElement.buffered.end(videoElement.buffered.length - 1);
if (bufferedEnd >= secondsToBuffer) {
videoElement.removeEventListener('progress', progressHandler);
resolve();
}
}
};
videoElement.addEventListener('progress', progressHandler);
progressHandler();
});
}
async function main() {
var videos = document.querySelectorAll(".video");
var seconds = 2
var promises = [...videos].map(video => getVideoPreloadChecker(video, seconds))
await Promise.all(promises)
console.log(`all videos been preloaded ${seconds} seconds`)
}
main();
<video class="video" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" preload="auto" controls width="200"></video>
<video class="video" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4" preload="auto" controls width="200"></video>