使用AVPlayer和AVAssetExportSession进行缓存

10

我想使用AVPlayer缓存渐进式下载的视频。如何将AVPlayer的项目保存到磁盘?我正在尝试在播放器的当前项目(已完全加载)上使用AVAssetExportSession。这段代码给我返回了“AVAssetExportSessionStatusFailed(操作无法完成)”:

    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]);
    }];

我该如何成功导出?我正在尝试将mediaAsset复制到AVMutableComposition中,但是也没有太多的成功经验。
谢谢!
附注:以下是一些其他人尝试实现相同目标的问题(但使用MPMoviePlayerController):
- 在MPMoviePlayerController中缓存渐进式下载的内容 - 同时流式传输和保存视频? - 在MPMoviePlayerController成功预加载后将视频缓存在磁盘中

嘿!你解决了吗? - Roi Mulia
2个回答

9

我目前还没有使用iOS 4.3 SDK,但我很想知道在4.3下mediaAsset.exportable的值是多少,正如这里所描述的:

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

我尝试了你的代码的多个修改,例如从可用的名称和文件类型列表中获取预设名称,但是我得到了与你相同的错误。
因此,我决定尝试一个更低级别的框架,因为文档说明可以连接AVAssetReader和AVAssetWriter以获得与AVAssetExportSession相同的效果,但具有更多的控制。然而,以下代码:
NSError *readerError = nil;
AVAssetReader *reader = 
  [AVAssetReader assetReaderWithAsset:mediaAsset error:&readerError];
if (readerError) NSLog(@"Error instantiating asset reader: %@",
  [readerError localizedDescription]);

给出以下输出:
*** 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''

请注意,我已经使用一个有效的URL进行了测试,但在上面替换成了一个虚假的URL。在我看来,这似乎是iOS不支持我们正在寻找的功能。我所知道的是,AVAssetExportSession在底层使用AVAssetReader,并且失败时只报告了一个不太详细的错误。如果他们能将其记录为这样就好了。AVAssetExportSession的文档没有提到资产需要是本地的任何内容。

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

我知道这不算是一个很好的答案,但它能推进调查的进展。我仍然非常希望有某种方法可以实现这个功能,因为显然我们不是唯一想要这个功能的人。

是的,我遇到了同样的问题。更糟糕的是,mediaAsset.exportable 是 YES!但它仍然抛出“无法在非本地 URL 初始化...”异常。 - tba
4
你对音频感兴趣吗?因为如果是的话,可以通过连接URL加载系统、音频文件流服务和音频队列服务来实现。我正在研究一种解决方案,但涉及复杂。你有兴趣吗? - Jesse Crossen
不幸的是,我需要缓存整个视频。谢谢你,但我会在几天内将你标记为被接受的答案。 - tba
Jesse,你能否谈谈你的音频解决方案或者分享一下吗?如果可以,请通过电子邮件或在此处留言与我联系。 - Roman Temchenko
@RomanTemchenko:很抱歉我从未完成那个解决方案。看起来很简单,但是我卡在了将编码数据包与正确的元数据一起提供给AQS的所有细节上。由于这些低级音视频框架有点像未经记录的黑匣子,所以我没有足够重视它并花时间去弄清楚所有细节。 - Jesse Crossen
@JesseCrossen,你有解决方案吗?我想从YouTube视频剪辑中导出一部分音频,但不想全部下载...有什么建议吗? - luca

0

肯定不能在iOS 4.X上工作。有人尝试在iOS 5 Beta上使其工作吗?

这似乎是一个缺失的功能。文档中没有说明它不支持网络媒体的数据访问。当尝试运行时,甚至API中的错误消息和其他东西的行为都很奇怪,似乎是不完整的。很可能很快就会得到支持。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接