起きたこと
Youtube動画を背景要素として再生させ続ける実装をしていたが、
OS X 上のSafariで表示するとバッファリング状態で停止し続ける現象が起こった。
バッファリング状態から自動で再生開始されるのが期待される動作なのだが、どうも再生されない。
別の動画を試すとバッファリング状態にすらならなかったりするので、
もしかすると元のアップロードされている動画のサイズやYoutube動画側の設定の影響かもしれないが、
なんとか再生させ続ける方法が見つかったので共有です。
回避方法
(根本的な解決ではないので、回避方法としています)
動画プレーヤーのステータスを監視して、バッファリング状態になったら、0.1秒先にシークする。
バッファリングの状態の時に、コントロールバーを表示してシークバーで再生位置を変えると
Safariでも再生が再開されるということをデバッグ中に気づいたので、
じゃあバッファリング状態になったらちょっと先にシークするようにすれば、
停止はしないんじゃないかと思い実装したら、期待の通りに動いてくれました。
⚠️ 僕が扱った動画はミュート状態での再生だったため、見た目上あまり気になりませんが、
音込みでの再生だった場合、気になる部分出てくるかもしれませんね。
コード
⚠️ パラメーターなどの詳細については、ドキュメントを見てください
https://developers.google.com/youtube/js_api_reference?hl=ja
// 埋め込んだ iframe 要素 *Youtubeの動画IDはXXXXXとして伏せています。
// <iframe id="video" frameborder="0" allowfullscreen="1" title="YouTube video player" src="https://www.youtube.com/embed/XXXXX?autoplay=0&loop=0&playlist=XXXXX&rel=0&showinfo=0&controls=0&enablejsapi=1"></iframe>
/**
* [init description]
* @param {string} targetID iframe の id名
*/
function setYoutube(targetID){
var tag = document.createElement('script')
, firstScriptTag = document.getElementsByTagName('script')[0]
, _this = this
;
window.onYouTubeIframeAPIReady = function() {
loadPlayer();
};
tag.src = 'https://www.youtube.com/iframe_api';
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onPlayerReady() {...}
function onPlayerStateChange(event) {
switch (event.data) {
case YT.PlayerState.BUFFERING:
// バッファリングステータスになったら、0.1秒先にシークする
_this.player.seekTo(_this.player.getCurrentTime() + .1);
break;
default:
}
}
function loadPlayer(_videoID) {
if(!_this.player){
_this.player = new YT.Player(
target, {
// iframeで埋め込んでいるのでtargetなど指定なし
// クエリもiframeのに直接指定しているのでここで指定なし
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
} else {
_this.player.loadVideoById(_videoID);
}
}
}
感想
背景でループ再生させる動画はできるだけ短いものにしたい。
ユーザーはおそらく、あまり動画を見ていない。
ローディング時間が増えて辛くなるだけだぞ。