19

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

- (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;
    }
}

问题是视频文件存储在内容可寻址存储中并且没有扩展名。随着资产的创建,这似乎会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

4 回答 4

13

最后,我临时创建了一个指向该文件的硬链接,并为该硬链接提供了正确的扩展名。虽然这是一个 hack,但我希望看到一个更好的解决方案。我已经提交了一个错误报告AVURLAsset希望 Apple 可以添加从options字典中读取文件格式信息的功能。

于 2012-02-19T16:15:34.647 回答
6

快速回答:

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.

于 2013-10-19T23:51:22.643 回答
5
let mimeType = "video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\""
let asset = AVURLAsset(url: videoURL!, options:["AVURLAssetOutOfBandMIMETypeKey": mimeType])
let playerItem = AVPlayerItem(asset: asset)
avPlayer = AVPlayer(playerItem: playerItem)
self.avPlayerViewConroller?.player = avPlayer
playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions(), context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
        if(avPlayer?.currentItem?.status == AVPlayerItemStatus.readyToPlay)
        {
            avPlayer?.play()
        }
}
于 2019-01-08T07:35:00.730 回答
4

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

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

于 2013-11-01T08:58:41.257 回答