1

AVQueuePlayerアプリで動画のリストを再生するために使用しています。AVQueuePlayerビデオを毎回ダウンロードする必要がないように、再生されるビデオをキャッシュしようとしています。

そのため、ビデオの再生が終了したら、AVPlayerItem をディスクに保存して、次回はローカル URL で初期化しようとします。

私は2つのアプローチでこれを達成しようとしました:

  1. AVAssetExportSession を使用する
  2. AVAssetReader と AVAssetWriter を使用します。

1) AVAssetExportSession アプローチ

このアプローチは次のように機能します。

  1. AVPlayerItemが を使用して演奏を終了するのを観察しAVPlayerItemDidPlayToEndTimeNotificationます。
  2. 上記の通知を受け取ると (ビデオの再生が終了したため、完全にダウンロードされます)、AVAssetExportSessionそのビデオをディスク内のファイルにエクスポートするために使用します。

コード:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

それから

- (void)videoDidFinishPlaying:(NSNotification*)note { AVPlayerItem *itemToSave = [note object]; AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:itemToSave.asset presetName:AVAssetExportPresetHighestQuality]; exportSession.outputFileType = AVFileTypeMPEG4; exportSession.outputURL = [NSURL fileURLWithPath:@"/path/to/Documents/video.mp4"]; [exportSession exportAsynchronouslyWithCompletionHandler:^{ switch(exportSession.status){ case AVAssetExportSessionStatusExporting: NSLog(@"Exporting..."); break; case AVAssetExportSessionStatusCompleted: NSLog(@"Export completed, wohooo!!"); break; case AVAssetExportSessionStatusWaiting: NSLog(@"Waiting..."); break; case AVAssetExportSessionStatusFailed: NSLog(@"Failed with error: %@", exportSession.error); break; } }

そのコードのコンソールでの結果は次のとおりです。

Failed with error: Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x98916a0 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x99ddd10 "The operation couldn’t be completed. (OSStatus error -12109.)", NSLocalizedFailureReason=An unknown error occurred (-12109)}

2) AVAssetReader、AVAssetWriter アプローチ

コード:

- (void)savePlayerItem:(AVPlayerItem*)item { NSError *assetReaderError = nil; AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:assetToCache error:&assetReaderError]; //(algorithm continues) }

AVAssetReader次の情報を使用して割り当て/初期化しようとすると、そのコードは例外をスローします。

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of AVAssetReader with an asset at non-local URL 'https://someserver.com/video1.mp4'' ***

どんな助けでも大歓迎です。

4

1 に答える 1

2

どうやってこれを行うことができたのかというと、通常は AVPlayer > AVPlayerItem > AVURLAsset の配列を作成することです。しかし同時に、AVPlayer がリモート URL からビデオを完全にロードする前に、すぐに AVExportSession を作成します。

AVPlayer が URL を事前にバッファリングしようとするため、AVExportSession は実際にはゆっくりとエクスポートされます。これは、ユーザーが AVPlayer の再生を開始するかどうかに関係なく行われます。ただし、URL 全体が事前にバッファリングされるまで、出力ファイルは実際には完成しません。その時点で、AVExportSession は完了でコールバックします。これは、ユーザーがビデオを再生しているかどうか、またはビデオの再生を完了したかどうかにも完全に依存しません。

そのため、AVPlayer/AVExportSession コンボを早期に作成することで、それが私のプリバッファー メカニズムになりました。

-- 2018-01-10 更新 --

上記のメカニズムを展開した後にそれを追加したい。言及する価値があると思われる 1 つの大きな警告に遭遇しました。

メモリ内にビデオ パイプラインが多すぎることはありません (AVPlayerItem/AVAsset が接続された AVPlayer)。AVFoundation はプレイを拒否します。したがって、上記のメカニズムを使用して事前バッファリングしてください。ただし、ビデオがファイルにダウンロードされた後、ユーザーがビデオを表示していない場合は、AVPlayer/AVAsset の割り当てを解除します。ユーザーがビデオを再度再生することを決定したときに、AVPlayer を再割り当てします。今回は、AVURLAsset がビデオのローカル バッファリング コピーを指しています。

于 2017-10-21T06:03:34.543 に答える