IT

【HTML5 ビデオ】再生が終わったらアンケートリンクを出す方法について

疑問に思っていたこと

  • HTML5 のビデオ要素で視聴が終わったら、ポップアップ出してアンケートページへ誘導したい時はどうすればいいのだろう?

解決方法

  • ビデオ要素にendedという"ビデオの再生が完全に終了したときに発生する"イベントがあり、JS でそれを拾ってあげれば OK でした。
  • アンケート用のポップアップに関しては、CSS で指定してあげれば表示と非表示を存外簡単に切り替えられました。

実装画面

  • サンプルでは BBB(Big Buck Bunny) の動画を流して、アンケートが用意できなかったので Fanza のリンクに飛ばします。
  • 動作としては、再生 → 最後の方まで先送り → 再生終了 → ポップアップ表示 →Fanza に遷移を確認します。

サンプルコード

  • CSS は Tailwind 利用
  • 上記以外はライブラリを用いない Pure な JS を利用
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ビデオ視聴後ポップアップ</title>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
  </head>

  <body class="bg-gray-100 min-h-screen font-sans">
    <div class="container mx-auto px-4 py-8">
      <h1 class="text-3xl font-bold text-center text-gray-800 mb-8">
        ビデオコンテンツ
      </h1>

      <div
        class="max-w-3xl mx-auto bg-white rounded-lg shadow-md overflow-hidden relative"
      >
        <!-- ビデオコンテナ -->
        <div class="relative" id="video-container">
          <video id="myVideo" class="w-full h-auto" controls>
            <source src="{MP4ファイルへのリンク}" type="video/mp4" />
            お使いのブラウザはビデオタグをサポートしていません。
          </video>

          <!-- オーバーレイ -->
          <div
            id="overlay"
            class="absolute inset-0 bg-black bg-opacity-70 hidden"
          ></div>

          <!-- ポップアップ -->
          <div
            id="popup"
            class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg shadow-xl p-6 w-4/5 max-w-md z-10 hidden"
          >
            <h2 class="text-2xl font-semibold text-gray-800 mb-3">
              アンケートにご協力ください
            </h2>
            <p class="text-gray-600 mb-6">
              ビデオをご視聴いただきありがとうございます。アンケートにご回答いただけますか?
            </p>
            <div class="flex justify-end space-x-3">
              <button
                id="closeBtn"
                class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-100 transition-colors duration-200"
              >
                閉じる
              </button>
              <button
                id="redirectBtn"
                class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-200"
              >
                アンケートに回答する
              </button>
            </div>
          </div>
        </div>

        <!-- ビデオ情報エリア(オプション) -->
        <div class="p-5">
          <h2 class="text-xl font-semibold text-gray-800 mb-2">
            ビデオタイトル
          </h2>
          <p class="text-gray-600">
            このビデオでは、重要な情報をご紹介しています。ご視聴後のアンケートにもぜひご協力ください。
          </p>
        </div>
      </div>
    </div>

    <script>
      document.addEventListener("DOMContentLoaded", function () {
        const video = document.getElementById("myVideo");
        const popup = document.getElementById("popup");
        const overlay = document.getElementById("overlay");
        const redirectBtn = document.getElementById("redirectBtn");
        const closeBtn = document.getElementById("closeBtn");

        // Tailwindの「hidden」クラスを使ってポップアップを表示/非表示にする関数
        function showPopup() {
          popup.classList.remove("hidden");
          popup.classList.add("block");
          overlay.classList.remove("hidden");
          overlay.classList.add("block");
        }

        function hidePopup() {
          popup.classList.add("hidden");
          popup.classList.remove("block");
          overlay.classList.add("hidden");
          overlay.classList.remove("block");
        }

        // ビデオ再生終了時のイベントリスナー
        video.addEventListener("ended", function () {
          showPopup();
        });

        // アンケートボタンクリック時の処理
        redirectBtn.addEventListener("click", function () {
          window.location.href = "{アンケートページへのリンク}";
        });

        // 閉じるボタンクリック時の処理
        closeBtn.addEventListener("click", function () {
          hidePopup();
        });
      });
    </script>
  </body>
</html>

おまけ

よく使いそうなイベント一覧

  • loadstart - メディアの読み込みが開始された
  • progress - メディアのダウンロード中に発生
  • loadedmetadata - メディアのメタデータが読み込まれた
  • loadeddata - メディアの最初のフレームが読み込まれた
  • canplay - メディアが再生可能になった
  • play - 再生が開始された
  • pause - 再生が一時停止された
  • timeupdate - 現在の再生位置が変更された
  • ended - 再生が終了した
  • error - エラーが発生した

timeupdateを利用すれば、何%まで視聴されたら表示するのようなことが可能になります。

video.addEventListener("timeupdate", function () {
  // ビデオの総再生時間の取得
  const duration = video.duration;
  // 現在の再生位置の取得
  const currentTime = video.currentTime;

  // ビデオの90%まで再生された場合
  if (currentTime / duration >= 0.9 && !popupShown) {
    popup.style.display = "block";
    overlay.style.display = "block";
    // フラグを設定して、ポップアップが一度だけ表示されるようにする
    popupShown = true;
  }
});

// ページ読み込み時にフラグを初期化
let popupShown = false;

HLS だと、SCTE-35 とかの広告マーカーを仕込んだりする部分感じですね。

SCTE-35 について

SCTE-35 は、デジタル放送やストリーミング配信において広告挿入ポイントやプログラム区切りを示すためのマーカー規格です。放送業界では、このマーカーを使って自動的に広告を挿入したり、番組の区切りを示したりします。

広告以外にも、以下の用途で利用可能です。

  • 視聴者が特定のセグメントを視聴した後にアンケートを表示
  • コンテンツの重要な区切り(章や単元など)でナビゲーションメニューを表示
  • 特定の教育コンテンツ視聴後にクイズを表示

以上。

  • この記事を書いた人

緑川縁

ニートからシステムエンジニアになった人
クラウド案件をメインにやっています。
保持資格:CCNA,AWS SAA&SAP,秘書検定2級
趣味でボカロ曲作り始めました。

-IT
-,