HTML5 Video - Percentage Loaded?
Asked Answered
B

5

45

Does anyone know what event or property I need to query in order to get a percentage figure of the amount an HTML5 video has loaded? I want to draw a CSS styled "loaded" bar that's width represents this figure. Just like You Tube or any other video player.

So just like you tube a video will play even if the whole video hasn't loaded and give the user feedback on how much of the video has loaded and is left to load.

Just like the Red Bar on YouTube:

enter image description here

Beamer answered 17/2, 2011 at 13:24 Comment(4)
I'm pretty sure the YouTube player is Flash, not HTML5. Are you asking for a similar solution using an HTML5 video?Mose
Yes you tube is flash. I am asking for the callback data from an html5 video that will enable me to represent this information to my user.Beamer
@evan, pagewil: youtube's html5 implementation is under testing...I use it....youtube.com/html5Russia
I think you have misunderstood meBeamer
A
97

The progress event is fired when some data has been downloaded, up to three times per second. The browser provides a list of ranges of available media through the buffered property; a thorough guide to this is available on Media buffering, seeking, and time ranges on MDN.

Single load start

If the user doesn't skip through the video, the file will be loaded in one TimeRange and the buffered property will have one range:

------------------------------------------------------
|=============|                                      |
------------------------------------------------------
0             5                                      21
|             \_ this.buffered.end(0)
|
\_ this.buffered.start(0)

To know how big that range is, read it this way:

video.addEventListener('progress', function() {
    var loadedPercentage = this.buffered.end(0) / this.duration;
    ...
    // suggestion: don't use this, use what's below
});

Multiple load starts

If the user changes the playhead position while it's loading, a new request may be triggered. This causes the buffered property to be fragmented:

------------------------------------------------------
  |===========|                    |===========|     |
------------------------------------------------------
  1           5                    15          19    21
  |           |                    |            \_ this.buffered.end(1)
  |           |                     \_ this.buffered.start(1)
  |            \_ this.buffered.end(0)
   \_ this.buffered.start(0)

Notice how the number of the buffer changes.

Since it's no longer a contiguous loaded, the "percentage loaded" doesn't make a lot of sense anymore. You want to know what the current TimeRange is and how much of that is loaded. In this example you get where the load bar should start (since it's not 0) and where it should end.

video.addEventListener('progress', function() {
    var range = 0;
    var bf = this.buffered;
    var time = this.currentTime;

    while(!(bf.start(range) <= time && time <= bf.end(range))) {
        range += 1;
    }
    var loadStartPercentage = bf.start(range) / this.duration;
    var loadEndPercentage = bf.end(range) / this.duration;
    var loadPercentage = loadEndPercentage - loadStartPercentage;
    ...
});
Auscultation answered 3/3, 2011 at 15:10 Comment(8)
I had to do video.buffered.end(0) (note: not wrapped in jQuery).Howlend
You can also use this in event instead of selecting video element. I think it's more comfortable and a bit faster.Headreach
nice but the $('video').get(0) part is wrong. 1. It only selects the first element from all videos while the bind is on a collection. 2. you should use eq(0) instead of get(0) to get the element itself. 3. you should use this inside the event instead of get() or eq()Impart
@Sumit I fixed the examples nowBeaty
I extended the answer to be more comprehensive.Beaty
Has anyone had any problems where you jump to a new currentTime and then when the buffer creates a new time range it's just slightly off from the new currentTime? An example would be jumping to the 20s point in a video and then the buffer starts loading from 20.02s. It's an insignificant amount of time, but enough to make the while loop in this example not match the new buffer range.Excessive
how can i make video player download data even when it is paused?Pintsize
Can someone tell me how to use this bit of code on an actual video? It doesn´t seem to do anything when you add the event listener to a video you have on your website. Also the vars dont console out anything.Outofdoor
A
6

The other awnsers didn't work for me so I started digging into this problem and this is what I came up with. The solutions uses jquery to make an progressbar.

function loaded()
{
    var v = document.getElementById('videoID');
    var r = v.buffered;
    var total = v.duration;

    var start = r.start(0);
    var end = r.end(0);

    $("#progressB").progressbar({value: (end/total)*100});      
}   

$('#videoID').bind('progress', function() 
{
    loaded();
}
);

I hope this helps others as well

Adolfo answered 10/7, 2011 at 20:41 Comment(0)
K
3

Percentage fix for loaded string.. Output something like 99% loaded inside #loaded element...

function loaded() {
    var v = document.getElementById('videoID');
    var r = v.buffered;
    var total = v.duration;

    var start = r.start(0);
    var end = r.end(0);
    var newValue = (end/total)*100;
    var loader = newValue.toString().split(".");

    $('#loaded').html(loader[0]+' loaded...');

    $("#progress").progressbar({
        value: newValue     
    });    
}
Kronos answered 20/11, 2012 at 3:35 Comment(0)
H
0

I think best event to update the buffered progress bar is timeupdate. whenever time of the media is updated event is fired.

It gives buffered property which we can use like this

audio.addEventListener('timeupdate', function () {
    if (this.duration) {
         let range = 0;
         let bf = this.buffered;
         let time = this.currentTime;

         while (!(bf.start(range) <= time && time <= bf.end(range))) {
            range += 1;
         }
         let loadStartPercentage = bf.start(range) / this.duration;
         let loadEndPercentage = bf.end(range) / this.duration;
         let loadPercentage = (loadEndPercentage - loadStartPercentage) * 100;
         //Update your progressbar DOM here
    }
});

Best advantage of this event is this is fired when media is played. Whereas progress event is fired when media is downloaded and notified by browser.

So just like youtube, buffered percentage can only be shown when media is played

Holcombe answered 5/11, 2020 at 7:17 Comment(0)
I
0

My answer is better than all of the other ones because you want to update buffer progress when the video is paused. This happens with the progress event. The time update event fires when progress fails, as it sometimes does.

$("#video").on("timeupdate progress", function(){
    var video = document.getElementById("video");
    var vidDur = video.duration;
    for(var i = 0; i <= vidDur; i++){
        var totBuffX = video.buffered.end(i);
        var perBuff = totBuffX/vidDur*100;
        $("#xVidBuffX").css("width", perBuff+"%");
    }
});

you only need video.buffered.end(i).

Impercipient answered 19/6, 2022 at 1:46 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Stilwell

© 2022 - 2024 — McMap. All rights reserved.