Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 - Detect the type of error when trying to load a video using a source element

I just found out some differences between handling errors when a video is loaded using the src tag of the <video> element and handling error when a video is loaded using a <source> element.

For example, if I try to load a video stream that is not found (HTTP 404) using the src tag of the video element, an event is triggered and the element stores the error data:

HTML

<video src="http://not.found.url"></video>

JS

var video = document.querySelector('video');

video.addEventListener('error', function(evt) {
  console.log(evt.target.error); // Object
});
video.load();

The video element stores a MediaError object in error:

error: {
  code: 4,
  message: 'MEDIA_ELEMENT_ERROR: Format error'
}

However, when I try to load the same video stream using a source element:

HTML

<video>
  <source src="http://not.found.url">
</video>

JS

var video = document.querySelector('video');
var source = document.querySelector('source');

video.addEventListener('error', function(evt) {
  // This event is not triggered
  console.log(evt.target.error); // null
});

source.addEventListener('error', function(evt) {
  console.log(evt.target.error); // null
});

video.load();

The source element error handler is the only one that catches the error but the error data is not stored anywhere. Neither the video element nor the source element stores an error object so, I can say an error has been triggered but I am not able to know the type of that error.

I would like to use the source element and be able to detect if the cause of the error has been a not valid video format, a 404 resource or any other reason.

Is that possible?

Thank you!

like image 682
Jorge Avatar asked Nov 29 '17 16:11

Jorge


1 Answers

Sorry, but the error codes will not help you with HTTP errors. However, the correct way to get the error code when using <source> elements is as follows:

<video class="video" autoplay controls>
    <source src="http://example.com/does-not-exist">
    <source src="http://example.com/corrupted-video">
    <source src="http://example.com/unsupported-video">
</video>
<script>
    var video = document.querySelector("video");
    var source = document.querySelector("source:last-child");
    // <source> elements are processed one by one until a usable source is found
    // if the last source failed then we know all sources failed

    video.addEventListener("error", function(e) {
        console.log("<video> error");
        console.log(e.target.error);
        // e.target would be the <video> element
        // e.target.error -- https://html.spec.whatwg.org/multipage/media.html#mediaerror
    });

    source.addEventListener("error", function(e) {
        console.log("<source> error");
        // e does not contain anything useful -- https://html.spec.whatwg.org/multipage/media.html#event-source-error
        // e.target would be the <source> element
        // e.target.parentNode would be the <video> element
        // e.target.parentNode.error -- https://html.spec.whatwg.org/multipage/media.html#mediaerror
        // e.target.parentNode.networkState -- https://html.spec.whatwg.org/multipage/media.html#dom-media-networkstate
        console.log(e.target.parentNode.error);
        console.log(e.target.parentNode.networkState);
    });
</script>

While this approach does not tell you about HTTP errors, you might be able to get some extra information by:

  1. Checking whether error was generated by <source> or <video>
  2. Looking at error and networkState
like image 182
Salman A Avatar answered Nov 15 '22 16:11

Salman A