Youtube iframe APIを活用した同時再生防止のテクニック
Youtubeの規約では同時再生は規約違反
同時再生は規約違反になるので、一つしか再生されないようにする方法を記載していきます。
下記参考
まずは、youtube iframe apiのjsを読み込む
scriptタグに下記のsrcを読み込む
この時点でconsoleに`YT`と打って存在すれば読み込めています
<script src="https://www.youtube.com/iframe_api"></script>
iframeでYouTubeを読み込む
`?enablejsapi=1`のqueryはapiを使う上で必須です。
styleはいい感じに調整してください
<div>
<iframe width="50%" height="315" src="https://www.youtube.com/embed/eB0arUZ-63I?enablejsapi=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<iframe width="50%" height="315" src="https://www.youtube.com/embed/eB0arUZ-63I?enablejsapi=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<iframe width="50%" height="315" src="https://www.youtube.com/embed/eB0arUZ-63I?enablejsapi=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<iframe width="50%" height="315" src="https://www.youtube.com/embed/eB0arUZ-63I?enablejsapi=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
playerのinstanceを生成する
`querySelectorAll`でiframeを取得する
mapでinstanceを生成して、instanceの配列を生成
第一引数にはiframeのdomかidを入れる
`onStateChange`のeventに関数を登録する
`onStateChange`とはyoutubeの状態に変更があった場合にtriggerされるeventです。
今回は`再生`をtriggerしたいので使用しています。
// domを取得(取得方法は自由でOK)
var iframes = Array.from(document.querySelectorAll('iframe'));
var players = iframes.map((iframe) => {
// 第一引数にはiframeのdomかidを入れる(下記はdomの例)
return new YT.Player(iframe , {
events: {
// ↓ここにステータスが変わった時に発火して欲しい関数を入れる
'onStateChange': onPlayerStateChange,
},
});
});
再生されていたら、他を止める処理
先ほど`onStateChange`に登録した関数に処理を書いていく
引数には、`data`(status そのプレイヤーの状態)と`target`(player そのもの)が入っています。
今回は`target`のみを使用するので、引数で受け取る。
triggerとなった再生を開始した、playerは再生を停止したくないので、ループして、同一のplayerだった場合returnする。
`player.getPlayerState()`でplayerの状態を取得(再生中は1が入る)※状態一覧は下記記載
`player.stopVideo()`で他の再生中の動画を止める。
const onPlayerStateChange = ({ target }) => {
// ループしてplay中の動画があるかチェック
players.forEach((player, index) => {
// targetと同じ場合はreturn
if (target === player) return ;
// プレイヤーのステータスを取得
let state = player.getPlayerState();
// プレイ中のものは再生を止める
if (state === YT.PlayerState.PLAYING) {
player.stopVideo();
}
});
};
`YT.PlayerState`の中身は下記のような定数
BUFFERING: 3 CUED: 5 ENDED: 0 PAUSED: 2 PLAYING: 1 UNSTARTED: -1
登録したeventとinstanceの破棄
ページを離れた時に破棄しましょう
destroyはeventのremoveとinstanceの破棄も兼ねていますs
players.forEach((player) => {
player.destroy();
});
デモ
これで下記のように再生中に他の動画を再生したら、元々再生されていた動画が止まっていますね
エラーが出た場合の対策
エラー内容
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.youtube.com') does not match the recipient window's origin ('http://localhost').
このエラーは、originが違うよーと言うエラーです(httpsとhttp)
起きる例としてiframeに`loading="lazy"`がついていると画面外にあるまだロードしていない、iframeに対して、instanceを生成しようすると起こるエラーです。
エラーについての記事は下記をご参考にしてくください
対策としてloadした時に、instanceを生成してあげる
iframeのload eventに関数を登録
iframes.forEach((iframe) => {
iframe.addEventListener('load', onLoad);
});
loadしたタイミングでinstanceを生成する
// loadが完了したらinstanceを生成
let onLoad = (e) => {
// loadが終わっているものは弾く
if (e.currentTarget.dataset.loaded === 'true') return ;
// loadしたらloadedにtrueを入れておく
e.currentTarget.dataset.loaded = 'true';
// playerのinstanceを生成
player = new YT.Player(iframe , {
events: {
'onStateChange': onPlayerStateChange,
},
});
}
まとめ
同時再生対策する際にぜひ参考にしてみてください!
この記事が気に入ったらサポートをしてみませんか?