2012-02-15 131 views
11

我试图为视频文件创建缩略图:是否可以使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参数看起来是提供文件类型的好地方,但根据文档,似乎没有任何支持。

PS。我测试了代码,具有正确扩展名的相同文件产生缩略图就好了。

回答

10

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

+0

你能告诉我PLZ。你如何创建硬链接到文件,实际上我有一个你管视频的网址,我必须使用它的网址创建该视频的缩略图 – 2012-03-01 12:20:23

+0

你的意思是一个本地文件的URL,或一个普通的HTTP YouTube网址?使用'[NSFileManager linkItemAtURL:toURL:error:]''可以很容易地链接本地文件的URL。从HTTP YouTube视频URL创建缩略图值得[单独的问题](http://stackoverflow.com/questions/ask),恕我直言。 – zoul 2012-03-01 13:04:11

+1

在iOS7和[[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]中仍然没有修复;'没有扩展名的文件没有问题 – 2013-10-19 19:51:28

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工作。

+0

嘿..相同的方法在PHAsset的情况下工作..我无法通过从PHAsset获取的路径读取本地文件。所以链接工程 – ProblemSlover 2015-11-03 10:20:37

4

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

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

+1

我正在努力实现您推荐的解决方法,并且我正在实现AVAssetResourceLoaderDelegate,但我仍然无法让AVPlayer播放音频源。你能详细说明你的意思吗?“现在实现AVAssetResourceLoaderDelegate以使用实际的URL,即'http://actual.com/file'”?您是否以某种方式换出网址? – Shackleford 2017-07-13 21:29:25

+1

前段时间我做了这个,但基本上我使用了一个带.mp4扩展名的资源方案,这样委托将被调用并且不会被跳过。一旦进入该委托,我使用实际的资源地址来加载它,我使用静态方法来获取实际资源地址,而不是使用虚拟委托所需的代码来正确调用。 – Pellet 2017-07-14 05:37:06

相关问题