公開日: 2019 年 8 月 16 日
画像要素と同様に、動画の遅延読み込みを行うこともできます。動画は通常 <video>
要素で読み込まれますが、YouTube などの他のサービスでホストされている動画の場合は <iframe>
を使用する場合があります(その場合は、遅延読み込みの iframe の記事をご覧ください)。
<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>
上の例では、preload
属性に none
の値を使用して、ブラウザが動画データを一切プリロードしないようにしています。poster
属性は、動画の読み込み中にスペースを占有するプレースホルダを <video>
要素に指定します。
ほとんどのブラウザでは、preload
はデフォルトで metadata
に設定され、動画の一部が Content-Range
ヘッダーを使用してプリロードされます。これにより、特にブラウザで Content-Range
ヘッダーがサポートされていない場合、必要な量よりも多くのデータがダウンロードされる可能性があります。これがサポートされている場合でも、ブラウザはメタデータがどのバイトに保存されているかを知ることができず、ファイルの先頭に保存されていない可能性があります。したがって、動画の読み込みを回避するには、none
を指定して preload="none"
を使用することをおすすめします。
onmouseenter
属性(または同等の mouseenter
イベント ハンドラ)を使用して、ユーザーが動画にカーソルを合わせたときにメタデータをプリロードするように、さらに拡張することもできます。
<video controls
preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
これにより、ユーザーが動画を再生する際の遅延が短縮されるだけでなく、動画の長さがすぐに表示されます。
動画は LCP の候補として適格とみなされる場合があります。poster
画像は動画よりも読み込みが速いため、LCP の候補となる場合はポスター画像を使用する必要があります。また、fetchpriority
属性値を "high"
にしてプリロードする必要があります。
<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
アニメーション GIF の代替の動画の場合
自動再生動画は、GIF スタイルのクイック アニメーションによく使用されます。アニメーション GIF は広く使用されていますが、特にファイルサイズなど、さまざまな点で動画に劣ります。アニメーション GIF は、数メガバイトのデータになることがあります。たいてい、同じような画質の動画ははるかに小さくなります。
アニメーション GIF の代わりに <video>
要素を使用するのは、<img>
要素のように単純ではありません。アニメーション GIF には次の 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
の各属性は一目瞭然です。iOS で自動再生するには playsinline
が必要です。これで、あらゆるプラットフォームで機能する、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-lazyload と lozad.js は、Intersection Observer のみを使用する超軽量のオプションです。そのため非常に高性能ですが、古いブラウザで使用するには polyfill が必要です。
- yall.js は、Intersection Observer を使用し、イベント ハンドラにフォールバックするライブラリです。
data-poster
属性を使用して、動画poster
画像を遅延読み込みすることもできます。 - React に特化した遅延読み込みライブラリが必要な場合は、react-lazyload を検討してください。これは Intersection Observer を使用しませんが、React を使ったアプリケーションの開発に慣れている場合には、イメージの遅延読み込みを行う慣れた方法です。
これらの遅延読み込みライブラリは、それぞれドキュメント化されており、さまざまな遅延読み込みのためのマークアップ パターンが豊富にあります。