0

Получение длительности HTML5 видео отдельно от файла

10

Я работаю над созданием 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 ответ(ов)

1

Ваш код:

var myVideoPlayer = document.getElementById('video_player');
myVideoPlayer.addEventListener('loadedmetadata', function() {
    console.log(myVideoPlayer.duration);
});

срабатывает, когда браузер получает все метаданные видео.

[правка] С тех пор лучше использовать событие 'durationchange' вместо 'loadedmetadata', так как оно может быть ненадежным. Пример кода:

myVideoPlayer.addEventListener('durationchange', function() {
    console.log('Изменение длительности', myVideoPlayer.duration);
});

Таким образом, при изменении длительности видео ваш обработчик будет срабатывать более надежно.

0

Да, спецификация 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.

0

Если вы столкнулись с проблемой, когда события 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.

0

Вот модификация вашего кода:

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, чтобы получить объект видео?

0

Я столкнулся с такой же проблемой: не удается получить длительность видео, $('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);

Код очень простой и действительно работает, поэтому я решил опубликовать этот ответ в надежде, что он поможет другим.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь