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


115

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

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

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

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

呼び出し元:私は以来、私はほぼ同じだと思うものに切り替えた[AVPlayerItem playerItemWithURL:]と待っているAVPlayerItemStatusReadyToPlayプレーします。ほぼ同じパフォーマンス。

私が観察していることの1つは、最初のAVPlayerアイテムのロードが他のアイテムよりも遅いことです。1つのアイデアは、最初のビデオを再生しようとする前に、短い/空のアセットでAVPlayerを事前に飛行させることは、一般的な慣習になるかもしれないようです。[ AVAudioPlayerの最初のサウンド再生時のスロースタート

私はビデオの開始時間をできる限り短くし、実験するためのアイデアをいくつか持っていることを望みますが、役立つ可能性がある人からのガイダンスをお願いします。

更新:実装後のアイデア7では、スイッチング時間が約500 msになります。これは改善ですが、これをさらに速くした方がいいでしょう。

アイデア1:N個のAVプレーヤーを使用する(機能しない)

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

私はこれがうまくいくとは思いません。私が読んだのはAVPlayer's、iOSでアクティブにできる制限はおよそ4 であるためです。ここでStackOverflowについてこれについて質問している人がいて、4 AVPlayerの制限について知りました:fast-switching-between-videos-using-avfoundation

アイデア2:AVQueuePlayerを使用する(機能しません)

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

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

各ビデオクリップの最初の1秒をバックグラウンドでロードして再生し(ビデオとオーディオの出力を抑制)、それぞれへの参照を保持し、AVPlayerItem再生する必要があるアイテムがわかっている場合にメリットがあるかどうかを確認しています実際にそれを入れ替え、バックグラウンドのAVPlayerをアクティブなAVPlayerと入れ替えます。すすぎと繰り返し。

理論的には、最近再生AVPlayer/AVPlayerItemされたは、その後の再生を高速化する準備されたリソースをまだ保持している可能性があります。これまでのところ、これによるメリットはありませんがAVPlayerLayer、背景の設定が正しくない可能性があります。これが私が見たものから本当に良くなるとは思えません。

アイデア4:別のファイル形式を使用する-おそらく読み込みが高速な形式ですか

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

アイデア5:ロスレスビデオ形式+ AVQueuePlayerの組み合わせ

読み込みが高速でファイルサイズが異常なビデオ形式がある場合、1つのアイデアは、各ビデオクリップの最初の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

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


価値があるので、私はアイデア7を使用します。それはまだ遅いですが、他のオプションほど予測できないほど遅くはありません。次の質問は、コーデックのオプション、解像度、およびキーフレームの頻度がシークタイミングに影響するかどうかです。
Bernt Habermeier、2012

ゲームの終盤ですが、ビデオをできるだけ速く切り替えて(つまり、新しいビデオの再生が開始された直後)、アプリをプロファイリングして、CPU時間のほとんどを費やしている場所を確認することをお勧めします。
tc。

1
今からほぼ1年後、これで何を知りましたか?
lnafziger 2013年

1
私はオプション7で行き、300msと500msシークの間のどこかに行きました。私が見つけた1つのことは、mp4コーデックオプションのより凝ったものはseekToが遅いということです。より良い圧縮を可能にし、ビデオ品質を維持しながら、デコード時間を短縮するビデオ圧縮オプションがいくつかあります。
Bernt Habermeier 2013年

2
これは妥当なサウンド要求ですが、実際にオプション7を実装するには、実装にファセットが多すぎて投稿できません。検討:(a)ビデオアセットをマージするためのツールチェーンを作成する、(b)ビデオセグメントのオフセットを追跡することを確認する、(c)特定のクリップを再生する要求が来たときにルックアップオフセットを確認する、(d)addPeriodicTimeObserverForIntervalを使用して確認するあなたがビデオクリップをオフに走ったし、それに応じて反応するならば、私は時々ではないトリガーに後者を発見したので、(シングルショットaddBoundaryTimeObserverForTimes対このメソッドを使用して...全体的に、これはコードを貼り付けるには向いていません。
Bernt Habermeier

回答:


4

iOS 10.x以降では、AVPlayerの開始遅延を減らすために設定 avplayer.automaticallyWaitsToMinimizeStalling = false; しました。これで問題が解決したようです。これは他の結果をもたらす可能性がありますが、私はまだそれらを打っていません。

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


遅延が6〜7秒減少しました。しかし、ここで質問があります。それはアプリのパフォーマンスに影響しますか?
カルパ

@kalpaこのコードを1年以上本番アプリで使用しており、目に見える悪影響はありません。私たちはほとんどの場合、モバイルデータのカバレッジが一般に速い米国のリスナーに対して、20〜60分のオーディオファイルを再生します。ただし、ユースケースは異なる場合があります。
grizzb

情報をありがとう。@grizzb
kalpa

1

作成したアセットは準備が整っていない可能性があります。映画の長さなどの計算を行う場合があります。必ず、ファイルに映画のすべてのメタデータを含めてください。


1

最初にオプション#7を試してみて、それが機能するかどうかを確認してください。シーク時間は、クリップ間のシームレスな切り替えを提供するのに十分な速度ではない可能性が高いため、実際にはニーズに対応できないと思います。それを試して失敗した場合は、オプション4/6を実行し、この目的のために特別に設計された私のiOSライブラリを確認することをお勧めします。私のライブラリでは、シームレスなループを実装し、1つのクリップから別のクリップに切り替えることができます。ビデオを事前にファイルにデコードする必要があるため、非常に高速です。あなたの場合、開始する前に10個のビデオクリップすべてがファイルにデコードされますが、それらの間の切り替えは高速です。


ビデオのオーディオ部分はどうですか?ビデオとオーディオを同期させる必要があります。
Bernt Habermeier 2013

はい、オーディオはすでに処理されており、オーディオトラックとビデオクリップは非常に緊密に同期しています。xcodeプロジェクトの例を参照してください。すでにすべて実装されているので、ダウンロードして試してみるだけです。
MoDJ 2013

AVAnimatorを使用してネットワークビデオを再生する可能性はありますか?
Richard Topchii 2016年

いいえ、ローカルファイルで機能します。ストリーミングネットワークビデオはまったく異なります。
MoDJ 2016年

0

過去にこのようなことをせずに、あなたの考えと経験に基づいて、7と1の組み合わせを試してみます。1つのAVPlayerに、10本のフォローアップビデオの最初の数秒をプリロードします。次に、データが少ないため、スキップがより高速で信頼性が高くなります。選択した曲を再生している間に、バックグラウンドで選択したフォローアップビデオの残りの部分をAVPlayerに準備するのに十分な時間があります。開始が終了したら、準備したAVPlayerに切り替えます。したがって、合計で、常に最大2つのAVプレーヤーがロードされます。

もちろん、切り替えがスムーズに行えて再生の邪魔にならないかどうかはわかりません。

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

ベスト、ピーター


1つのAVPlayerに10個のアセットを連続してロードするメリットはありません。さらに、オプション(1)と(7)は相互に排他的であるため、私はあなたの提案を理解していません。オプション7は、すべての動画アセットを1つのアセットにマージします。したがって、ロードするアセットは1つだけです。これは私が今日やっていることであり、その価値があるために、実際の開始/再生時間に約500ミリ秒の遅延が発生します。SeekToは実際の最初のフレームが再生されるよりも速く完了することに注意する価値があります。そのため、実際の開始時間については、最初のフレームが時間指定のコールバックを介して実際に再生される時間を測定します。
Bernt Habermeier、2012

私のアイデアを明確にするために:私のアイデアは、アセットを2つの部分に分割することでした:最初の数秒と残りの部分。これで、1つから2つのアセットが作成されました。参加してスキップを使用する10の最初の部分と、最初の部分の再生中に残りの部分をロードします。これは、リストに追加する提案8で構成されます。
ilmiacs 2012

しかし、あなたの最後のコメントから理解できるように、その間、あなたは研究をさらに推進しましたが、それは良いことであり、ソリューション7もうまくいきません。AVは基本的にあなたの邪魔にならないように見え、あなたが行く唯一の方法はおそらくその下のテクノロジー、つまりCore Mediaを使用してあなたの資産をより細かく制御することです。ピーター。
ilmiacs 2012

ああ、私は今あなたの考えをよりよく理解しています。ありがとう。短いビデオクリップのシーク時間が高速になるかどうかを調べるのは興味深いことです。私はまだそれを試していませんが、検討する価値があります。コアメディアの使用について-そのAPIに関する適切な参考資料は見つかりませんでした。あなたが私に向けることができる良いリソースはありますか?
Bernt Habermeier、2012

いいえ、申し訳ありません。言ったように、私はAVやコアメディアの専門家ではありません。あなたの質問を読んで、私が個人的にどのように進め、共有したいかについていくつかのアイデアがありました。ピーター
ilmiacs 2012

0

問題を正しく理解できた場合、一瞬でオーディオトラックをロードする必要のある連続したビデオが1つあるようです。

その場合は、BASSを検討することをお勧めします。BASSは、AVPlayerによく似たオーディオライブラリで、iOSのAudioUnitsフレームワークの低レベルAPIに(比較的)簡単にアクセスできます。あなたにとっての意味は何ですか?それは、ほんの少しのバッファ操作で(あなたはそれを必要としないことさえあるかもしれません、あなたが即座に音楽の再生を開始できることを意味します)

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

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

PS:BASSはCに似た形式のため、最初は気が遠くなるように見えるかもしれませんが、それが何であるかについては本当に簡単に使用できます。


-2

AVAssetクラスが提供するいくつかのプロパティとメソッドを以下に示します。

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.