はじめに
「WordPress高速化」シリーズの第11回です。当サイトでは、操作の様子を見せるために、記事にmp4の動画を入れることがあります。動画ブロックで入れた動画が、いつ読み込まれているのかを調べてみました。
結果は次のとおりです。
- 動画がページのかなり下にあっても、開いた直後に動画のファイルが丸ごと読み込まれていた
- 自動再生の動画は、
preload="none"(読み込まない指定)を付けてもブラウザが無視して読み込む - Intersection Observerで近づいてから読み込むようにすると、テスト記事の開いた直後の動画の読み込みが3,798KB→232KBになった
この記事では、自動再生の動画を画面に近づいてから読み込む方法と、再生ボタン付きの動画をブロックの設定だけで軽くする方法を解説します。
WordPress 7.1.4、SWELL 2.19、Chrome 157 で確認しています。子テーマの functions.php を編集し、JavaScriptのファイルを追加します。編集する前に、必ずバックアップを取ってください。
動画ブロックは、いつ読み込まれるか
本番の記事で確かめる
当サイトで動画を入れている記事を、スクロールせずに開いて、読み込まれたファイルを調べました。
| 記事 | 動画の種類 | 動画の位置 | 開いた直後に読み込んだ量 |
|---|---|---|---|
| VBAのユーザーフォームの記事 | 自動再生(ミュート・ループ)×3本 | 4,000〜8,400px下 | 291KB(3本とも丸ごと) |
| GASの第7回 | 再生ボタン付き ×1本 | 3,000px下 | 169KB(丸ごと) |
どちらも、読者が動画の位置までスクロールしていないのに、動画のファイルを最後まで読み込んでいました。ページ全体の読み込み量(約1.3MB)の1〜2割にあたります。
なお、本文の画像には、WordPressが自動で loading="lazy" を付けているので、画面に近づくまで読み込まれていませんでした。遅延読み込みが効いていないのは、動画だけです。
preload の指定と、実際の読み込み量
<video> タグには、preload という属性で「最初にどこまで読み込むか」を指定できます。
| preload の値 | 意味 |
|---|---|
auto | 全部読み込んでよい |
metadata | 長さや大きさなどの情報だけ読み込む |
none | 再生されるまで読み込まない |
ただし、これはブラウザへの「お願い」で、実際にどれだけ読み込むかはブラウザが決めます。そこで、テスト用の動画を2つ(232KBと3.3MB)用意して、ページの4,000px下に置き、スクロールせずに読み込まれた量をChromeで測りました。

| 動画の書き方 | 小さい動画(232KB) | 大きい動画(3.3MB) |
|---|---|---|
| 自動再生(指定なし) | 232KB | 4,134KB |
自動再生+preload="none" | 232KB | 3,047KB |
| 自動再生+Intersection Observer | 0KB | 0KB |
| 再生ボタン付き(指定なし) | 232KB | 1,958KB |
再生ボタン付き+preload="metadata" | 232KB | 1,984KB |
再生ボタン付き+preload="none" | 0KB | 0KB |
わかったことは、次の3つです。
- 自動再生の動画は、
preloadの指定が効かない:自動再生(autoplay)は「すぐ再生する」指定なので、preload="none"より優先されます preload="metadata"は、ほとんど効果がない:小さい動画は丸ごと、大きい動画でも約2MB読み込みました- 再生ボタン付きの動画は、
preload="none"で0KBになる:ただし、最初のコマも読み込まないので、再生するまで黒い枠になります
大きい動画で、読み込んだ量がファイルの大きさを超えているのは、ループ再生のために同じ部分を読み直しているためです。
つまり、自動再生の動画は、ページに書いてある限り読み込まれてしまうので、画面に近づくまで src(動画のURL)を書かないようにする必要があります。再生ボタン付きの動画は、preload="none" で済みます。
SWELLの「画像等のLazyload」との関係
SWELLには、「SWELL設定」→「高速化」に「画像等のLazyload」という設定があり、次の3つから選べます。
- 使用しない
loading="lazy"を使用する- スクリプト(
lazysizes.js)を使って遅延読み込みさせる
3つ目のスクリプトを選ぶと、画像だけでなく、動画にも遅延読み込みがかかります。これで解決できるかを確かめるため、テスト記事に動画を4本入れて比べました(結果は後の「実測」で詳しく紹介します)。
| SWELLの設定 | 開いた直後 | 最後までスクロールしたときの合計 |
|---|---|---|
loading="lazy"(当サイトの設定) | 3,798KB | 3,798KB |
スクリプト(lazysizes.js) | 0KB | 8,351KB |
スクリプトにすると、開いた直後は0KBになりました。しかし、preload="none" にした再生ボタン付きの動画まで、近づいたときに丸ごと読み込んでいました(3.6MB)。再生ボタンを押さない読者の分まで読み込むので、最後までスクロールしたときの合計は、かえって多くなります。
また、スクリプトにすると、画像の遅延読み込みもJavaScriptで行う方式に変わります。そこで当サイトでは、「loading="lazy" を使用する」のまま、自動再生の動画だけをコードで遅延読み込みすることにしました。
手順:自動再生の動画を、近づいてから読み込む
考え方は、【WordPress高速化】YouTube埋め込みを遅延読み込み(以下、第3回)と同じ2段階です。
- PHP:自動再生の動画の
srcをdata-srcに書き換えて、最初は読み込まないようにする - JavaScript:動画が画面に近づいたら、
data-srcの値をsrcに戻して読み込む
Intersection Observer(要素が画面に近づいたことを知らせる仕組み)の基本は、第3回で解説しています。
Step1:functions.phpでsrcをdata-srcに書き換える
子テーマの functions.php に、次のコードを追加します。
// 自動再生の動画を、画面に近づくまで読み込まないようにする
add_filter('render_block_core/video', function ($html) {
// 管理画面・RSSフィードでは書き換えない
if (is_admin() || is_feed()) {
return $html;
}
$tags = new WP_HTML_Tag_Processor($html);
// 自動再生でない動画はそのまま
if (!$tags->next_tag('video') || null === $tags->get_attribute('autoplay')) {
return $html;
}
$src = $tags->get_attribute('src');
if (!$src) {
return $html;
}
// src を data-src に変えて、最初は読み込まないようにする
$tags->set_attribute('data-src', $src);
$tags->remove_attribute('src');
return $tags->get_updated_html();
});
// 記事ページだけ、遅延読み込み用のJavaScriptを読み込む
add_action('wp_enqueue_scripts', function () {
if (!is_singular()) {
return;
}
wp_enqueue_script(
'video-lazy',
get_stylesheet_directory_uri() . '/js/video-lazy.js',
[],
'1.0',
['in_footer' => true, 'strategy' => 'defer']
);
});render_block_core/video:動画ブロックのHTMLを出力する直前に呼ばれるフィルターフックです。フィルターフックの仕組みは【WordPress×PHP】フィルターフックの仕組みと使い方で解説していますWP_HTML_Tag_Processor:HTMLのタグを1つずつ調べて、属性を書き換えられるWordPressの機能です。動画ブロックには、字幕(<track>)のsrcやポスター画像の指定が入ることがあるので、文字の置き換えではなく、<video>タグのsrcだけを確実に書き換えるために使っていますget_attribute('autoplay'):自動再生の指定がない動画は、nullが返るので、書き換えずにそのまま出力します- 出力のたびに書き換えるので、過去の記事を保存し直す必要はありません
Step2:JavaScriptで画面に近づいたら読み込む
子テーマのフォルダに js フォルダを作り、video-lazy.js というファイルを置きます(wp-content/themes/swell_child/js/video-lazy.js)。
// data-src を持つ動画が画面に近づいたら、src に入れて読み込む
document.addEventListener('DOMContentLoaded', () => {
const videos = document.querySelectorAll('video[data-src]');
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
return;
}
const video = entry.target;
video.src = video.dataset.src;
obs.unobserve(video);
});
}, { rootMargin: '200px 0px' });
videos.forEach((video) => observer.observe(video));
});video[data-src]:Step1で書き換えた動画だけを集めます- 画面の200px手前に来たら、
data-srcの値をsrcに入れます。動画には自動再生の指定が残っているので、読み込みが終わるとそのまま再生が始まります - 1回読み込んだら、
unobserveで見張りをやめます
第3回のコードと見比べると、iframe が video に変わっただけです。第3回の yt-lazy.js をすでに使っている場合は、1行目の 'iframe[data-src]' を 'iframe[data-src], video[data-src]' に変えれば、1つのファイルで両方に使えます。その場合、Step1の後半(wp_enqueue_script の部分)は不要です。
Step3:検証ツールで確認する
- 自動再生の動画を入れた記事を開き、F12で検証ツールを開く
- 「ネットワーク」タブを開き、上の検索欄に
mp4と入力する。「キャッシュを無効化」にもチェックを入れる - ページの一番上で再読み込みし、動画まで少しずつスクロールする
自動再生の動画は、画面に近づいたときに一覧に追加されます。このとき「イニシエータ」(読み込みのきっかけ)の列は「その他」になります。
同じ記事に、プリロードを指定していない再生ボタン付きの動画がある場合、そちらは開いた直後に読み込まれます。イニシエータには、記事のHTMLの行(記事のURL:行番号)が表示されます。

上の画像では、1行目が再生ボタン付きの動画、2行目が自動再生の動画です。再生ボタン付きの動画を開いた直後に読み込ませない方法は、次の章で説明します。
再生ボタン付きの動画は、ブロックの設定で
再生ボタン付きの動画は、コードを使わずに、動画ブロックの設定だけで軽くできます。
- 記事の編集画面で、動画ブロックを選ぶ
- 右側の設定で、「先読み」(プリロード)を「なし」にする
- 「ポスター画像を設定」から、動画の最初の画面などの画像を選ぶ
- 記事を更新する

先読みを「なし」にすると、再生ボタンが押されるまで動画を読み込みません。その代わり、最初のコマも表示されなくなり、黒い枠だけになってしまいます。ポスター画像は、先読み「なし」とセットで設定してください。ポスター画像は普通の画像なので、動画より軽く済みます。
ポスター画像は、「ポスター画像を設定」を押した後の画面からアップロードできます。動画を一時停止した画面を切り取って使うと、再生前と再生後の見た目がそろいます。
実測:対策前後の比較
テスト記事に、次の4本の動画を、ページの下のほうに離して入れました。
- 自動再生(小:232KB)
- 自動再生(大:3.3MB)
- 再生ボタン付き・先読み「なし」・ポスター画像あり(大)
- 再生ボタン付き・指定なし(小)

| パターン | 開いた直後 | 最後までスクロールしたときの合計 | 再生 | CLS |
|---|---|---|---|---|
SWELLの設定 loading="lazy" のまま | 3,798KB | 3,798KB | ○ | 0 |
| SWELLの設定をスクリプトにする | 0KB | 8,351KB | ○ | 0 |
loading="lazy"+この記事のコード | 232KB | 5,314KB | ○ | 0 |
この記事のコードを入れると、開いた直後の読み込みは3,798KB→232KBになりました。残った232KBは、「再生ボタン付き・指定なし」の動画です。この動画もプリロードを「なし」にすれば、開いた直後は0KBになります。
自動再生の動画は、近づいたときに読み込まれ、どれも問題なく再生されました。プリロード「なし」の動画は、再生ボタンを押すまで0KBのままです。
最後までスクロールしたときの合計が増えているのは、自動再生(大)の動画がループ再生で読み直しをしているためです。開いた直後に読み込むか、近づいてから読み込むかの違いなので、最後まで読む読者にとっての合計は、ほとんど変わりません。途中で読むのをやめた読者や、動画の手前までしか読まない読者の分だけ、読み込みが減ります。
注意点
- 自動再生はミュートが前提:Chromeなどのブラウザは、音が出る動画の自動再生を止めます。動画ブロックの設定で「自動再生」と「ミュート」を両方オンにしてください
- 動画の幅と高さ:動画ブロックでメディアライブラリから入れた動画には、幅と高さが自動で付きます。古い記事の動画には付いていないことがありますが、当サイトで幅と高さのない動画でも測ったところ、近づいてから読み込んでもレイアウトのずれ(CLS)は0でした
- キャッシュを削除してから確かめる:SWELLのキャッシュやキャッシュ系のプラグインを使っている場合は、コードを追加したら削除してください
- 読み込みを始める距離:大きな動画をスマホの回線で見ると、近づいてから読み込むので再生が少し遅れることがあります。
rootMarginの'200px 0px'を'600px 0px'のように大きくすると、早めに読み込み始めます
よくある質問・エラー対処
Q. 動画までスクロールしても、再生されません
→ まず、ページのソースで <video を検索し、data-src に書き換わっているか確認してください。書き換わっているのに再生されない場合は、video-lazy.js の場所(swell_child/js/video-lazy.js)が正しいか、検証ツールの「Console」タブにエラーが出ていないかを確認してください。ミュートがオフの動画は、ブラウザが自動再生を止めることがあります。
Q. SWELLの「画像等のLazyload」をスクリプトにしている場合は、このコードは必要ですか
→ スクリプトにしている場合は、自動再生の動画もSWELLが遅延読み込みするので、このコードは必要ありません。ただし、プリロード「なし」の動画も近づいたときに読み込まれます。この記事のコードを追加しても、SWELLは data-src が付いた動画を書き換えないので、両方を入れても問題はありません。
Q. ブロックエディター以前の記事の動画( ショートコード)にも効きますか
→ 効きません。このコードは動画ブロックだけが対象です。 ショートコードの動画は、動画のURLが <video> タグの中の <source> タグに入っていて、作りが違います。対象の記事が少なければ、動画ブロックに入れ直すのが手軽です。
おわりに(まとめ)
自動再生の動画はコードで、再生ボタン付きの動画はブロックの設定で、画面に近づくまで読み込まないようにできます。
- ✅ 動画ブロックの動画は、画面の外にあっても、開いた直後に読み込まれる
- ✅ 自動再生の動画は、
preload="none"が効かない。srcを後から入れる - ✅
render_block_core/videoとWP_HTML_Tag_Processorで、自動再生の動画だけdata-srcに書き換える - ✅ 再生ボタン付きの動画は、先読み「なし」とポスター画像をセットで設定する
- ✅ テスト記事では、開いた直後の動画の読み込みが3,798KB→232KBになった
この記事が、少しでも誰かのお役に立てれば幸いです。
関連記事
- 【WordPress高速化】SWELLのDOMサイズを減らす:PSIの「DOM サイズを最適化する」の内訳を数え、3か所に出力されているグロナビを減らす方法(シリーズ第10回)
- 【WordPress高速化】SWELLのPrefetchは不要:SWELLのPrefetchが移動時に使われない理由と、WordPress本体の先読みに一本化する方法(シリーズ第9回)
- 【WordPress高速化】X・Instagramの遅延読み込み:Intersection Observerで、XとInstagramの埋め込みを投稿に近づくまで読み込まない方法(シリーズ第8回)
- 【WordPress高速化】HCBを必要な記事だけで読み込む:Highlighting Code BlockのCSSとJSを、コードブロックがある記事だけで読み込む方法(シリーズ第7回)
- 【WordPress高速化】h3まで入れた目次の高さを自動設定:h2とh3を分けて数え、目次の高さを記事ごとに自動で確保する方法(シリーズ第6回)
- 【WordPress高速化】目次の高さを見出しの数で自動設定:PHPで見出しを数えてCSS変数に渡し、目次の高さを記事ごとに自動で確保する方法(シリーズ第5回)
- 【WordPress高速化】AdSenseを枠ごとに遅延読み込み:Intersection Observerで、画面に近づいた広告枠だけを読み込む方法(シリーズ第4回)
- 【WordPress高速化】YouTube埋め込みを遅延読み込み:Intersection Observerの基本と、画面外の動画の読み込みを0KBにした方法(シリーズ第3回)
- 【WordPress高速化】SWELLのCLSをCSSで改善:広告枠などに高さを確保して、CLSを0.14から0.0008に下げた実例(シリーズ第2回)
- 【WordPress高速化】CLSの原因を検証ツールで探す方法:検証ツールで、ずれた場所を見つけて高さを測る方法(シリーズ第1回)
※1回買えば複数サイトで使い回しOK
当サイトの記事で使用したVBAなどのサンプルをDLできます
この記事のサンプルはありません!
ダウンロードページへは下のカードをクリックすればジャンプできます。
よろしければご利用ください!


