Tiffany B. Brown

05 July 2010

The HTML5 video progress event

UPDATE: Thanks to zcorpan's comments, I have posted a follow-up entry that should clarify the current status of the video element and its properties.

The progress event is fired as the browser loads more of the media file. It may not be fired reliably, however. Chrome, for example, will not fire the progress event if it has cached the video file.

Only Firefox provides a means to calculate the amount of the video that has been loaded. The progress event object includes total and loaded properties that reflect the total size of the video file, and the amount the browser has retrieved from the server. This is also a reflection of how each browser handles video downloads.

Firefox requests partial content on the initial page load, then pauses downloading until the play event is fired. After the play event is fired — whether when the user clicks the 'play' button or the video tag has the autoplay attribute — Firefox resumes downloading the video file.

Safari, Chrome, and Opera conversely, download the entire video on page load — they automatically buffer by default. Opera and Chrome, however, will make the video available for play almost immediately, while Safari takes several seconds to download a larger portion of the file. Firefox will behave similarly if when the autobuffer attribute is present.

Presumably because they auto-buffer video, neither Safari, Chrome, nor Opera offer a means by which to detect either the video's size, nor how much of the video has loaded.

Some example code for handling the progress event (assuming we're wrapping this video element in a <div> tag with an id of 'container'). This will return the percentage of the video loaded in Firefox (and other browsers that don't auto-buffer), and fail silently in other browsers.

var container = document.getElementById('container');
var video = document.createElement(video);
// only Firefox and Opera support Ogg ... oh yeah Chrome does too.
video.setAttribute('src','movie.ogv'); 
function progressHandler(e){
      if(e.total && e.loaded){
           // percentage of video loaded
          var proportion = Math.round( e.loaded / e.total );
          return proportion * 100; 
      } else {  
           // do nothing because we're autobuffering.
      }
}
video.addEventListener('progress',progressHandler,false);
container.appendChild(video);