AVPlayerにおける再生開始制御
やりたいこと
TL;DR
理想的な制御
再生開始は
開始が早すぎると、すぐに stall してしまう
開始が遅すぎると、ユーザ体験が悪くなる
stall せずに視聴し続けられる最も早いタイミング で再生を開始したい!
どう検知すれば良いのか?
iOS 9 以前
AVFoundation のアルゴリズムによって、「このまま読み込み続ければ、今再生開始しても最後まで stall せずに再生し続けられそうだ」と判断された場合に true となる この判断元の情報には、I/O スループットや、再生メディアのデコードのパフォーマンスなどがある
再生用のバッファが容量に達した場合に true となる
バッファが満タンになっても、予測のための統計情報が揃っておらず、playbackLikelyToKeepUp が false のままになる可能性もある
stall 中、あるいは stall しそうになっている場合に true
HTTP Progressive Download では、 playbackLikelyToKeepUp もしくは playbackBufferFull が true になるまで、AVPlayer の AVPlayer.rate を 1 に設定するのを待つ必要があった。然もなくば、stall した段階で再生が停止してしまい、AVPlayer.rate が 0 に戻ってしまう。 一方 HLS では、AVPlayer.rate を一度 1 に設定しさえすれば、stall してもその状態は持続しつつ、再び再生可能な状態になったら自動で再生を開始してくれた。 iOS 10 以降
この挙動は iOS 10 で、HLS 側の振る舞いに寄せることができるようになった。つまり、HTTP Progressive Download も HLS も、AVPlayer.rate を一度 1 に設定してしまえば、そのあとは stall しても再び AVPlayer.rate を設定し直す必要は無い、という挙動を設定できるようになった。 このプロパティが true の時に AVPlayer の rate が0から0以上に変化した場合、「変化後の rate で stall せずに最後まで再生可能か?」が予測される。予測の結果、途中で stall しそうであれば、再生が一時停止した上で timeControlStatus が .waitingToPlayAtSpecifiedRate に切り替わり、stall する可能性が最小化した段階で自動的に再生が再開される。あるいは、再生中に再生バッファが底を尽きて stall してしまった場合にも、同様に stall する可能性が最小化した段階で自動的に再生が開始される。 このプロパティが false の時に再生が要求された場合、再生バッファが空でさえなければ即座に再生が開始される。その後もし再生バッファが底を尽きて stall した場合、timeControlStatus は .paused に、rate は 0 に変化する。stall 最小化のために .waitingToPlayAtSpecifiedRate であった最中にこのプロパティを false に切り替えた場合にも、即座に再生が開始される。 しかし、このプロパティが true に設定されている状態で、かつ iOS 9 以前の HTTP Progressive Download の振る舞いを再現したい場合がある。つまり、再生バッファがたまるまで ≒ playbackLikelyToKeepUp が true になるまで待機せず、明示的に、即座に再生したい 場合がある。この挙動をサポートする API として、playImmediately(atRate:) が iOS 10 から提供されるようになった。この API を利用すれば、再生バッファの状態を考慮せずに強制的に再生を開始させることができる。 WWDC の発表から持ってきた図を引用すると、再生の状態は下記のように移り変わる。
https://gyazo.com/897d17454a69fdea8f0497a65ffd54b7
参考