1つのWebページ内に複数のYouTubeプレーヤーを配置する場合、
常に再生されるのは1つのプレイヤーに限定しなければ利用規約違反になるそうで。
※なお、iOSやAndroidでも同時再生が規約違反なのは同じ。
ぶっちゃけ注意のメールが来るまで知らなかった🙄
WordPressでembedしたやつとか普通に同時再生なるし、今更?と思ったが
3営以内にどうにかしろと大本営に言われたらやるしかないので、
対策がてらサンプルを作ってみた。
Vue.jsで管理するサンプル
妹が好きなバンドのPVを1個だけ再生するぞ。
See the Pen Example of YouTube component playing only one video at a time by Tenderfeel (@Tenderfeel) on CodePen.
YouTubeのiFrame Player APIそのものは変わってないので、昔書いた記事とやり方は同じ。
コンソール見るとpostMessageのエラー出てますが、
Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://www.youtube.com’) does not match the recipient window’s origin
console.error
originを設定したり色々試したけど消せなかったんで諦めた。
embedUrl() {
return `//www.youtube.com/embed/${this.data.id}?rel=0&playsinline=1&enablejsapi=1&origin=${window.location.origin}`;
}
確認中iOS12系だとインライン再生できない不具合があった。(バッファリングで勝手に止まる)iOS13はなんともない。
以下要点の説明
Appコンポーネント
App.created
APIのスクリプトタグ追加してイベントハンドラ設定している。
イベントハンドラでは dataのyoutubeApiReady
を変更する。
created() {
const tag = window.document.createElement('script');
tag.src = '//www.youtube.com/iframe_api';
tag.async = true;
const firstScriptTag = document.querySelector('script');
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeAPIReady = () => {
console.log('YouTube API Ready')
this.youtubeApiReady = true;
};
},
App.methods.onYouTubeStateChange
Youtubeコンポーネントのchangeイベントに渡すイベントハンドラ。
新しいプレイヤーの再生が始まった時、すでに再生中のプレイヤーがあれば停止する。
methods: {
onYouTubeStateChange({ player, status }) {
if (status !== window.YT.PlayerState.PLAYING) {
return;
}
if (playingVideo === null) {
playingVideo = player;
return;
}
if (playingVideo.getVideoUrl() !== player.getVideoUrl()) {
try {
playingVideo.stopVideo();
} catch (e) {
//
}
playingVideo = player;
}
}
}
YouTubeコンポーネント
YouTube.mounted
親の youtubeApiReady
を監視する。trueになったらPlayer作る。
Propsで渡してwatchで監視するでも良い。
mounted() {
this.$watch('$parent.youtubeApiReady', val => {
if (val === true) {
this.createPlayer();
}
})
},
YouTube.methods.createPlayer
iFrame要素を渡す場合でURLにパラメーターを設定しているならプレイヤー作成時のオプションを省略できる。
コールバックでカスタムイベントを$emit
する。
methods: {
createPlayer() {
this.player = new window.YT.Player(this.$refs.iframe, {
events: {
onReady: event => {
this.$emit('ready', { player: event.target });
},
onStateChange: event => {
this.$emit('change', {
player: event.target,
status: event.data
});
}
}
});
}
}
YouTube.beforeDestroy
コンポーネント破棄前にplayer.destroy()
する。
beforeDestroy() {
try {
if (this.player) {
this.player.destroy();
}
} catch (e) {
//
}
},
lazysizesに対応させる場合
YouTubeプレイヤーコンポーネントに遅延読み込みのライブラリlazysizesを使うサンプル。
div.lazyload
な要素にlazybeforeunveil
イベントハンドラを設定する。
子のdivにref="player"
を設定しておく。(iFrameでもおk)
<div class="lazyload" @lazybeforeunveil="onLazybeforeunveil">
<div ref="player" />
</div>
あとはイベントハンドラの方でプレイヤー作成するだけ。
methods: {
onLazybeforeunveil() {
this.player = new window.YT.Player(this.$refs.player, {
// ここにプレイヤーの設定
})
}
}
注意文面
どうやらYouTube使ってるサービスへ一斉に注意がきたそうな。
不正な再生数稼ぎ対策の一環らしい。
Policy #: III.C 1
YouTube API Services Form
Violation: API Client is allowing multiple players playing parallel in a web page.
Proposed Solution: As per YouTube terms of services & policies in a page only one video should be played at a time. In case there are multiple videos on that page make sure that only one player must be active at a time in each and every page of your website wherever applicable.