Получение длительности HTML5 видео отдельно от файла
Я работаю над созданием HTML5 видеоплеера с пользовательским интерфейсом, но у меня возникли проблемы с отображением информации о длительности видео.
Мой HTML выглядит просто:
<video id="video" poster="image.jpg" controls>
<source src="video_path.mp4" type="video/mp4" />
<source src="video_path.ogv" type="video/ogg" />
</video>
<ul class="controls">
<li class="time"><p><span id="timer">0</span> из <span id="duration">0</span></p></li>
</ul>
А вот JavaScript, который я использую для получения и вставки информации о продолжительности:
var duration = $('#duration').get(0);
var vid_duration = Math.round(video.duration);
duration.firstChild.nodeValue = vid_duration;
Проблема в том, что ничего не происходит. Я знаю, что в видеофайле есть данные о длительности, так как при использовании стандартных элементов управления она отображается корректно.
Но странно то, что если я вставляю alert(duration)
в мой код следующим образом:
alert(duration);
var vid_duration = Math.round(video.duration);
duration.firstChild.nodeValue = vid_duration;
то все работает нормально (если не считать неприятного всплывающего окна). Есть идеи, что здесь происходит или как я могу это исправить?
ОБНОВЛЕНИЕ: Я не решил эту проблему полностью, но я нашел обходной путь, который учитывает мою главную озабоченность... пользовательский опыт.
Во-первых, видео начинает загружаться только после того, как зритель нажимает кнопку "воспроизведение", так что я предполагаю, что информация о длительности не была доступна для извлечения (я не знаю, как исправить эту конкретную проблему... хотя предполагаю, что это связано с загрузкой метаданных видео отдельно от самого видео, но не знаю, возможно ли это).
Поэтому, чтобы обойти отсутствие данных о длительности, я решил скрыть информацию о длительности (а фактически весь элемент управления) до тех пор, пока вы не нажмете "воспроизведение".
Тем не менее, если кто-то знает, как загружать метаданные видео отдельно от видеофайла, пожалуйста, поделитесь. Я думаю, это должно полностью решить данную проблему.
5 ответ(ов)
Ваш код:
var myVideoPlayer = document.getElementById('video_player');
myVideoPlayer.addEventListener('loadedmetadata', function() {
console.log(myVideoPlayer.duration);
});
срабатывает, когда браузер получает все метаданные видео.
[правка] С тех пор лучше использовать событие 'durationchange' вместо 'loadedmetadata', так как оно может быть ненадежным. Пример кода:
myVideoPlayer.addEventListener('durationchange', function() {
console.log('Изменение длительности', myVideoPlayer.duration);
});
Таким образом, при изменении длительности видео ваш обработчик будет срабатывать более надежно.
Да, спецификация HTML5 действительно позволяет загружать только метаданные с помощью атрибута preload
. Это можно сделать, используя следующий код:
<video id="video" poster="image.jpg" controls preload="metadata">
<source src="video_path.mp4" type="video/mp4" />
<source src="video_path.ogv" type="video/ogg" />
</video>
Атрибут preload="metadata"
указывает браузеру, что нужно загружать только информацию о видео (например, продолжительность и размеры), но не само видео. Это может быть полезно для экономии трафика и времени загрузки, если вы не планируете сразу воспроизводить видео. Дополнительную информацию можно найти в документации W3C.
Если вы столкнулись с проблемой, когда события loadedmetadata
и durationchange
не срабатывают, и video.duration
оказывается ненадежным, вы можете попробовать следующий подход.
Вот обработка, которая обеспечивает надежный доступ к длительности видео:
// Сначала установите текущую позицию времени на большой интервал
video.currentTime = 7 * 24 * 60 * 60; // 7 дней в секундах
// Затем слушаем событие 'seeked'. Когда это событие происходит, значит, к длительности видео можно получить доступ нормально.
video.onseeked = () => {
alert("Длительность видео: " + video.duration);
video.onseeked = null; // Удаляем слушатель события, чтобы предотвратить повторные срабатывания
};
Этот код работает следующим образом: мы устанавливаем currentTime
на достаточно большое значение, чтобы триггерить событие seeked
. После этого, когда вы получите событие seeked
, длительность видео должна быть доступна и надежна. Этот подход может работать в случаях, когда видео не загружает метаданные должным образом.
Не забудьте заменить 7 * 24 * 60 * 60
на соответствующее значение, чтобы убедиться, что оно превышает длительность вашего video.
Вот модификация вашего кода:
var duration = document.getElementById("duration");
var vid_duration = Math.round(document.getElementById("video").duration);
//alert(vid_duration);
duration.innerHTML = vid_duration;
//duration.firstChild.nodeValue = vid_duration;
Надеюсь, это поможет.
Судя по всему, вы используете Internet Explorer. Почему бы вам не воспользоваться методом document.getElementById
, чтобы получить объект видео?
Я столкнулся с такой же проблемой: не удается получить длительность видео, $('video')[0].duration
всегда возвращает NaN
. Я обратился к принятому ответу @stopsatgreen и изменил код, чтобы он подходил для общего случая, и это действительно сработало.
var video = $('video')[0];
var t = setInterval(function () {
if(video.readyState > 0) {
var duration = video.duration;
console.log(duration);
clearInterval(t);
}
}, 500);
Код очень простой и действительно работает, поэтому я решил опубликовать этот ответ в надежде, что он поможет другим.
Потеряно HTML-кодирование при чтении атрибута из поля ввода
jQuery/JavaScript: Замена битых изображений
Предварительный просмотр изображений перед загрузкой
Как создать WYSIWYG-редактор на HTML/JS? [закрыто]
Как выполнить код после сброса HTML-формы с помощью jQuery?