生成CGImagesAsynchronouslyForTimes有时无法生成完整的缩略图

14

我正在开发一个OS X应用程序,使用AVAssetImageGenerator.generateCGImagesAsynchronouslyForTimes方法,通常情况下它可以正常工作。但是偶尔会出现缩略图仅包含前几行像素的情况,并且其余部分都是绿色的,有时候图片会呈现不同的绿色调。由于这种情况并不总是发生,所以很难追踪问题,但当发生时,大约有一半的缩略图会受到影响。这是我希望看到的图像:

enter image description here

但经常会出现以下情况:

enter image description here

这是我用来生成缩略图的代码:

let assetGenerator = AVAssetImageGenerator(asset: AVURLAsset(URL: url))
assetGenerator.appliesPreferredTrackTransform = true
let time = CMTime(seconds: 0, preferredTimescale: 30)

let handler: AVAssetImageGeneratorCompletionHandler = { _, image, _, res, error in
    defer { dispatch_group_leave(self.waitForThumbnail!) }

    guard let image = image where res == .Succeeded else {
        if let error = error { print(error) }
        return
    }

    let s = CGSize(width: CGImageGetWidth(image), height: CGImageGetHeight(image))
    self.thumbnail = NSImage(CGImage: image, size: s)

}

waitForThumbnail = dispatch_group_create()
dispatch_group_enter(waitForThumbnail!)

assetGenerator.maximumSize = maxThumbnailSize
assetGenerator.generateCGImagesAsynchronouslyForTimes([NSValue(CMTime: time)], completionHandler: handler)

这是我检索缩略图的方法:

dispatch_group_wait(file.waitForThumbnail!, DISPATCH_TIME_FOREVER)
dispatch_async(dispatch_get_main_queue()) {
    self.imageView.image = file.thumbnail
}

非常感谢您的任何帮助!


1
出于好奇,你是如何创建 AVAsset 的?如果你正在使用 NSItemProvider,它会带有一个完成处理程序,为该文件提供苹果默认的缩略图作为图像。 - NSGangster
哦,真的吗?听起来不错,谢谢,我得试试看。现在我正在使用AVURLAsset(URL:url)来创建它们。 - Addison
这是一个处理预览图像的处理程序链接。我刚刚检查了一下,如果您只想使用它,NSItemProvider确实有initWithURL - NSGangster
2个回答

7

不要使用generateCGImagesAsynchronouslyForTimes方法,可以使用copyCGImageAtTime方法从资产中获取图像,并像以前一样保存该图像。以下是代码。

let assetGenerator = AVAssetImageGenerator(asset: AVURLAsset(URL: url))
assetGenerator.appliesPreferredTrackTransform = true
assetGenerator.maximumSize = maxThumbnailSize
let time = CMTime(seconds: 0, preferredTimescale: 30)
do {
    let cgImage = try assetGenerator.copyCGImageAtTime(time, actualTime: nil)
    let s = CGSize(width: CGImageGetWidth(cgImage), height: CGImageGetHeight(cgImage))
    self.thumbnail = NSImage(CGImage: cgImage, size: s)    
} catch let error {
    print(error)
}

3
我认为你的问题实际上是AVAssetImageGenerator.generateCGImagesAsynchronouslyForTimes返回的CGImage没有被保留。有趣的是,官方文档没有提到这一点,但读取头文件明确指出了这一点。
/*! @method generateCGImagesAsynchronouslyForTimes:completionHandler: @abstract 在给定时间或附近返回一个资源的一系列 CGImageRefs。 @param requestedTimes 包含 CMTime 值的 NSValue 数组,指定请求图像的资源时间。 @param handler 当图像请求完成时将调用的 block。 @discussion 采用有效的“批处理模式”以按时间顺序获取图像。客户端将为请求的每个时间在requestedTimes中收到恰好一个处理程序回调。生成的图像未被保留。如果客户端希望图像在完成处理程序返回后仍然存在,则应保留该图像。 */ - (void)generateCGImagesAsynchronouslyForTimes:(NSArray<NSValue *> *)requestedTimes completionHandler:(AVAssetImageGeneratorCompletionHandler)handler;
我相信保留这些CGImage可以解决这个问题。

1
非常感谢!虽然我已经完成了这个项目,但知道可能发生了什么是很有趣的。令人沮丧的是,苹果文档没有提到这样的事情... - Addison

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