36

So, I've been using a listener on

document.getElementById("video").buffered.length

to see if it's greater than 0 for when a video's loaded or not. This works for a very small video, and only in Google Chrome. It doesn't work in Firefox at all. Any ideas for how to get this to work?

I essentially want to wait till 3 seperate videos are loaded to take a specific action, how do I go about this?

insertusernamehere
  • 21,742
  • 7
  • 80
  • 113
Riveascore
  • 1,536
  • 3
  • 22
  • 43

4 Answers4

50

Try this:

var video = document.getElementById("video-id-name");

if ( video.readyState === 4 ) {
    // it's loaded
}

Read here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState

Richard de Wit
  • 5,772
  • 7
  • 42
  • 50
Šime Vidas
  • 163,768
  • 59
  • 261
  • 366
  • Which browsers support that property? – Jared Farrish Dec 30 '11 at 23:51
  • @JaredFarrish According to this [Wiki](http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28HTML5_Media%29), the support is complete (The WebKit column is empty, but I would be surprised if their implementation was behind Mozilla's/Opera's). – Šime Vidas Dec 31 '11 at 00:28
  • @ŠimeVidas how this can be used if there are more than 1 videos. ? thanks –  Aug 12 '16 at 07:08
  • 15
    This answer doesnt make sense. This is not really listening for changes. This is only going to run when the page first loads and if it's ready right away it will only work. – Omar Mar 24 '17 at 20:50
  • 1
    @Omar You are correct. I can delete my answer when a true solution is posted. – Šime Vidas Mar 25 '17 at 14:52
  • @Omar You are generalizing the use cases. I am saying this because in my media preload function, this solution fits perfectly, as I poll for load of various audio,video,image files periodically. – Dapu Sep 06 '19 at 06:42
16

UPDATE:

As others have mentioned, my original solution below does work but it can lead to performance issues and some unpredictability in its behaviour.

Therefore I recommend listening to the loadeddata event. Read more here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/loadeddata_event

const videoElement = document.getElementById("my_video");

videoElement.addEventListener('loadeddata', (e) => {
   //Video should now be loaded but we can add a second check

   if(videoElement.readyState >= 3){
       //your code goes here
   }

});

==================================

INFERIOR SOLUTION:

I find using setInterval works for actively listening to when the readyState of the video changes by checking every half-second until it loads in.

checkforVideo();

function checkforVideo() {
    //Every 500ms, check if the video element has loaded
    var b = setInterval(()=>{
        if(VideoElement.readyState >= 3){
            //This block of code is triggered when the video is loaded

            //your code goes here

            //stop checking every half second
            clearInterval(b);

        }                   
    },500);
}

If you're not using ES6 just replace () => with function()

Miro
  • 7,402
  • 2
  • 25
  • 52
Badrush
  • 1,003
  • 10
  • 29
  • 1
    Great answer! FYI all this is doing is checking a simple property of the video element. It uses very little processing power, so there's really no need to wait a half second between checks. You can change it to 10 milliseconds and catch the video at almost the exact moment it's loaded. – Gavin Apr 05 '19 at 06:50
  • 1
    This is badass. – John the Painter Nov 09 '19 at 18:10
  • 1
    This answer is fantastic but it blocks the main thread and I am trying to display a spinner there... the spinner animation freezes every second. – Duck May 22 '20 at 01:26
  • @DuckDucking you're right. Using `setInterval` might get the job done but it's far from ideal. I updated my answer with an new and improved solution that shouldn't cause performance issues. – Badrush May 26 '20 at 02:00
6

To make this into a listener, under normal circumstances, you'll want to listen to the suspend event. It's triggered when download is paused or stopped for any reason, including it's finished.

You'll also want to listen to playing for the cases when the content is already loaded (like, from cache)

video.addEventListener("playing", function() {
    console.log("[Playing] loading of video");
    if ( video.readyState == 4 ) {
        console.log("[Finished] loading of video");
    }
});
video.addEventListener("suspend", function(e) {
    console.log("[Suspended] loading of video");
    if ( video.readyState == 4 ) {
        console.log("[Finished] loading of video");
    }
});

Source: https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events

efaj
  • 888
  • 1
  • 11
  • 22
2

Use onloadeddata event on the video element. It checks whether the video is loaded or not. See this reference for more information.

The loadeddata event is fired when the frame at the current playback position of the media has finished loading; often the first frame.

var video = document.getElementById("video");
video.onloadeddata = function() {
    // video is loaded
}
aye2m
  • 113
  • 2
  • 8
  • 1
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Ethan May 24 '18 at 10:22
  • Well it didn't take me long to research this hint, and in my case it turned out to be the best solution. – Leo Smith Jun 30 '20 at 02:50