The canplay/canplaythrough events for an HTML5 video are not called on Firefox. Why?

陌路散爱 提交于 2019-12-18 12:47:40

问题


I'm building a jQuery plugin for managing HTML5 videos. I'm trying to capture the canplay and canplaythrough events. In Chrome, the event is fired without problem. In Firefox, sometime it's triggered, sometime it's not.

I'm simplifying my code a little here:

$('#my_video').on('canplay canplaythrough', function(){
    console.log('canplay event fired');
});

I also tried with the native javascript .addEventListener() and it's not working.

Any idea why the event is not called on Firefox and how to fix that?

NOTE: Please do not tell me to use one of the already available plugins like jplayer and video-js, I know that they exist and work well, but I have to build an in-house solution.


回答1:


The problem is that your video element has triggered the canplaythrough event before you registered the event handler.

As you pointed out in your own answer, you can put your scripts in the <head>, but this is bad for your page performance.

A better way to fix your problem is to check the readystate attribute and execute your function manually in that case:

var $video = $('video'),
    videoElement = $video[0];

$video.on('canplaythrough', callback);

// If the video is in the cache of the browser,
// the 'canplaythrough' event might have been triggered
// before we registered the event handler.
if (videoElement.readyState > 3) {
  callback();
}



回答2:


The most likely reason you're seeing this probably has to do with timing issues. You stated in your accepted answer that putting jQuery into the head rather than the footer solves the problem. This tells me that the issue is DOM parsing and script execution order. The most likely culprit is that the "canplay" and "canplaythrough" events were being fired before jquery and your page script were parsed and the event handlers added - but only sometimes, depending on network traffic and load times. By putting the script in the head, you forced your event binding to occur before the DOM elements were created, thereby ensuring that you didn't miss any events.

As an aside, the performance benefits of putting script elements at the bottom of the page are debatable. If you really want to tweak page performance, use something like LABjs to manage parallel script loading.




回答3:


Even if my question didn't get any attention whatsoever, I think it's a good idea to give an explanation for people who may stumble on this in the future...

The problem is really weird: if the jQuery core is included in the footer, some of the video events do not work. If the jQuery core is included in the head of the document, all events are called correctly.

So the solution is to include the jQuery core in the html head even if "best practices" for optimization recommends placing all script at the end of the body for faster loading times.




回答4:


In my case, this was determined by the preload attribute specified for the element. I did not have it specified at all, so different browsers were choosing to do different things.

Once I specified preload="auto", the on("canplay") event handler worked fine/as expected.




回答5:


I do also think this is a race condition. The way I got around it is as follows:

In the HTML of the video element add the attribute preload="metadata" - to just preload the video metadata. So:

<video id="myVideo" width="640" height="480" preload="metadata" />

Next, inside the JS:

var $vid = $("#myVideo");
$vid.bind("canplaythrough", console.log("can play through full video"));
$vid.get(0).load();

This logged the message for me in Chrome - haven't tested elsewhere.




回答6:


If you expect the Firefox to load the whole audio after you trigger load then it would not do this. It will fire the loadstart but will not download anything. No progress events will be fired. And it will actually do no request to that file. You can see this behavior in the Firebug.

Firefox will only start loading the file after you trigger 'play`.

Proof. See console output.




回答7:


Adding:

var video = $('video');
video.trigger('load');

After adding the canplaythrough event listener fixed it for me on Firefox and Safari.




回答8:


After 1.5 days of trying different approaches from here (in vanilla). The events "canplay" and "canplaythrough" with addEventListner don't work in Edge. They work fine in every other Browser. So I ended up with a check of "ready-state" with setTimout :-(. Not realy elegant, but it works for me.

Controller.prototype.backGroundControl = function () {
var vid = document.querySelector('#bgvid');
var bgImg = document.querySelector('#bgimg');
_this = this;

if (vid.readyState === 4){
    bgImg.style.opacity = "0"
} else{
    setTimeout(function(){
        _this.backGroundControl();
    },500)
}  

}



来源:https://stackoverflow.com/questions/10235919/the-canplay-canplaythrough-events-for-an-html5-video-are-not-called-on-firefox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!