コピペで実装!WordPressに埋め込んだYouTube動画を高速表示するカスタマイズ方法

現在WordPressはデフォルトでYouTubeのiframeに対してLazy Loadをするので、もはや以下のカスタマイズをする必要はないかと思います。

YouTube動画が埋め込まれているページは、読み込みが遅いです。

それは、以下のようにiframeが埋め込まれてYouTube動画が読み込まれるからです。

iframeでYouTube動画が読み込まれる

今回は、そのiframeをページ読み込み時は表示しないで、最初はサムネイル画像を表示させておき、クリックした時に初めてiframeを読み込むことで高速化を図る方法の紹介です。

こんな感じに。

上記はYouTubeインターフェースに外観を似せて作った動画サムネイル画像です。
スポンサーリンク
レクタングル(大)広告

カスタマイズ方法

カスタマイズの主な手順はこちら。

  1. functions.phpにコードをコピペ
  2. style.cssにコードをコピペ
  3. 画像をテーマフォルダ直下に配置

基本コピペでカスタマイズできます。

functions.phpにコードをコピペ

テーマ(子テーマ)のfunctions.phpに以下のコードを追記します。

//Jetpackとの競合対応
remove_action( 'init', 'wpcom_youtube_embed_crazy_url_init' );
//YouTube動画表示の高速化
add_filter('embed_oembed_html', 'youtube_embed_oembed_html', 1, 3);
if ( !function_exists( 'youtube_embed_oembed_html' ) ):
function youtube_embed_oembed_html ($cache, $url, $attr) {

  // data-youtubeチェック
  if (strpos($cache, 'data-youtube')) {
    preg_match( '/(?<=data-youtube=")(.+?)(?=")/', $cache, $match_cache);
    $MATCH_CACHE = $match_cache[0];
  };

  //* YouTubeキャッシュが空のときYouTubeビデオとプレイリストのためにこれらを作成する ( video_id, title, picprefix and etc for schema.org )
  if (empty($MATCH_CACHE)) {

    // YouTubeキャッシュを無視する
    if (!strpos($cache, 'youtube')) {
      return $cache;
    }

    // curlの存在確認
    if (!function_exists('curl_version')) {
      return $cache;
    }

    // 古いデータの除去
    $cache = preg_replace('/data-picprefix=\\"(.+?)\\"/s', "", $cache);
    // プレイリストIDがある場合
    if( preg_match_all( '/videoseries|list=/i', $cache, $m )){
      // プレイリストIDの抽出
      preg_match( '/(?<=list=)(.+?)(?=")/', $cache, $list );
      // ビデオIDの取得
      $json = json_decode(file_get_contents('https://www.youtube.com/oembed?url=http://www.youtube.com/playlist?list='.$list[1]), true);
      // ビデオIDの抽出
      preg_match( '/(?<=vi\/)(.+?)(?=\/)/', $json['thumbnail_url'], $video_id );
    } else {
      preg_match( '/(?<=embed\/)(.+?)(?=\?)/', $cache, $video_id );
    }

    // もしビデオIDないまだ空ならおそらくYouTubeがオフライン
    if (!$video_id[0]) {
      return $cache;
    }

    $ch = curl_init();
    $headers = array(
      'Accept-language: en',
      'User-Agent: Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari',
    );
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_URL, "https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=" . $video_id[0] . "&format=json");

    $data = curl_exec($ch);

    $info = curl_getinfo($ch);
    curl_close($ch);

    if ($info['http_code'] != 200){
      return $cache;
    }

    // YouTubeからデータが取得できなかった場合
    if (empty($data)) {
      return $cache;
    }

    // コード処理
    $data = str_replace("\\U",'\\u', $data);
    $json =  json_decode($data,JSON_UNESCAPED_SLASHES);


    // JSONが無効な場合
    if (empty($json)) {
      return $cache;
    }

    $youtube_cache  = [];
    $youtube_cache['title'] = htmlentities( $json['title'], ENT_QUOTES, 'UTF-8' );
    $youtube_cache['video_id'] = $video_id[0];


    $youtube_cache = base64_encode(json_encode($youtube_cache));

    if(isset($attr['discover']) && $attr['discover'] == 1){
      unset($attr['discover']);
    }

    $cachekey   = '_oembed_' . md5( $url . serialize( $attr ) );
    // $cache変数のアップデート
    $cache      = str_replace('src', ' data-youtube="'.$youtube_cache.'" src', $cache);

    // 新しいキャッシュを保存
    update_post_meta( get_the_ID(), $cachekey, $cache );

    $MATCH_CACHE = $youtube_cache;
  }

  $json   = json_decode(base64_decode($MATCH_CACHE), true);

  $youtube   = preg_replace("/data-youtube=\"(.+?)\"/", "", $cache);
  $youtube   = htmlentities(str_replace( '=oembed','=oembed&autoplay=1', $youtube ));

  $thumb_url  = "https://i.ytimg.com/vi/{$json['video_id']}/hqdefault.jpg";

  $wrap_start = '<div class="video-container">';
  $wrap_end   = '</div>';

  //タグの生成
  $html = $wrap_start . "<div class='video-click video' data-iframe='$youtube' style='position:relative;background: url($thumb_url) no-repeat scroll center center / cover' ><div class='video-title-grad'><div class='video-title-text'>{$json['title']}</div></div><div class='video-play'></div></div>" . $wrap_end;

  return $html;

};
endif;

//クリックしたときにiframe読み込む
add_filter( 'wp_footer', 'youtube_embed_oembed_script' );
if ( !function_exists( 'youtube_embed_oembed_script' ) ):
function youtube_embed_oembed_script(){
  ?>
  <script>
    (function(){
        var f = document.querySelectorAll(".video-click");
        for (var i = 0; i < f.length; ++i) {
        f[i].onclick = function () {
          var iframe = this.getAttribute("data-iframe");
          this.parentElement.innerHTML = '<div class="video">' + iframe + '</div>';
        }
        }
    })();
  </script>
  <?php  
}
endif;

全ての内容を説明するわけにもいかないので、簡単に書きますが、上記コードでは以下のようなことを行っています。

  • URL埋め込みを検知して高速表示用のHTMLに置き換える処理
  • フッターにクリック動作用のJavaScriptを挿入する処理

YouTube URLの埋め込み処理を検知して動作するものなので、YouTubeが生成するiframeで埋め込んでいる場合は、通常表示されます。

style.cssにコードをコピペ

次に、高速表示用のファイルをテーマ(子テーマ)のstyle.cssに追記します。

/*!動画の最大幅を指定する*/
.video-container{
  max-width:640px;
}

/*!動画の大きさを調整*/
.video-container .video {
  position: relative;
  padding-bottom: 56.25%;
  margin-top: 30px;
  height: 0;
  overflow: hidden;
  max-width: 100%;
}

.video iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.video-click {
  cursor: pointer;
}

.video-click:hover .video-play {
    background: url("youtube-play.png") no-repeat scroll -101px -13px rgba(0, 0, 0, 0);
}

.video-play {
  background: url("youtube-play.png") no-repeat scroll 2px -13px rgba(0, 0, 0, 0);
  height: 62px;
  left: 50%;
  margin-left: -45px;
  margin-top: -33px;
  position: absolute;
  top: 50%;
  width: 100px;
  opacity: 0.8;
}

.video-title-grad {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABiCAQAAAA7fHH2AAAAQUlEQVQYV22KQQoAIAzDyv7/Et/oVlGZVCfkkIYamsENXESyi8vc0u/PKZ6o8+7fZ0h8ShRYnD+BFKToRJkHFpkM2hZSxuyWpEYAAAAASUVORK5CYII=");
  background-position: center top;
}

.video-title-text {
  color: #eeeeee;
  font-family: Roboto,Arial,Helvetica,sans-serif;
  font-size: 17px;
  overflow: hidden;
  padding: 12px 16px 4px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

動画を格納するコンテナの最大幅は640pxになっています。デフォルト表示サイズを調整したい場合は、数値を変更してください。

こちらのCSSをエディター用のCSSファイルで読み込めば、ビジュアルエディター上でも同様に表示されます。

画像をテーマフォルダ直下に配置

最後に以下の画像をダウンロードし、名前を変更しないでテーマ(子テーマ)フォルダー直下に配置します。

youtube-play

テーマ(子テーマ)直下とは、style.cssがあるファイルと同じ階層です。

画像をテーマ直下に名前を変更しないで配置する

ファイルの保存場所を変更する場合は、style.cssのファイルパスも変更してください。

使い方

このカスタマイズを利用するには、WordPressの「URL埋め込み形式」でYouTube URLをエディターに書き込む必要があります。

「URL埋め込み形式」といっても、簡単で単にURLをテキストでエディターの一行に対して書き込むだけです。

URL埋め込み形式でYouTubeを書き込む

動作確認

エディターにURLのみを書き込んだら、以下のように表示されます。

実写系だとこんな感じ。

注意点

今回のカスタマイズは、WordPressのURL埋め込みのみに対応しています。

通常のiframeで埋め込んだYouTube動画には対応していません。また対応させる方法の質問にはお答え致しかねますのでご了承ください。

また、すべての動画に対応できるかの保証も致しかねます。JavaScriptが無効になっているブラウザではクリックしても再生しません。

参考

このカスタマイズは、Alexufo氏が作成したWordPressプラグイン「Youtube SpeedLoad」のコードを参考にさせていただきました。

Improve rendering speed pages with YouTube players.

まとめ

とこんな感じで、かなりYouTube動画の読み込み表示時間を短縮できるかと思います。

YouTube動画iframe風の見た目を維持しつつ、表示も高速化するという、一挙両得的なカスタマイズかと思います。

特に、動画などを多く掲載しているサイトには重宝するのではないかと。

Youtube SpeedLoadのソースコードを見たとき、いろいろな面において「なるほどそんな手があったか」と目からうろこでございました。

『コピペで実装!WordPressに埋め込んだYouTube動画を高速表示するカスタマイズ方法』へのコメント

  1. 名前:chan 投稿日:2018/09/12(水) 20:10:19 ID:1661f1504

    わいひらさん、こんばんわ。

    早速、二つをコピーして画像も子テーマにアップロードしました。

    ですが、記事のように画像の右▸マークが表示されていません。

    これは、既存の記事には対応してないと考えて良いでしょうか?

    https://chan-bike.com/tourofbritain8

    それと、新規にurlをテキストで貼りつけると、リンクカードの形式になります。

    何か、ヒントをいただけると幸いです。

  2. アバター画像 名前:わいひら 投稿日:2018/09/13(木) 22:47:30 ID:6609a2564

    こんにちは。

    僕の環境からは表示されているようです。

    それと、新規にurlをテキストで貼りつけると、リンクカードの形式になります。

    これは、実際にそういった表示になっているページのURLはありますか?

  3. 名前:chan 投稿日:2018/09/14(金) 10:47:18 ID:07959a817

    寝ログにかかれている記事なので、cocoonでは対応済みと考えてコードを消してました。
    わいひらさんが、見られた時には元に戻していた時間ではないかと思います。

    そこで、もう一つのサイトでコードと画像をアップして記事を作成しました。

    https://chan-biku.club/wordpress/youtube-speedup

    こちらでは、「URL埋め込み形式」にすると真ん中の画像が表示されていません。
    iPhoneでも表示されてなくて、2回クリックすると動画が始まります。

    リンクカード形式になることは無くなりました。

  4. アバター画像 名前:わいひら 投稿日:2018/09/14(金) 12:30:59 ID:139ec567d

    画像はどこに保存されているんですか?
    https://chan-biku.club/wp-content/themes/cocoon-child-master/youtube-play.png
    子テーマ直下にはないようですけど。