web-dev-qa-db-ja.com

AVPlayerでHLSセグメントをキャッシュすることは可能ですか?

根本的な問題

私たちのビデオは、iOSでシークするときに多くバッファリングします。これは、すでに監視しているセグメントのコピーを一時ストレージに保存するWebプレーヤーよりもかなり多くバッファリングします。

望ましいソリューション

ビデオセグメントをデバイスのディスクにローカルにキャッシュします。単一の品質をキャッシュして常に再生することで問題ありません。

ブロッカー

AVFoundation/AVPlayer内でキャッシュを実行する方法が見つかりません。

これまでに試したこと

AVPlayerでネットワーキングリクエストをインターセプトする2つの方法。

  1. AVAssetResourceLoaderDelegateに準拠し、メディアの読み込みを手動で処理する

HLSでは機能しません。 AVAssetResourceLoaderDelegateを実装することでm3u8ファイルをロードできます。これにより、認証を渡したり、応答を復号化したりできますが、.tsファイルはロードできません。これが私たちが試したコードです: https://Gist.github.com/nathanhillyer/84e46152d7c4c88183b6

  1. NSURLProtocolを実装して、.tsファイルのリクエストをキャプチャします。

AVURLAssetは、インターセプトされることを実際に回避します。どういうわけか、ネットワーク要求はキャプチャされません。 (理由がわかりません)

27
Nathan Hillyer

本当に良いニュースから始めましょう-iOS 10以降-これは箱から出してこれを与えます。すぐにハックする必要はもうありません。 HTTPライブストリーミングの新機能に関する詳細は、次のWWDC16セッションで確認できます。 https://developer.Apple.com/videos/play/wwdc2016/504/

さて、現状に戻りましょう-iOS 9以下:AVPlayerでは、いいえ。ただし、ローカルのHTTPサーバーを介してHLSセグメントをキャッシュし、AVPlayerでローカルストリームを再生できます。

AVPlayerとAVAssetには、HLS再生を処理するときに必要な情報が含まれていません(たとえば、MP4静的ファイルとは動作が異なります)。

TL; DR-セグメントを取得し、ローカルのHTTPサーバーを使用してそれらを提供するには、HTTPリクエストを使用する必要があります。

私が働いている会社を含むいくつかの会社がこの戦略を使用しています。

接続を使用して必要な品質でセグメントをダウンロードし、マニフェストを再構築してすべてを1つのディレクトリと1つの品質にフラット化してから、アプリ内のローカルhttpサーバーを使用してAVPlayerに配信します(AVPlayerは、配信されたHLSストリームのみを再生できますHTTP-ファイルアセットからではありません)。

Edgeのケースがあります。たとえば、1回の実行で再生とダウンロードを行う場合のバッファリング、m3u8マニフェストの正しい再構築、ディスク読み取りによるさまざまなAVPlayer状態などがあります。

これは、このようなシステムが5年間製造されていることと、同じソリューションを使用するApp Storeの他のビデオ製品の両方を持っているという直接的な知識からわかりました-合計で多くのユーザーにサービスを提供しています。

これは、Android向けに見つけた最良のソリューションでもあります。

10
Liviu R

実際、AVPlayerにネットワークからビデオを再生させることができますが、ダウンロードしたデータをキャッシュしてローカルで再生したい場合は、AVPlayerを使用することは今では不可能に思えます。

幸いなことに、AVURLAssetにはresourceLoaderオブジェクトというすばらしいAPIがあり、AVPlayerにリモートオーディオファイルへの制御されたアクセスを提供できます。これはローカルHTTPプロキシのように機能しますが、手間はかかりません。

https://Gist.github.com/anonymous/83a93746d1ea52e9d23f で詳細を確認できます

2
HSG

NSURLProtocolについて:私が理解したように、それは独自のリクエストを行うので、カスタムタグ/フィールド/マークは削除されます。

私はそれを別の方法で行いました:セグメント要求をカスタムURLスキームにリダイレクトし、プロトコルのcanInitWithRequestメソッドでスキームを確認するだけです。

このようにして、うまく動作します。 (hls処理全体を把握するために1週間を費やした...)

0
norlin