Событие canplay/canplaythrough для видео HTML5 не вызывается в Firefox. Зачем?
Я создаю плагин jQuery для управления видео HTML5. Я пытаюсь захватить казус и события canplaythrough. В Chrome событие запускается без проблем. В Firefox иногда срабатывает, а иногда нет.
Я немного упрощаю свой код здесь:
$('#my_video').on('canplay canplaythrough', function(){
console.log('canplay event fired');
});
Я также пробовал с собственным javascript.addEventListener(), и он не работает.
Любая идея, почему событие не вызывается в Firefox и как это исправить?
ПРИМЕЧАНИЕ. Пожалуйста, не говорите мне использовать один из уже доступных плагинов, таких как jplayer и video-js. Я знаю, что они существуют и работают хорошо, но мне нужно построить собственное решение.
Ответы
Ответ 1
Проблема в том, что ваш элемент video
вызвал событие canplaythrough
до того, как вы зарегистрировали обработчик события.
Как вы указали в своем ответе, вы можете поместить свои сценарии в <head>
, но это плохо сказывается на производительности вашей страницы.
Лучший способ решить вашу проблему - это проверить атрибут readystate
и выполнить вашу функцию вручную в этом случае:
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
Наиболее вероятная причина, по которой вы видите это, вероятно, связана с проблемами времени. Вы заявили в своем принятом ответе, что ставить jQuery в голову, а не нижний колонтитул, решает проблему. Это говорит мне о том, что проблема заключается в разборе DOM и при выполнении script порядка выполнения. Наиболее вероятным виновником является то, что события "canplay" и "canplaythrough" запускаются перед jquery, и ваша страница script анализируется, а обработчики событий добавляются, но только иногда, в зависимости от сетевого трафика и времени загрузки. Поместив script в голову, вы заставили привязку своего события произойти до создания элементов DOM, тем самым гарантируя, что вы не пропустите никаких событий.
В стороне, преимущества производительности размещения элементов script в нижней части страницы являются спорными. Если вы действительно хотите настроить производительность страницы, используйте LABjs для управления параллельной загрузкой script.
Ответ 3
Даже если мой вопрос не привлечет никакого внимания, я думаю, что это хорошая идея дать объяснение людям, которые могут наткнуться на это в будущем...
Проблема действительно странная: если ядро jQuery включено в нижний колонтитул, некоторые из видео-событий не работают. Если ядро jQuery включено в заголовок документа, все события вызываются правильно.
Итак, решение состоит в том, чтобы включить ядро jQuery в html-head, даже если "лучшие практики" для оптимизации рекомендуют размещать все script в конце тела для более быстрого времени загрузки.
Ответ 4
Я тоже думаю, что это состояние гонки. Способ, которым я обходился, заключается в следующем:
В HTML-элементе видео добавьте атрибут preload = "metadata" - чтобы предварительно загрузить метаданные видео. Итак:
<video id="myVideo" width="640" height="480" preload="metadata" />
Далее, внутри JS:
var $vid = $("#myVideo");
$vid.bind("canplaythrough", console.log("can play through full video"));
$vid.get(0).load();
Это зарегистрировало сообщение для меня в Chrome - не тестировалось в другом месте.
Ответ 5
Если вы ожидаете, что Firefox загрузит весь звук после запуска load
, тогда он не сделает этого. Он запустит loadstart
, но ничего не загрузит. Нет событий progress
. И он фактически не будет запрашивать этот файл. Вы можете видеть это поведение в Firebug.
Firefox начнет загружать файл после запуска "play".
Доказательство. См. Вывод консоли.
Ответ 6
В моем случае это было определено атрибутом preload
, указанным для этого элемента. У меня этого не было, поэтому разные браузеры решили делать разные вещи.
Как только я указал preload="auto"
, обработчик события on("canplay")
работал нормально/как ожидалось.
Ответ 7
Добавление:
var video = $('video');
video.trigger('load');
После добавление прослушивателя событий canplaythrough зафиксировало его для меня в Firefox и Safari.
Ответ 8
После 1,5 дней попытки попробовать разные подходы отсюда (в ванили). События "canplay" и "canplaythrough" с addEventListner не работают в Edge. Они отлично работают в каждом браузере. Итак, я закончил с проверкой "ready-state" с setTimout:-( Не очень элегантный, но он работает для меня.
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)
}
}