是否可以在没有文件扩展名的情况下使AVURLAsset工作?

时间:2012-02-15 09:41:04

标签: avfoundation avurlasset

我正在尝试为视频文件创建缩略图:

- (UIImage*) thumbnailForVideoAtURL: (NSURL*) videoURL
{
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    CGImageRef imageHandle = [generator copyCGImageAtTime:kCMTimeZero actualTime:NULL error:NULL];
    if (imageHandle) {
        UIImage *frameImage = [UIImage imageWithCGImage:imageHandle];
        CFRelease(imageHandle);
        return frameImage;
    } else {
        return nil;
    }
}

问题是视频文件存储在content-addressable store中,没有扩展名。当资产被创建时,这似乎会抛出AVURLAsset,但在读取帧图像时,我会收到以下错误:

Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo=0x167170 {NSLocalizedFailureReason=This media format is not supported., NSUnderlyingError=0x163a00 "The operation couldn’t be completed. (OSStatus error -12847.)", NSLocalizedDescription=Cannot Open}

这是在某处记录或提及的吗?我无法相信我真的被迫通过文件名传递文件格式信息。 options初始化程序的AVURLAsset参数看起来是提供文件类型的好地方,但根据文档似乎没有任何支持。

PS。我已经测试了代码,具有正确扩展名的相同文件会生成缩略图。

4 个答案:

答案 0 :(得分:12)

最后,我暂时创建了一个文件的硬链接,并为硬链接提供了正确的扩展名。虽然这是一个黑客,我希望看到一个更好的解决方案。我submitted a bug report反对AVURLAsset,希望Apple可以添加该功能,以便从options词典中读取文件格式信息。

答案 1 :(得分:4)

我相信我在iOS7中找到了解决方法。 诀窍是使用AVAssetResourceLoader。 将包含您创建的方案的虚拟URL传递给AVURLAsset,这将导致调用AVAssetResourceLoaderDelegate,例如: 'myscheme://random.com/file.mp4' 正如您在我创建的URL中看到的那样,它具有.mp4扩展名,这将允许AVPlayer正确打开文件,只要您正确地执行下一步。

现在实现AVAssetResourceLoaderDelegate以使用实际的URL,即“http://actual.com/file” 现在数据将正确传递到AVPlayer,而不会抱怨无法打开那种类型的文件格式。

答案 2 :(得分:3)

快速回答:

let filePath = ###YOU SET THIS###
let fileManager = NSFileManager.defaultManager()
let documentsURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .AllDomainsMask).last!
let tmpURL = documentsURL.URLByAppendingPathComponent("tmp.caf")
_ = try? fileManager.removeItemAtURL(tmpURL)
_ = try? fileManager.linkItemAtURL(fileURL, toURL: tmpURL)

完整答案Obj-C:

NSString *filePath = ###YOU SET THIS###
NSFileManager *dfm = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *tmpPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"tmp.caf"];
[dfm removeItemAtPath:tmpPath error:nil];
[dfm linkItemAtPath:filePath toPath:tmpPath error:nil];

现在AVURLAsset将与tmpPath一起使用。

答案 3 :(得分:0)

ORDER