🎮

Youtube埋め込み動画をプレイヤーコントロールを介さず動かす

2022/10/24に公開

この記事では、埋め込み動画の Youtube プレーヤーの再生ボタンやシークバーなどのコントロールを使わずに、JavaScript で動画の再生・一時停止や再生位置の移動を行う方法について説明します。また、HTMLコントロールからYoutubeプレイヤーを操作する実装例を紹介します。説明の動画例には Google アプリの CM 動画を使います。

動画の埋め込み

自分で書く必要はありません。目的の動画の「共有」メニューから「動画の埋め込み」を開くと、次のようなタグを自動生成してくれます。特定の動画を埋め込む場合でも、src 属性を変更して読み込む動画を動的に指定する場合でも、ベースは同じです。

Youtube埋め込みタグ(読まなくてOK)
<iframe width="560" height="315" src="https://www.youtube.com/embed/ef41Q2-DQ2Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

動画の操作はこの iframe 要素を介して行うので、jQuery なら id を指定してセレクタを作成するなり、Vue.js なら <iframe> に ref 属性をつけるなりと、使用するフレームワークに合わせてアクセス経路を確保してください。また、外部操作を有効化するため URLに ?enablejsapi=1 パラメータをつけてください。

外部操作の有効化
<iframe src="https://www.youtube.com/embed/***?enablejsapi=1" (略) ></iframe>

このURLは、一般的な動画ページのURLや短縮リンクとは構造が違うので、手動で直さずに埋め込みタグから持ってくることをオススメします。

URL
共有リンク(外部操作を有効) https://www.youtube.com/embed/ef41Q2-DQ2Q?enablejsapi=1
一般的な動画ページ https://www.youtube.com/watch?v=ef41Q2-DQ2Q
動画ページの短縮リンク https://youtu.be/ef41Q2-DQ2Q

パラメータの詳細は YouTube IFrame Player API の公式ドキュメントに書いてあります。

動画操作インターフェース

再生、停止といった命令は、iframe.contentWindow.postMessage() 関数を介して送信します。フォーマットが決まっているので、色々な操作をさせるのであればインターフェースを作っておくと楽です。シーク(再生位置を指定した秒数へ変更)のような引数をとる命令もあるので、それにも対応しています。

動画操作インターフェース
/**
 * @param target 操作する要素のオブジェクト
 * @param method 命令の文字列
 * @param args 命令の引数の配列(任意)
 */
sendVideoControl (target, method, args) {
    const _args = args !== undefined ? JSON.stringify(args) : '""'
    target.contentWindow.postMessage(`{"event":"command","func":"${method}","args":${_args}}`, '*')
}

postMessage() は Window オブジェクト間の通信に使う関数で、これを利用して動画操作情報を送信します。

参考:Window.postMessage() - Web API | MDN

操作メニューの実装例

例えば、次のような HTML の操作メニューに対応するイベントハンドラを用意します。何をしているのかを直感的に伝えるために Vue.js の実装例を紹介しますが、やっていることの本質は HTML のコントロールにイベントハンドラを紐づけて、適切なパラメータで動画操作インターフェース(sendVideoControl())を実行することです。

埋め込みタグ
<iframe ref="embed" :src="url"
    width="560" height="315" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
操作メニュー
<div class="controller">
    <button @click="onStop"></button>
    <button @click="onPause">||</button>
    <button @click="onPlay"></button>
    <input type="number" min="0" v-model="seekPosition" />
    <button @click="onSeek">シーク</button>
</div>
イベントハンドラ
data () {
    return {
        url: 'https://www.youtube.com/embed/ef41Q2-DQ2Q?enablejsapi=1',
        seekPosition: 0 // シーク位置
    }
},
methods: {
    onPlay () {
        this.sendVideoControl(this.$refs.embed, 'playVideo') // 再生
    },
    onPause () {
        this.sendVideoControl(this.$refs.embed, 'pauseVideo') // 一時停止
    },
    onStop () {
        this.sendVideoControl(this.$refs.embed, 'stopVideo') // 停止(一時停止+再生位置を0秒に)
    },
    onSeek () {
        this.sendVideoControl(this.$refs.embed, 'seekTo', [this.seekPosition]) // 指定秒数へシーク
    }
}

ここでは再生、一時停止、停止、シークを紹介しました。詳細な再生制御については、iframe 組み込みの YouTube Player API リファレンス > 再生の制御とプレーヤーの設定を参照してください。やりたい操作の関数名(と引数の配列)を method(と args)に指定すれば、色々なことができるはずです。

かゆいところ:読み込んだ Youtube プレーヤーに自動フォーカスさせる

ページに読み込んだ Youtube プレーヤーに初めてクリックする時、動画のコントロールが反応せず、二回目以降のクリックで反応することがあります。これは表示したタイミングで <iframe> にフォーカスが当たっていないことが問題です。ユーザがページを開いてすぐに Youtube プレーヤーを操作するようなケースでは、次のようにフォーカスを当てておくとよいでしょう。

Vue.js ならmounted()で実行する
const target =<iframe>への参照)
target.contentWindow.focus()

まとめ

  • Youtube動画の埋め込みタグのテンプレは、Youtubeの動画ページの共有メニューから拾う。
    • そこに <iframe> へのアクセス経路を作る。
    • src 属性に指定する URL に ?enablejsapi=1 を付ける。
  • 動画操作インターフェースを作って楽をする。
    • <iframe>postMessage() の実行を抽象化する。

Discussion