web-dev-qa-db-ja.com

iOS AVPlayerの開始遅延を減らす方法

以下の質問に注意してください。すべてのアセットはデバイス上でローカルです。ネットワークストリーミングは行われていません。ビデオにはオーディオトラックが含まれています。

私は、問題のビデオクリップを開始するために最小限の遅延でビデオファイルを再生する必要があるiOSアプリケーションで作業しています。残念ながら、実際に起動する必要があるまで、特定のビデオクリップが次に何であるかはわかりません。具体的には、1つのビデオクリップが再生されると、次の(大まかに)10個のビデオクリップのセットが何であるかがわかりますが、次のクリップを「すぐに」再生するときが来るまで、どのクリップが正確かはわかりません。

実際の開始遅延を確認するために行ったのは、ビデオプレーヤーでaddBoundaryTimeObserverForTimesを呼び出して、ビデオが実際に再生を開始した時間を1ミリ秒の時間で確認し、その時間の差を取ることです。再生を開始するアセットを示すコードの最初の場所にスタンプを付けます。

これまで見てきたことから、AVAssetロードの組み合わせを使用し、準備ができたらそこからAVPlayerItemを作成し、AVPlayerStatusReadyToPlay playを呼び出す前に、クリップを開始するのに1〜3秒かかります。

それ以来、ほぼ同等と思われるものに切り替えました。[AVPlayerItem playerItemWithURL:]を呼び出し、AVPlayerItemStatusReadyToPlayの再生を待機しています。ほぼ同じパフォーマンス。

私が観察していることの1つは、最初のAVPlayerアイテムのロードが他のアイテムよりも遅いことです。 1つのアイデアは、最初のビデオを再生する前にAVPlayerを短い/空のアセットでプリフライトすることが一般的な慣例であると思われることです。 [ サウンドが最初に再生されるときのAVAudioPlayerのスロースタート

ビデオの開始時間をできる限り短くし、実験すべきことについていくつかのアイデアを持ちたいと思っていますが、手助けできる人からのガイダンスが欲しいです。

更新:以下のアイデア7、実装されたままの状態では、スイッチング時間は約500ミリ秒になります。これは改善されていますが、これをさらに速くするのはいいことです。

アイデア1:N個のAVPlayerを使用する(機能しない)

〜10個のAVPPlayerオブジェクトを使用して、〜10個すべてのクリップを開始および一時停止し、必要なクリップがわかったら、正しいAVPlayerに切り替えて一時停止を解除し、すべてを開始します次のサイクルのためにもう一度。

IOSでのアクティブなAVPlayer'sの制限はおおよそ4つであると読んだため、これが機能するとは思わない。 StackOverflowでこれについて尋ねている人がいて、4つのAVPlayerの制限について知りました: fast-switching-between-videos-using-avfoundation

アイデア2:AVQueuePlayerを使用する(機能しない)

10個のAVPlayerItemsAVQueuePlayerに押し込めば、それらがすべてシームレスに起動するようにプリロードされるとは思わない。 AVQueuePlayerはキューであり、キュー内の次のビデオをすぐに再生できるようにするだけです。 〜10本のビデオのうち、どれを再生したいかは、そのビデオを開始する時が来るまでわかりません。 ios-avplayer-video-preloading

アイデア3:バックグラウンドでAVPlayerItemsをロード、再生、保持します(まだ100%確かではありませんが、見栄えがよくありません)

バックグラウンドで各ビデオクリップの最初の1秒をロードして再生する(ビデオとオーディオの出力を抑制する)利点があるかどうかを調べ、各AVPlayerItemへの参照を保持します。アイテムを実際に再生し、そのアイテムを交換し、バックグラウンドAVPlayerをアクティブなものと交換する必要があります。すすぎと繰り返し。

理論的には、最近再生されたAVPlayer/AVPlayerItemにはまだ準備されたリソースが保持されている可能性があり、それにより後続の再生が高速になります。これまでのところ、これによるメリットは見ていませんが、バックグラウンド用にAVPlayerLayerを正しくセットアップしていない可能性があります。これが私が見たものから本当に改善されるとは思わない。

アイデア4:別のファイル形式を使用します-読み込み速度が速いものかもしれませんか?

現在、.m4v(video-MPEG4)H.264形式を使用しています。 H.264には多くの異なるコーデックオプションがあるため、一部のオプションは他のオプションよりも高速に検索できる可能性があります。ファイルサイズを小さくするより高度な設定を使用すると、シーク時間が長くなることがわかりましたが、逆の方法は見つかりませんでした。

アイデア5:ロスレスビデオフォーマットとAVQueuePlayerの組み合わせ

読み込みが高速で、ファイルサイズが非常に大きいビデオ形式がある場合は、各ビデオクリップの最初の10秒に、肥大化したが読み込みは速いが元に戻すバージョンを事前に準備することをお勧めします。 H.264でエンコードされたアセットを使用します。 AVQueuePlayerを使用して、最初の10秒を非圧縮ファイル形式で追加し、さらに10秒までの準備/プリロード時間を取得するH.264のファイルを追加します。だから、両方の世界の「最高」を手に入れるだろう:速いスタート時間だけでなく、よりコンパクトなフォーマットの恩恵も受ける。

アイデア6:非標準のAVPlayerを使用する/自分で作成する/他人のを使用する

私のニーズを考えると、おそらくAVPlayerを使用することはできませんが、AVAssetReaderに頼り、最初の数秒をデコードし(おそらく生ファイルをディスクに書き込む)、再生に関しては生フォーマットを使用して再生する必要があります早く戻る。私には巨大なプロジェクトのように思えます。そして、私がそれを素朴な方法で行けば、それは不明瞭であり、より良く機能することすらありません。デコードされた非圧縮ビデオフレームはそれぞれ2.25 MBです。簡単に言えば、ビデオに〜30 fpsを使用した場合、〜60 MB/sのディスクからの読み取りが必要になりますが、これはおそらく不可能/プッシュです。明らかに、ある程度の画像圧縮を行う必要があります(おそらく、PVRTCを介したネイティブのopenGL/es圧縮形式)...しかし、それはちょっとおかしいです。たぶん私が使用できるライブラリがそこにありますか?

アイデア7:すべてを1つの映画アセットに結合し、seekToTime

上記のいくつかよりも簡単なアイデアの1つは、すべてを1つのムービーに結合し、seekToTimeを使用することです。大事なのは、あちこちジャンプしているということです。映画への本質的にランダムなアクセス。これは実際にうまくいくと思う: avplayer-movie-playing-lag-in-ios5

どのアプローチが最適だと思いますか?これまでのところ、ラグを減らすという点ではそれほど進歩していません。

109

IOS 10.x以降では、AVPlayerの起動遅延を減らすために設定しました:avplayer.automaticallyWaitsToMinimizeStalling = false;そしてそれは私のためにそれを修正するようでした。これは他の結果をもたらす可能性がありますが、私はまだそれらを打っていません。

私はそれからアイデアを得ました: https://stackoverflow.com/a/50598525/9620547

1
grizzb

動作させることができるかどうかを確認するために、最初にオプション#7を試す必要があります。シーク時間はクリップ間のシームレスな切り替えを行うのに十分な速さではない可能性が高いため、実際にはニーズに合っていないと思われます。あなたがそれを試して失敗した場合、オプション4/6を行い、この目的のために特別に設計された私のiOSライブラリを見て、AVAnimatorで簡単にグーグル検索して詳細を調べることをお勧めします。私のライブラリは、シームレスなループを実装し、あるクリップから別のクリップに切り替えることを可能にします。ビデオは手作業でファイルにデコードする必要があるため、非常に高速です。あなたの場合、開始する前に10個のビデオクリップすべてがファイルにデコードされますが、それらの間の切り替えは高速です。

1
MoDJ

作成したアセットは準備ができていない場合があり、映画の継続時間などの計算を行う場合があります。映画のすべてのメタデータがファイルに含まれていることを確認してください。

1
nova

過去にこのようなことをしていなかったので、あなたの考えと経験に基づいて、私は7と1の組み合わせを試してみました。スキップすると、データが少ないため、より高速で信頼性が高くなります。選択した作品を再生している間、バックグラウンドで選択したフォローアップ動画の残りのためにAVPlayerを準備するのに十分な時間があります。開始が終了したら、準備されたAVPlayerに切り替えます。したがって、合計で、任意の時点で最大2つのAVPlayerがロードされます。

もちろん、切り替えが非常にスムーズに行えるので、再生を妨げないかどうかはわかりません。

(できればこれをコメントとして追加します。)

ベスト、ピーター

0
ilmiacs

あなたの問題を正しく理解していれば、すぐにオーディオトラックをロードする必要がある連続したビデオが1つあるようです。

その場合は、 [〜#〜] bass [〜#〜] を調べることをお勧めします。 BASSはAVPlayerによく似たオーディオライブラリで、iOSのAudioUnitsフレームワークの低レベルAPIに(比較的)簡単にアクセスできます。あなたにとってどういう意味ですか?つまり、ほんの少しのバッファー操作(必要ない場合もあります。遅延がどれだけ小さいかによって異なります)を使用すると、すぐに音楽の再生を開始できます。

ただし、前述のとおり、ビデオに制限があります。これはaudioライブラリなので、ビデオ操作はAVPlayerで行う必要があります。ただし、using-seekToTime:toleranfeBefore:toleranceAfter:必要なすべてのオプションをプリロールする限り、ビデオ内で高速シークを達成できるはずです。

複数のデバイス間で同期する場合(アプリケーションが提案する場合があります)、コメントを残してください。回答を編集させていただきます。

PS:BASSはCに似たフォーマットであるため、最初は気が遠くなるかもしれませんが、その用途には本当に簡単です。

0
Ge0rges