動画の遅延読み込み

画像要素と同様に、動画を遅延読み込みすることもできます。一般的に、動画は <video> 要素で読み込まれます(ただし、<img> を使用する代替メソッドは限定的に実装されています)。ただし、<video> を遅延読み込みする方法はユースケースによって異なります。異なるソリューションを必要とするシナリオをいくつか説明します。

自動再生されない動画の場合

ユーザーによって再生が開始される動画(つまり、自動再生されない動画)の場合は、<video> 要素に preload 属性を指定することをおすすめします。

<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>

上記の例では、値が nonepreload 属性を使用して、ブラウザによる動画データのプリロードを防ぎます。poster 属性により、動画が読み込まれる間にスペースを占有するプレースホルダが <video> 要素に設定されます。これは、動画を読み込むデフォルトの動作がブラウザによって異なるためです。

  • Chrome では、これまで preload のデフォルトは auto でしたが、Chrome 64 では metadata になりました。ただし、PC 版の Chrome では、Content-Range ヘッダーを使用して動画の一部がプリロードされることがあります。他の Chromium ベースのブラウザや Firefox も同じように動作します。
  • パソコン版 Chrome と同様に、パソコン版 Safari 11.0 でも一定の範囲の動画がプリロードされます。バージョン 11.2 以降では、動画のメタデータのみがプリロードされています。iOS の Safari では、動画はプリロードされません
  • データセーバー モードが有効になっている場合、preload はデフォルトで none に設定されます。

preload に関するブラウザのデフォルトの動作は固定されていないため、明示することが最善策と考えられます。ユーザーが再生を開始する場合は、preload="none" を使用するのが、すべてのプラットフォームで動画の読み込みを遅らせる最も簡単な方法です。preload 属性以外にも、動画コンテンツの読み込みを遅らせる方法があります。動画プリロードによる高速再生をご覧ください。JavaScript で動画再生を扱う際のアイデアやヒントが紹介されています。

残念ながら、次に説明するアニメーション GIF の代わりに動画を使用する場合には役に立ちません。

アニメーション GIF の代替となる動画の場合

アニメーション GIF は幅広い用途に利用されていますが、特にファイルサイズにおいて、多くの点で動画と同等ではありません。アニメーション GIF は 数メガバイトにも達します画質が同程度の動画は サイズがはるかに小さくなる傾向があります

<video> 要素をアニメーション GIF の代わりとして使用するのは、<img> 要素ほど単純ではありません。アニメーション GIF には次の 3 つの特徴があります。

  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>

autoplaymutedloop の各属性は一目瞭然です。iOS で自動再生を行うには playsinline が必要です。これで、複数のプラットフォームで機能する Video-as-GIF の代替機能が作成されました。遅延読み込みを行うには どうすればよいでしょうかまず、<video> マークアップを次のように変更します。

<video class="lazy" 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> 要素のスペースを占有するプレースホルダを指定できます。<img> 遅延読み込みの例と同様に、各 <source> 要素の data-src 属性に動画の URL を隠します。そこから、Intersection Observer ベースの画像遅延読み込みの例に類似した JavaScript コードを使用します。

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);
    });
  }
});

<video> 要素を遅延読み込みする場合は、すべての <source> 子要素を反復処理し、その data-src 属性を src 属性に切り替える必要があります。それが完了したら、要素の load メソッドを呼び出して動画の読み込みをトリガーする必要があります。その後、autoplay 属性に基づいてメディアが自動的に再生されるようになります。

この方法を使用すると、アニメーション GIF の動作をエミュレートする動画ソリューションが得られますが、アニメーション GIF ほど大量のデータ使用量が発生することはなく、そのコンテンツを遅延読み込みできます。

ライブラリの遅延読み込み

次のライブラリは、動画の遅延読み込みに役立ちます。

  • vanilla-lazyloadlozad.js は、Intersection Observer のみを使用する超軽量のオプションです。そのため、パフォーマンスに優れていますが、古いブラウザで使用するには事前にポリフィルする必要があります。
  • yall.js は、Intersection Observer を使用するライブラリで、イベント ハンドラにフォールバックします。data-poster 属性を使用して、動画の poster 画像を遅延読み込みすることもできます。
  • React 固有の遅延読み込みライブラリが必要な場合は、react-lazyload を検討してください。Intersection Observer は使用しませんが、React でのアプリケーションの開発に慣れている人には、画像の遅延読み込みを行うことができます。

これらの各遅延読み込みライブラリはドキュメント化されており、さまざまな遅延読み込みのためのマークアップ パターンが数多く用意されています。