Как сделать собственный видео-плеер на HTML5 Video
Ранее мы уже рассмотрели общие вопросы использования HTML5 Audio и Video и начали погружаться в детали, начав с задачи определения поддержки браузером нужного кодека. Сегодня мы рассмотрим задачу создания собственного видео-плеера на HTML5 Video.
Напомню, что video-элемент сам по себе уже обеспечивает необходимый набор контролов для управления проигрыванием. Чтобы была видна панель управления воспроизведением, достаточно указать атрибут controls.
Однако, как я отмечал в вводной статье, со стандартными контролами есть проблема, которая заключается как раз в том, что выглядят они нестандартно. Другими словами, в каждом браузере они выглядят по-своему (проверить, как выглядят контролы в разных браузерах, можно на примере Video Format Support на ietestdrive.com — просто откройте его в двух-трех различных браузерах).
API для управления воспроизведением
Стандарт HTML5 для работы с видео вводит в DOM новый интерфейс — HTMLVideoElement, наследующий в свою очередь интерфейс HTMLMediaElement.
Интерфейс HTMLMediaElementЭто общий интерфейс для обоих медиа-элементов (аудио и видео), описывающий доступ к базовым возможностями работы с медиа-контентом: контроль источника контента, управление воспроизведением, изменение уровня звука и обработка ошибок. Основные свойства и методы, которые нам понадобятся:
Состояние сети и готовность к работе src — ссылка (url) на воспроизводимый контент buffered — буферизованные куски видео
Воспроизведение и контролы currentTime — текущий момент проигрывания (с.) duration — длительность медиа-контента (с.) paused — находится ли воспроизведение на паузе ended — закончилось ли проигрывание muted — включение/выключение звука volume — уровень звука [0, 1] play() — начать проигрывание pause() — поставить на паузу
События oncanplay — можно начать проигрывание ontimeupdate — изменена позиция проигрывания onplay — запущено проигрыв onpause — нажата пауза onended — воспроизведение закончилось
Важно: это далеко не все методы и свойства, выставляемые через интерфейс HTMLMediaElement.
Интерфейс HTMLVideoElementВидео отличается от аудио несколькими дополнительными свойствами: width и height — ширина и высота контейнера для проигрывания видео; videoWidth и videoHeight — внутреннее значение ширины и высоты видео, если размеры не известны, равны 0; poster — ссылка на картинку, которую можно показывать, пока видео недоступно (обычно это один из первых непустых кадров).
Разница между width/height и videoWidth/videoHeight в том, что последние — это собственные характеристики видео, в частности, с учетом соотношения сторон и других характеристик, в то время как контейнер для видео может быть любых размеров (больше, меньше, с другой пропорцией).
Play & Pause
Создание нашего собственного видео-плеера мы начнем с простой задачи: научимся запускать видео на проигрывание и останавливать воспроизведение. Для этого нам понадобятся методы play() и pause() и несколько свойств, описывающих текущее состояние видео-потока (мы также будем использовать библиотеку jQuery, не забудьте ее подключить).
Первым делом нам необходим video-элемент, которым мы хотим управлять, и элемент на который можно нажимать для управления текущим состоянием:
Обратите внимание на инвертирование состояния кнопки (paused) и действия (play).
Теперь надо добавить немного js-кода, чтобы нажатие на кнопку play переключало ее состояние и соответственно запускало видео-ролик или ставило его на паузу:
При желании можно сразу добавить несколько css-стилей для кнопок управления и их различных состояний и.
… казалось бы, все уже замечательно работает, но не тут-то было! Есть несколько мелочей, которые нам также нужно учесть.
Проигрывание сначалаВо-первых, нам нужно правильно обработать окончание проигрывания видео-ролика (если, конечно, оно не зациклено), и в этот момент нужно переключить кнопки управления так, чтобы вместо состояния «pause» было состояние «play»:
Контекстное менюВо-вторых, браузеры обычно добавляют возможность управлять воспроизведением через контекстное меню. Это означает, что пользователь, вообще говоря, может что-то изменить в обход наших элементов управления. Этот момент нужно также отловить и внести необходимые изменения во внешний вид контролов. Для этого достаточно подписаться на события onplay и onpause.
Так как у нас становится многовато мест, где меняется внешний вид, самое время попутно произвести небольшой рефакторинг, убрав из изначального переключения режимов теперь уже дублирующую смену внешнего состояния:
Кликабельное видеоНаконец, наверняка, нам захочется, чтобы проигрывание и пауза переключались по нажатию на само видео, поэтому нужно добавить еще несколько строчек:
Прогресс
Теперь давайте перейдем к отображению прогресса проигрывания. Для начала необходимо добавить несколько элементов, которые будут использоваться для отображения текущего состояния и управления текущей позицией:
И соответствующие стили:
И несколько ссылок на соответствующие элементы для быстрого доступа в объект controls:
Первым делом, нам нужно понять, какова длительность ролика — для этого у video-элемента есть свойство duration. Отследить это значение можно, например, в момент готовности ролика к проигрыванию — по событию oncanplay:
В данном случае, мы попутно определяем, нужно ли отображать количество часов в видео-плеере (кстати, вообще говоря, спецификация предполагает, что длительность ролика может изменяться — в этот момент срабатывает событие ondurationchange, и к тому же быть бесконечной — например, при стриминге радио).
Также мы используем специальную функцию formatTime для перевода секунд в формат HH:mm:ss или mm:ss:
Для отображения процесса проигрывания нам понадобится событие ontimeupdate, срабатывающее при изменении текущего момента:
Свойство currentTime выдает в секундах текущее время. Его же можно использовать, чтобы изменить время проигрывания:
Также будет полезным показывать буферизацию видео, для этого можно отталкиваться от события onprogress, срабатывающего при загрузке новых порций видео:
Важный нюанс относительно свойства buffered, который нужно иметь в виду, заключается в том, что он предоставляет не просто время в секундах, а промежутки времени в виде объекта TimaRanges. В большинстве случаев это будет только один промежуток с индексом 0, и начинающийся с отметки 0c. Однако, если браузер использует HTTP range запросы к серверу, например, в ответ на попытки перейти к другим фрагментам видео-потока, промежутков может быть несколько. Также надо учитывать, что в зависимости от реализации браузер может удалять из буфера памяти уже проигранные куски видео.
Наконец, давайте добавим еще небольшой штрих к нашем видео-плееру — возможность включать и выключать звук. Для этого добавим небольшой контрол с динамиком (SVG-иконка взята с сайта The Noun Project):
С соответствующими стилями для включенного и выключенного состояний:
Для переключения состояния динамика нам понадобится свойство mute:
(Стандартные методы jQuery для переключения css-классов не работают с SVG-элементами.) Если вы хотите также менять уровень громкости, то вам поможет свойство volume, принимающее значения в диапазоне [0, 1].
Что еще.
- проверка поддержки браузером HMTL5 Video, ,
- поддержка субтитров, в том числе для обеспечния accessibility.
Либо нужно делать соответствующие проверки или отлавливать возможные исключения. Исключения вообще надо отлавливать, например, событие onerror, возникающее при ошибке загрузки видео-потока :)
Из дополнительных опций, которые могут вам понадобиться: изменение скорости проигрывания. Для этого есть свойство playbackRate и соответствующее событие onratechange.