Youtube埋め込み動画をプレイヤーコントロールを介さず動かす
この記事では、埋め込み動画の Youtube プレーヤーの再生ボタンやシークバーなどのコントロールを使わずに、JavaScript で動画の再生・一時停止や再生位置の移動を行う方法について説明します。また、HTMLコントロールからYoutubeプレイヤーを操作する実装例を紹介します。説明の動画例には Google アプリの CM 動画を使います。
動画の埋め込み
自分で書く必要はありません。目的の動画の「共有」メニューから「動画の埋め込み」を開くと、次のようなタグを自動生成してくれます。特定の動画を埋め込む場合でも、src
属性を変更して読み込む動画を動的に指定する場合でも、ベースは同じです。
<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 プレーヤーを操作するようなケースでは、次のようにフォーカスを当てておくとよいでしょう。
const target = (<iframe>への参照)
target.contentWindow.focus()
まとめ
- Youtube動画の埋め込みタグのテンプレは、Youtubeの動画ページの共有メニューから拾う。
- そこに
<iframe>
へのアクセス経路を作る。 -
src
属性に指定する URL に?enablejsapi=1
を付ける。
- そこに
- 動画操作インターフェースを作って楽をする。
-
<iframe>
のpostMessage()
の実行を抽象化する。
-
Discussion