I need to tell, whether video cannot be played ("x" sign is shown in browser).
This code does't works. "onerror" event will never be fired under Firefox
var v = document.getElementsByTagName("video")[0];
if ( v != undefined )
v.onerror = function(e) {
if ( v.networkState == v.NETWORK_NO_SOURCE )
{
// handle error
}
}
What's wrong here ?
"onerror" is not a valid event type for <video>
Use "error" instead.
document.getElementsByTagName('video')[0].addEventListener('error', function(event) { ... }, true);
For a complete list of events for <video>
go here: https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox
From Firefox 4 onwards, the 'error' event is dispatched on the <source>
element.
And you should add an error handler on the only/last source:
HTML
<video id="vid" controls>
<source src="dynamicsearch.mp4" type="video/mp4"></source>
<source src="otherdynamicsearch.avi" type="video/avi"></source>
</video>
JS
var v = document.querySelector('video#vid');
var sources = v.querySelectorAll('source');
if (sources.length !== 0) {
var lastSource = sources[sources.length-1];
lastSource.addEventListener('error', function() {
alert('uh oh');
});
}
JQuery
$('video source').last().on('error', function() {
alert('uh oh');
});
AngularJS
You can create an error handling directive (or just use ng-error):
<video id="vid" controls>
<source src="dynamicsearch.mp4" type="video/mp4"></source>
<source src="otherdynamicsearch.avi" type="video/avi" ng-error="handleError()"></source>
</video>
Where the error handling directive's link
function should do (copied from ng-error):
element.on('error', function(event) {
scope.$apply(function() {
fn(scope, {$event:event});
});
});
To catch error event, you should use video.addEventListner()
:
var video = document.createElement('video');
var onError = function() { // your handler};
video.addEventListener('error', onError, true);
...
// remove listener eventually
video.removeEventListener('error', onError, true);
Note that the 3rd parameter of addEventListener
(on capture) should be set to true. Error event is typically fired from descendatns of video element ( tags).
Anyway, relying on video tag to fire an error
event is not the best strategy to detect if video has played. This event is not fired on some android and iOS devices.
The most reliable method, I can think of, is to listen to timeupdate
and ended
events. If video was playing, you'll get at least 3 timeupdate events. In the case of error, ended
will be triggered more reliably than error
.
It's good to know that Chrome and Firefox have different onerror
callbacks. The error must therefore be mapped. Mozilla uses error.originalTarget.
Here is a sample on how to do it with pure JavaScript:
const file = 'https://samples.ffmpeg.org/MPEG-4/MPEGSolution_jurassic.mp4';
window.fetch(file, {mode: 'no-cors'})
.then((response) => response.blob())
.then((blob) => {
const url = window.URL.createObjectURL(blob);
const video = document.createElement('video');
video.addEventListener('error', (event) => {
let error = event;
// Chrome v60
if (event.path && event.path[0]) {
error = event.path[0].error;
}
// Firefox v55
if (event.originalTarget) {
error = error.originalTarget.error;
}
// Here comes the error message
alert(`Video error: ${error.message}`);
window.URL.revokeObjectURL(url);
}, true);
video.src = url;
document.body.appendChild(video);
});
The above example maps an incoming error event into a MediaError which can be used to display an error playback message.
Try adding the event listener to the tag instead - I think the onerror attribute ("error" event) works on the source tag now, not the video tag.
Pug example
video(src= encodeURI(item.urlVideo), type='video/mp4' onerror="myFunction('param',this)")
script(src='/javascripts/onerror.js')
function myFunction(param, me) {
console.log(me);
me.poster = './images/placeholder.jpg'; }