Youtube 動画の埋め込みで遅いページの高速化

最終更新日: 公開日: 2019年10月

Youtube の複数の動画を埋め込むとページ自体が非常に遅くなる(重い)時の高速化(軽量化)の方法.

原因は iframe で各動画を読み込みに行くため.

「youtube 複数 埋め込み 高速化」「youtube 複数 埋め込み 軽量化」「youtube base.js 重い」「youtube 埋め込み 重い」で検索すると説明してくれているページが多数見つかる.

軽くするのが目的なのに jQuery を使うのは本末転倒と気づいたので jQuery を使用しないで javascript オンリーで書き直しました.(2021/02/12)

Youtube

変更履歴

(2020/04/05 スマホ時に横がはみ出る場合に対応.)
(2020/05/12 縦の長さも横幅を縮小した割合で縮小するように修正.)
(2020/05/21 最大化ボタンを有効化.)
(2020/06/10 自作サムネイルに対応.)
(2020/10/09 サムネイルを高精細な画像に変更.mqdefault.jpg の代わりに maxresdefault を使用)
(2020/10/14 デフォルトは mqdefalut.jpg を使い,高精細にしたい場合は data-img="maxresdefault" と指定して画像を変更できるように変更)
(2021/02/12 jQuery を使わない方法に大幅書き替え)
(2021/03/30 IEへの対応のさせ方を記載)
(2022/12/19 alt属性に対応)
(2024/01/19 width, height を入れなくても自動で対応)

高速化の方法は二つ

やり方としては大きく二つあって,

  • 最初から iframe を使わないように記述し,クリックで iframe にする方法
  • ソースはいじらず,一旦,動画(iframe)をサムネイル(img)に変更しておいて,クリックされたときにまた,iframe に戻す方法

参考にしたページは前者の方法だと,
【デモあり】YouTubeの読み込みを軽くする!複数動画埋め込みページを高速化

後者の方法だと
YouTube動画の埋め込みを軽くする

どちらも分かりやすいので,どちらも試してみたところ,当然ながら体感ではどちらも速くなる.

PageSpeed Insights で計測するとパソコンの方で後者が遅くなる.
chrome の開発者ツールの Network で見てみると,後者の方法は iframe の部分が pending となっている.どうやら途中までは読み込んでいるようだ.

つまり,出来るだけ高速を目指すなら,前者の方法で最初から iframe は書き替えておく方がよいようだ.

ただし,それだと既存のサイトに多数の youtube を埋め込んでいる場合に面倒.
よって,出来るだけ変更作業の負担を軽くする方法はないかを考えると,src やめればいいんじゃないかと気が付いた.
しかし,既に気づいていた先人のサイトを見つけた.

埋め込みyoutubeが想像以上に戦犯級だった件
src を data-src に代えていた.これがいい.

これらの良いところを使わせてもらって作ってみた.

できるだけ Youtube に似せる

先ほどのサイトでは fontawesome を使っているので,再生ボタンが明らかにYoutube のそれと違う.

そこで,YouTube動画の埋め込みを軽くするのページで見つけたYouTube ブランドの 使用についてからアイコンをダウンロードしてきて,出来るだけ本物に近づけることにした.

ソース

上記リンクサイトからいろいろ頂いて作っています.

縦長動画のサムネイルにも対応

Youtube のサムネイル画像は自由に変更できるが,個人認証をしないと使えません.
また,標準のサムネイルは問答無用で横長タイプになります.
このライブラリでは縦長動画のサムネイルにも簡単に対応できます.

自動再生

chrome では iframe に allow="autoplay" をつけないと現状では自動再生になりませんでした.
自動的に autoplay を付加するようにしています.

javascript

ソースはfastyt.nojq.js
上記リンクを右クリックして,「ファイルを保存」するとソースが保存される.
(古いバージョンは fastyt.js こちらは jQuery 必須となっています.)
普通に左クリックすればソースを見ることが出来ます.

/*
  YouTube 初回表示軽量化スクリプト
  Copyright Rectus Inc, 2024/01/19 Ver 1.03
  javascript版
  https://www.rectus.co.jp/
  Released under the MIT license
 */

document.addEventListener("DOMContentLoaded", function() {
  var srcs = [];
  var images = [];
  var heights = [];
  var widths = [];
  var thumbs = [];
  var imgs = [];
  var alt = [];

  var fyt = document.getElementsByClassName('fastyt');
  var fy = Array.prototype.filter.call(fyt, ele => ele.nodeName === 'IFRAME');

  // 全ての iframe.fastyt に対して処理を実行
  Array.prototype.forEach.call(fy, function(ele, index) {
    var img;
    
    // 属性を配列に格納
    srcs[index] = ele.getAttribute('data-src');
    heights[index] = ele.getAttribute('height');
    widths[index] = ele.getAttribute('width');
    thumbs[index] = ele.getAttribute('data-thumbnail');
    imgs[index] = ele.getAttribute('data-img');
    alt[index] = ele.getAttribute('data-alt');
    maxWidth = getAncestorWidth(ele);

    img = 'mqdefault';
    if (imgs[index]) {
      img = imgs[index];
    }

    // サムネイルのサイズ指定に応じてサイズを代入
    if (widths[index] === null) {
      switch (img) {
      case 'default':
        widths[index] = 120;
        heights[index] = 90;
        break;
      case 'mqdefault':
        widths[index] = 320;
        heights[index] = 180;
        break;
      case 'hqdefault':
        widths[index] = 480;
        heights[index] = 360;
        break;
      case 'sddefault':
        widths[index] = 640;
        heights[index] = 480;
        break;
      case 'maxresdefault':
        widths[index] = 1280;
        heights[index] = 720;
        break;
      }
    }

    // 取りうる最大幅を超えている場合はそこまでにする.
    if (maxWidth < widths[index]) {
      heights[index] = Math.floor(heights[index] * maxWidth / widths[index]);
      widths[index] = Math.floor(maxWidth);
    }

    // URL から動画 id のみを取得して文字連結をしてサムネイルを取得
    var id = srcs[index].match(/[\/?=]([a-zA-Z0-9_-]{11})[&\?]?/)[1];
    if (thumbs[index]) {
      images[index] = thumbs[index];
    } else {
      // 高精細にしたい場合は data-img="maxresdefault" を指定
      images[index] = '//img.youtube.com/vi/' + id + '/' + img + '.jpg';
    }

    // iframeをサムネイル画像に置換
    var divyt = document.createElement("div");
    divyt.className = "yt";
    divyt.style.width = widths[index] + 'px';
    divyt.style.height = heights[index] + 'px';
    var divyt_play = document.createElement("div");
    divyt_play.className = "yt_play";
    var imgmovie = document.createElement("img");
    imgmovie.className = "recmovie";
    imgmovie.setAttribute("src", images[index]);
    imgmovie.setAttribute("alt", alt[index]);
    imgmovie.setAttribute("loading", "lazy");
    imgmovie.width = widths[index];
    imgmovie.height = heights[index];
    divyt_play.appendChild(imgmovie);
    divyt.appendChild(divyt_play);
    ele.parentNode.insertBefore(divyt, ele.nextElementSibling);
    
    ele.remove();
  });

  var ytp = document.getElementsByClassName('yt_play');
  Array.prototype.forEach.call(ytp, function(ele, index) {
    // サムネイルがクリックされた時の処理
    ele.addEventListener('click', function (){
      // iframeに置換
      var autoplay;
      if (0 < srcs[index].indexOf("?")) {
        autoplay = '&';
      } else {
        autoplay = '?';
      }
      autoplay += "autoplay=1";
      var ifr = document.createElement("iframe");
      ifr.className = "recmovie";
      ifr.setAttribute("src", srcs[index] + autoplay);
      ifr.setAttribute("allow", "autoplay");
      ifr.setAttribute("allowfullscreen", "allowfullscreen");
      ifr.width = widths[index];
      ifr.height = heights[index];
      ele.parentNode.replaceChild(ifr, ele);
    })
  }, false);
});

function getAncestorWidth(ele) {
  if (ele.parentNode === undefined) {
    return ele.offsetWidth;
  }
  width = ele.parentNode.offsetWidth;
  if (width == 0) {
    width = getAncestorWidth(ele.parentNode);
  } else {
    width = ele.parentNode.offsetWidth;
  }
  return width;
};

IE の場合は2か所書き替える必要がある.

17行目

var fy = Array.prototype.filter.call(fyt, function(ele) {if (ele.nodeName === 'IFRAME') {return ele}});

67行目

ele.parentNode.removeChild(ele);

CSS

ソースはfastyt.css
上記リンクを右クリックして,「ファイルを保存」するとソースが保存される.
(2020/05/11 ご指摘を受けて修正.IE で表示が崩れるところがありました.)

@charset "utf-8";

.yt {
  position:relative;
}
.yt_play {
  position: absolute;
}
.yt_play:hover {
  cursor:pointer;
}
.yt_play::before { /* YouTubeアイコン */
  position: absolute;
  background: url(/images/yt_icon_mono_light.png);
  content: "";
  background-size: 100%;
  width: 70px;
  height: 50px;
  top: 50%;
  left: 50%;
  transform : translate(-50%,-50%);
  opacity: .90;
  transition:.5s;
}
.yt_play:hover::before { /* YouTubeアイコン */
  cursor: pointer;
  background-image:url(/images/yt_icon_rgb.png);
}

再生ボタンのアイコンは youtube からダウンロードしてきた png の画像を使いました.

/images/yt_icon_rgb.png
赤の再生ボタン

/images/yt_icon_mono_light.png
灰色背景の再生ボタン

javascript と css で納得いかない部分がありましたら自由に変えて下さい.

iframe で width と height を入れ,class で fastyt を指定してください.

埋め込み手順・方法

必要なファイルのダウンロード

スタイルシート

fastyt.css

javascript

fastyt.nojq.js

Youtube の再生ボタン用画像

YouTube ブランドの 使用について
の真ん中より少し下にある「YouTube アイコン」のところ

これらを自分のサイトの適切な場所に置きます.

該当ソースの変更

動画を埋め込んでいるページを変更します.

以下をヘッダなどに入れます.

<script src="/js/fastyt.nojq.js" type="text/javascript"></script>
<link href="/css/fastyt.css" rel="stylesheet" type="text/css">

以下の動画のタグは埋め込みたい場所に入れます.

<iframe class="fastyt" data-src="//www.youtube.com/embed/動画ID" data-alt="動画の説明" width="300" height="169"></iframe>

width と height は埋め込みたい動画のサイズに変更します.

独自のサムネイルを使いたい場合は,iframe の中に data-thumbnail="サムネイルのURL" のように記述します.(2020/06/10)
Youtube に存在しているサムネイルに高精細画像を表示したい場合は data-img="maxresdefault" を追加して記述する.(2020/10/14)
data-alt に img タグの alt 属性を入れておけば,img になった時に alt属性として挿入される.(2022/12/19)
width と height を入れなくても表示できるように変更.指定できるサムネイルの画像サイズは default, mqdefault, hqdefault, sddefault, maxresdefault (2024/01/19)

埋め込みの一例

埋め込み例(youtube最初の動画)

速度(スピード)測定サイト

動画が挿入されたページを軽量化するFAQ

どのような方法で軽くしますか?
表示しただけでは動画を読み込まないようにしています.
どのように実装しますか?
javascript と CSS を読み込んで動画読み込み部分の動作を変更します.HTML も少し変更します.

PageSpeed Insights 対策

PageSpeed Insights 対策の一覧.他の対策は以下を見てください.
 

Contact

ご質問等ありましたら,お手数ですが弊社の個人情報保護方針をお読み頂いた上でフォームからお願い致します.
※このページと無関係な内容のセールスはご遠慮ください.

 
   
contact
Pagetop