Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching with AVPlayer and AVAssetExportSession

I would like to cache progressive-download videos using AVPlayer. How can I save an AVPlayer's item to disk? I'm trying to use AVAssetExportSession on the player's currentItem (which is fully loaded). This code is giving me "AVAssetExportSessionStatusFailed (The operation could not be completed)" :

    AVAsset *mediaAsset = self.player.currentItem.asset;

    AVAssetExportSession *es = [[AVAssetExportSession alloc] initWithAsset:mediaAsset presetName:AVAssetExportPresetLowQuality];

    NSString *outPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.mp4"];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:outPath error:NULL];

    es.outputFileType = @"com.apple.quicktime-movie";
    es.outputURL = [[[NSURL alloc] initFileURLWithPath:outPath] autorelease];
    NSLog(@"exporting to %@",outPath);
    [es exportAsynchronouslyWithCompletionHandler:^{
        NSString *status = @"";

        if( es.status == AVAssetExportSessionStatusUnknown ) status = @"AVAssetExportSessionStatusUnknown";
        else if( es.status == AVAssetExportSessionStatusWaiting ) status = @"AVAssetExportSessionStatusWaiting";
        else if( es.status == AVAssetExportSessionStatusExporting ) status = @"AVAssetExportSessionStatusExporting";
        else if( es.status == AVAssetExportSessionStatusCompleted ) status = @"AVAssetExportSessionStatusCompleted";
        else if( es.status == AVAssetExportSessionStatusFailed ) status = @"AVAssetExportSessionStatusFailed";
        else if( es.status == AVAssetExportSessionStatusCancelled ) status = @"AVAssetExportSessionStatusCancelled";

        NSLog(@"done exporting to %@ status %d = %@ (%@)",outPath,es.status, status,[[es error] localizedDescription]);
    }];

How can I export successfully? I'm looking into copying mediaAsset into an AVMutableComposition, but haven't had much luck with that either.

Thanks!

PS: Here are some questions from people trying to accomplish the same thing (but with MPMoviePlayerController):

  • Cache Progressive downloaded content in MPMoviePlayerController

  • Simultaneously stream and save a video?

  • Caching videos to disk after successful preload by MPMoviePlayerController

like image 908
tba Avatar asked Jun 06 '11 23:06

tba


Video Answer


1 Answers

I'm not using the iOS 4.3 SDK yet, but I'd be curious to know the value of mediaAsset.exportable under 4.3, as described here:

http://developer.apple.com/library/ios/#releasenotes/AudioVideo/RN-AVFoundation/_index.html#//apple_ref/doc/uid/TP40010717-CH1-SW4

I've tried a number of modifications to your code, such as getting the preset name and file type from the list of those available, but I'm getting the same error you are.

So, I decided to try a lower-level framework, since the documentation states that you can connect an AVAssetReader and an AVAssetWriter to get the same effect as an AVAssetExportSession except with more control. However, the following code:

NSError *readerError = nil;
AVAssetReader *reader = 
  [AVAssetReader assetReaderWithAsset:mediaAsset error:&readerError];
if (readerError) NSLog(@"Error instantiating asset reader: %@",
  [readerError localizedDescription]);

Gives the following output:

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

Note that I tested this with a working URL but have replaced it with a fake one above. This looks to me like iOS doesn't support the functionality we're looking for. For all I know AVAssetExportSession uses an AVAssetReader under the hood and just reports a much less descriptive error when it fails. It sure would be nice if they'd just document it as such. The docs for AVAssetExportSession don't mention anything about the asset needing to be local:

http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAssetExportSession_Class/Reference/Reference.html#//apple_ref/occ/cl/AVAssetExportSession

I know this isn't much of an answer, but it moves the investigation down the road a little. I'm still really hoping there's some way to do this, because clearly we are not alone in wanting the feature.

like image 198
Jesse Crossen Avatar answered Sep 20 '22 13:09

Jesse Crossen