image

Обычно видео загружаются с помощью тега video (хотя, появился альтернативный метод с использованием img, правда, его возможности ограничены). Способ реализации отложенной загрузки видео зависит от варианта его использования. Давайте обсудим несколько сценариев, для каждого из которых требуется своё решение.

Для видео без автоматического автовоспроизведения


Для видео, воспроизведение которых инициируется пользователем (т.е. видео, которые не воспроизводятся автоматически) требуется указать соответствующий атрибут в теге video:

<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

В приведённом выше примере используется атрибут preload со значением none, запрещающий браузерам загружать любые видеоданные. Атрибут poster устанавливает для видео превью-изображение, которое займёт место видео на странице, пока оно не загружено. Необходимость превью обусловлена тем, что загрузка видео отличается в разных браузерах:

  • В Chrome значение атрибута preload по умолчанию было auto, но, начиная с версии 64, значением по умолчанию стало metadata. Даже в этом случае в десктопной версии Chrome часть видео может быть предварительно загружена, используя заголовок Content-Range. Firefox, Edge и Internet Explorer 11 ведут себя аналогично.
  • Как и в случае с десктопной версией Chrome, в версии Safari 11.0 для ПК сработает автозагрузка видео. Начиная с версии 11.2, предварительно загружаются только метаданные для видео, а В Safari на iOS видео никогда не загружаются предварительно.
  • Когда включен режим экономии трафика, значение preload по умолчанию становится none.

Поскольку в отношении автозагрузки поведение по умолчанию в разных браузерах различается, вероятно, лучшим решением будет явно установить это поведение. В тех случаях, когда пользователь самостоятельно инициирует воспроизведение, использование preload = «none» — самый простой способ отложить загрузку видео на всех платформах. Атрибут preload — не единственный способ отложить загрузку видеоконтента. Fast Playback with Video Preload может дать вам некоторые идеи и понимание работы с воспроизведением видео в JavaScript.

К сожалению, это бесполезно, если вы хотите использовать видео вместо GIF-анимаций, об этом поговорим ниже.

Для видео, выступающего в качестве замены анимированного GIF


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

Использовать элемент video в качестве замены анимированного GIF не так просто. Анимированные GIF-файлы имеют три характеристики:

  1. Они автоматически воспроизводятся после загрузки.
  2. Они непрерывно зациклены (хотя это не всегда так).
  3. У них нет звуковой дорожки.

Достижение этого с помощью тега video выглядит примерно так:

<video autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Атрибуты autoplay, muted и loop не требуют пояснений. playsinline необходим для автоматического воспроизведения в iOS. Теперь у вас есть пригодная к использованию замена анимации видео. Но как добавить для видео «ленивую» загрузку? В Chrome нет проблем с lazy-load загрузкой видео, но вы не можете рассчитывать на то, что все браузеры обеспечат такое оптимизированное поведение. В зависимости от вашей аудитории и требований приложения, вам может потребоваться взять дело в свои руки. Для начала изменим подключение видео:

<video autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
  <source data-src="one-does-not-simply.webm" type="video/webm">
  <source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>

Вы можете заметить добавление атрибута poster, который позволяет указать превью-изображение, расположенное на странице вместо тега video до тех пор, пока видео не будет загружено «лениво». URL-адрес видео помещён в атрибут data-src каждого элемента source.

Используем JavaScript для организации «ленивой» загрузки, использующий IntersectionObserver.

document.addEventListener("DOMContentLoaded", function() {
  var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));

  if ("IntersectionObserver" in window) {
    var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(video) {
        if (video.isIntersecting) {
          for (var source in video.target.children) {
            var videoSource = video.target.children[source];
            if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
              videoSource.src = videoSource.dataset.src;
            }
          }

          video.target.load();
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

    lazyVideos.forEach(function(lazyVideo) {
      lazyVideoObserver.observe(lazyVideo);
    });
  }
});

Мы перебираем все дочерние элементы source и преобразуем их атрибуты data-src в атрибуты src. Как только вы это сделаете, вам нужно запустить загрузку видео, вызвав метод load, после чего мультимедиа начнёт воспроизводиться автоматически в соответствии с атрибутом autoplay.

При использование этого метода, вы получаете готовое решение для видео, которое имитирует поведение анимированного GIF, но не требует такого же интенсивного использования данных, и вы можете «лениво» загружать этот контент.

Библиотеки для «ленивой» загрузки


Следующие библиотеки могут помочь вам с «ленивой» загрузкой видео:

  • lozad.js — это сверхлёгкий вариант, использующий только Intersection Observer. Таким образом, он очень эффективен, но его необходимо будет дополнить полифиллами, прежде чем вы сможете использовать его в старых браузерах.
  • yall.js — это библиотека, которая использует Intersection Observer и обращается к обработчикам событий. Она совместима с IE11 и основными браузерами.
  • Если вам нужна библиотека с отложенной загрузкой для React, вы можете подумать о react-lazyload. Эта библиотека не использует Intersection Observer, но предоставляет способ для «ленивой» загрузки изображений, который будет привычен разработчикам приложений на React.

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