HTML5 Video buffered attribute features

How video is buffered is browser implementation-dependent and therefore may vary from browser to browser.

Various browsers can use different factors to determine to keep or to discard a part of the buffer. Old segments, disk space, memory, and performance are typical factors.

The only way to know is to "see" what the browser has or is loading.

For example - in Chrome I played a few seconds then I skipped to about 30 seconds and you can see that it starts to load another part starting from that position.

(The buffer also seem to be bounded to key-frames so it is possible to decode the n-frames in that buffer. This means the buffer can start to load data a little before the actual position).

Example

I supplied a demo video about 1 minute long - however, this is not long enough to do proper testing. Free free to supply video links that contain longer video (or please share if you want me to update the demo with this).

The main function will iterate through the buffered object on the video element. It will render all parts that exist to the canvas right below the video showing in red.

You can click (bit not drag) on this viewer to move the video to different positions.

/// buffer viewer loop (updates about every 2nd frame)
function loop() {

    var b = vid.buffered,  /// get buffer object
        i = b.length,      /// counter for loop
        w = canvas.width,  /// cache canvas width and height
        h = canvas.height,
        vl = vid.duration, /// total video duration in seconds
        x1, x2;            /// buffer segment mark positions

    /// clear canvas with black
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, w, h);

    /// red color for loaded buffer(s)
    ctx.fillStyle = '#d00';

    /// iterate through buffers
    while (i--) {
        x1 = b.start(i) / vl * w;
        x2 = b.end(i) / vl * w;
        ctx.fillRect(x1, 0, x2 - x1, h);
    }

    /// draw info
    ctx.fillStyle = '#fff';

    ctx.textBaseline = 'top';
    ctx.textAlign = 'left';
    ctx.fillText(vid.currentTime.toFixed(1), 4, 4);

    ctx.textAlign = 'right';
    ctx.fillText(vl.toFixed(1), w - 4, 4);

    /// draw cursor for position
    x1 = vid.currentTime / vl * w;

    ctx.beginPath();
    ctx.arc(x1, h * 0.5, 7, 0, 2 * Math.PI);
    ctx.fill();

    setTimeout(loop, 29);
}

According to

  • https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
  • https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges
  • https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges.start

the buffered attribute holds information about all currently buffered time ranges. To my understanding, if a buffered portion is lost, it is removed from the object (in case that ever happens).

Esepcially the last link seems to be very useful for understanding the matter (since it offers a code sample) but keep in mind these are mozilla documents and support might be different in other browsers.

To answer your questions

Say the video starts. It continues upto 1:45 on its own (occasionally stalling perhaps, waiting for further data), after which I suddenly jump to 32:45. Now after some time, if I jump back to 1:27 (within the time range initially loaded and played through, before I made the jump), will it start playing immediately as it was already loaded before?

It should play immediately when jumping back unless the buffer of that portion was unloaded. I think it's very reasonable to assume that buffers or buffer ranges are unloaded at some point if the overall buffersize exceeds a certain volume.

Say I make 5 or 6 such jumps, each time waiting for a few seconds for some data to load after the jump. Does that mean the buffered object will have all those time ranges stored?

Yes, all buffered ranges should be readable through the attribute.

Will checking whether the buffered object has one time range starting at 0 (forget live streaming) and ending at the video duration length ensure tht the entire video resource has been loaded fully?

Yes, this is the code example in the last link. Apparently this is an applicable method of determining if the entire video has been loaded.

if (buf.start(0) == 0 && buf.end(0) == v.duration)