Duck
Duck

Reputation: 36003

Javascript: Error loading a video, but just on Chrome

I have an HTML page that loads a video and display a download progress bar.

The video element is created like this:

function createVideo() {  
  var video = document.createElement("VIDEO");
  video.setAttribute('controls', '');
  video.setAttribute('preload', 'auto');
  video.setAttribute('width', width);
  video.setAttribute('id', 'video');

  var source = document.createElement("SOURCE");
  source.setAttribute('src', "https://www.example.com/video.mp4");
  source.setAttribute('type', 'video/mp4');


  video.addEventListener('progress', function() {

    var endBuf = this.buffered.end(0); //1
    var soFar = parseInt(((endBuf / this.duration) * 100));
    var progressBar = document.getElementById("progressBar");

    if (soFar < 100) {
      progressBar.setAttribute('value', soFar);
    } else {
      progressBar.style = "display:none;";
    }

  });

The behavior I have on browsers is like this:

  1. Safari shows the video page but the video does not auto play. No error is shown on console.
  2. Firefox autoplays the video and shows no error on console.
  3. Chrome autoplays the video and shows this error on console:

2codes.js:368 Uncaught DOMException: Failed to execute 'end' on 'TimeRanges': The index provided (0) is greater than or equal to the maximum bound (0). at HTMLVideoElement. (https://example.com/code.js:368:32) (anonymous) @ functions.js:368

Line 368 is the one marked with //1 on the code above.

How do I solve that?

Upvotes: 0

Views: 248

Answers (1)

Justin Pearce
Justin Pearce

Reputation: 5097

It's possible that Chrome is triggering your "progress" listener before the video is completely loaded and meaning that this.buffered has no TimeRanges yet. You might consider wrapping the body of your "progress" listener in an statement to handle if buffered has no TimeRanges specified:

  video.addEventListener('progress', function() {
    if(this.buffered.length > 0) {
        var endBuf = this.buffered.end(0);
        var soFar = parseInt(((endBuf / this.duration) * 100));
        var progressBar = document.getElementById("progressBar");

        if (soFar < 100) {
          progressBar.setAttribute('value', soFar);
        } else {
          progressBar.style = "display:none;";
        }
    } else {
        progressBar.style = "display:none;";
    }

  });

Upvotes: 1

Related Questions