Подтвердить что ты не робот

Событие 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. Я знаю, что они существуют и работают хорошо, но мне нужно построить собственное решение.

4b9b3361

Ответ 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)
}  

}