Frontender Magazine

Создание интерактивного видео на HTML5

Благодаря элементу <video> из спецификации HTML5, теперь вставить видео на сайт так же просто, как картинку. И если принять во внимание, что все ведущие браузеры поддерживают <video> с 2011 года, сейчас это ещё и самый надёжный способ показать людям ваши движущиеся картинки.

Относительно новым в HTML5-семействе является элемент <track>. Это дочерний элемент для <video>, предназначенный для упрощения доступа к временной шкале видеоролика. В основном он нужен для добавления субтитров. Субтитры загружаются из отдельного текстового файла (в формате WebVTT) и воспроизводятся в нижней части области отображаемого видео. Ян Девлин (Ian Devlin) написал отличную статью на эту тему.

Однако, помимо субтитров, элемент <track> можно использовать для любых видов взаимодействия с временной шкалой видеоролика. В этой статье будут рассмотрены три примера: метки эпизодов, миниатюры предпросмотра и поиск по временной шкале. После прочтения статьи вы будете значительно лучше понимать принцип работы <track> и его API, что позволит вам создавать собственные интерактивные видеоролики.

Метки эпизодов

Давайте начнём с примера, который многим стал знаком благодаря DVD-дискам: метки эпизодов. Они позволяют зрителям быстро перейти к конкретному эпизоду. Это особенно удобно когда видео длинное как «Синтел»:

Метки эпизодов в этом примере помещены во внешний VTT-файл и загружаются на страницу с помощью элемента <track>, со своего рода разделами. В этом коде <track> установлен для загрузки по умолчанию:

<video width="480" height="204" poster="assets/sintel.jpg" controls>
  <source src="assets/sintel.mp4" type="video/mp4">
  <track src="assets/chapters.vtt" kind="chapters" default>
</video>

Затем мы используем JavaScript чтобы загрузить подписи из текстовой дорожки, отформатировать их и вывести в панели управления под видео. Обратите внимание, что нам нужно подождать пока загрузится VTT-файл:

track.addEventListener('load',function() {
    var c = video.textTracks[0].cues;
    for (var i=0; i<c.length; i++) {
      var s = document.createElement("span");
      s.innerHTML = c[i].text;
      s.setAttribute('data-start',c[i].startTime);
      s.addEventListener("click",seek);
      controlbar.appendChild(s);
    }
});

В этом коде мы добавляем 2 свойства списку записей чтобы получить интерактивность. Во-первых, мы устанавливаем атрибут data для хранения информации о начальной позиции эпизода, во-вторых, мы добавляем обработчик клика для внешней функции поиска. Эта функция будет проматывать видео к начальной позиции эпизода. Если видео (ещё) не проигрывается, это делается так:

function seek() {
  video.currentTime = this.getAttribute('data-start');
  if(video.paused){ video.play(); }
};

Вот и всё! Теперь у вас есть визуальное меню с эпизодами для вашего видеоролика, созданное с помощью VTT-дорожки. Обратите внимание, что в действующем примере создания меток для эпизодов используется большее количество кода, чем было описано выше, например, код для запуска проигрывания по клику, код для обновления позиции видео в панели эпизодов и немного CSS-стилей.

Миниатюры предпросмотра

Вторым примером является замечательная фича, популярности которой способствовали видеосервисы Hulu и Netflix: миниатюры предварительного просмотра. При наведении курсора на панель управления (или при перетягивании на мобильных устройствах), отображается превью для позиции, к которой вы собираетесь перейти:

Этот пример также сделан с помощью внешнего VTT-файла, загруженного в дорожку метаданных. Вместо текста метки в этом VTT-файле содержат ссылки на отдельные JPG-изображения. Каждая метка может содержать ссылку на отдельный файл, однако в этом случае мы отдали предпочтение JPG-спрайту из соображений быстрой загрузки и удобной поддержки в дальнейшем. Метки привязаны к соответствующему участку спрайта с помощью URI медиа фрагментов. Пример:

http://example.com/assets/thumbs.jpg?xywh=0,0,160,90

Вся важная логика получения правильной миниатюры и её отображения содержится в обработчике события mousemove для панели управления:

controlbar.addEventListener('mousemove',function(e) {
  // сначала на основе позиции мыши рассчитываем позицию во времени ..
  var p = (e.pageX - controlbar.offsetLeft) * video.duration / 480;

  // ..затем находим соответствующую метку..
  var c = video.textTracks[0].cues;
  for (var i=0; i p) {
          break;
      };
  }

  // ..затем определяем url-адрес изображения и медиа фрагмента..
  var url =c[i].text.split('#')[0];
  var xywh = c[i].text.substr(c[i].text.indexOf("=")+1).split(',');

  // ..и наконец стилизируем перекрытие миниатюрой
  thumbnail.style.backgroundImage = 'url('+c[i].text.split('#')[0]+')';
  thumbnail.style.backgroundPosition = '-'+xywh[0]+'px -'+xywh[1]+'px';
  thumbnail.style.left = e.pageX - xywh[2]/2+'px';
  thumbnail.style.top = controlbar.offsetTop - xywh[3]+8+'px';
  thumbnail.style.width = xywh[2]+'px';
  thumbnail.style.height = xywh[3]+'px';
});

Вот и всё. Опять же, актуальный пример с миниатюрами для предпросмотра содержит дополнительный код. В нём предусмотрена та же логика запуска воспроизведения и поиска, а также отображения/скрытия миниатюр при наведении курсора на панель управления.

Поиск по временной шкале

В нашем последнем примере рассмотрим ещё один способ добраться до контента, на этот раз с помощью поиска внутри видео:

В этом примере использован ранее созданный VTT-файл с титрами , который загружается в дорожку субтитров. Под видео и панелью управления мы выводим простую форму поиска:

Как в примере с миниатюрами, вся ключевая логика помещена в одну функцию. Например, это обработчик события для отправки формы:

form.addEventListener('submit',function(e) {
  // Сначала мы блокируем перезагрузку страницы и извлекаем ключевое слово/запрос..
  e.preventDefault();
  var c = video.textTracks[0].cues;
  var q = document.querySelector("input").value.toLowerCase();

  // ..затем находим все подходящие метки..
  var a = [];
  for(var j=0; j -1) {
      a.push(c[j]);
    }
  }

  // ..и выводим найденные метки в панели управления
  for (var i=0; i<a.length; i++) {
    var s = document.createElement("span");
    s.style.left = (a[i].startTime/video.duration*480-2)+"px";
    bar.appendChild(s);
  }
});

Вот и в третий раз всё получилось. Как и в предыдущих случаях, реальный пример поиска по временной шкале содержит дополнительный код для запуска воспроизведения и поиска, а также сниппет для обновления текста-подсказки в панели управления.

Подведём итоги

На основе приведённых выше примеров вы должны получить достаточное количество знаний для создания собственных интерактивных видеороликов. В качестве источника вдохновения посмотрите на наши эксперименты с кликабельными горячими точками, интерактивными расшифровками или взаимодействием с временной шкалой.

HTML5-элемент <track> представляет простой в применении, кроссплатформенный способ добавления интерактивности в ваши видеоролики. И хотя вам придётся потратить некоторое время на создание VTT-файлов и выстраивание взаимодействия, вы отметите улучшение доступности ваших роликов и повышение интереса к ним. Удачи!

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Jeroen Wijering
Robert Nyman
Автор:
Robert Nyman
Сaйт:
https://robertnyman.com/
GitHub:
robnyman
Twitter:
@robertnyman
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF

Комментарии (8 комментариев, если быть точным)

Автар пользователя
LakeVostok

Может мне показалось, но на ютубе была такая фича, если отмотать видео назад, то ему надо заново загружаться, т.е. видео как-то по кусочкам разделено. У меня тогда на диске 10 мб свободных было и показывало видяшки только в их плеере, остальные крашились. Интересно, как это реализовано.

Автар пользователя
dvzzz

LakeVostok, HLS или MPEG-DASH, например

Автар пользователя
bioshopik

Изучаю веб-разработку уже около 4 месяцев. Скажем, не особо усердно, так как до сих пор не сделал ни одного проекта, хотя по ощущениям уже могу сделать полноценный сайт. Знаю html и css на обычном уровне, Javascript понимаю нормально, умею нормально работать с DOM, знаю jQuery на базовом уровне (работа с DOM, без плагинов и UI). Знаю как пользоваться SASS, миксины, переменные и тд, вроде там ничего сложного не было. Вопрос в следующем: что делать дальше, чтобы найти работу? Сейчас думаю научиться пользоваться git и сделать пару проектов и залить туда, правда каких я не знаю, может пару сайтов? Что делать дальше с тем что я имею?

Ps; английский на среднем уровне.

Ps2; Не знаю где еще спросить как не на сайте с таким названием.

Автар пользователя
bioshopik

Я имел ввиду github. Сорри за вопрос не по теме, просто я уже совсем запутался.

Автар пользователя
iamstarkov

@bioshopik пройти learn.javascript.ru, потом найти работу джуном куда угодно, ходить на митапы и конференции, уйти на работу, где делают проекты, а не лендинги

Автар пользователя
bioshopik

@iamstarkov спасибо за а отличный сайт по js. Последний вопрос: я смотрел много вакансий по фронт-енд и зачастую требования очень разные. Кому-то требуется отличное знание html/css а js, например, совершенно не нужно, за исключением каких-нибудь библиотек типа jquery, а кому-то все, плюс еще тележку js-фреймворков. Подскажите, на что конкретно делать нажим при подготовке на позицию джуниора?

Автар пользователя
iamstarkov

@bioshopik зависит от вакансии. но сначала стоит разобраться с html/css, потом с ванильным js, потом с lodash и потом фреймворки, например с react или ember. вот ешё посмотри https://github.com/h5bp/Front-end-Developer-Interview-Questions

Автар пользователя
bioshopik

@iamstarkov спасибо большое за ответы! :)