generateCGImagesAsynchronouslyForTimes 有时不会生成整个缩略图

generateCGImagesAsynchronouslyForTimes sometimes don't generate entire thumbnails

我正在开发一个使用 AVAssetImageGenerator.generateCGImagesAsynchronouslyForTimes 的 OS X 应用程序,它通常运行良好。然而,有时我得到的缩略图只包含前几行像素,其余的都是绿色,有时图像会呈现不同深浅的绿色。很难追踪到,因为它不会一直发生,但是当它发生时,大约一半的缩略图会受到影响。这是我希望看到的图像:

但这种情况经常发生:

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

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
}

非常感谢任何帮助,谢谢!

您可以使用 copyCGImageAtTime 方法从资产中获取图像并像之前保存的那样保存该图像,而不是使用 generateCGImagesAsynchronouslyForTimes 方法。这是代码。

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

我认为您的问题实际上是未保留从 AVAssetImageGenerator.generateCGImagesAsynchronouslyForTimes 返回的 CGImage。有趣的是,official documentation 没有提到这一点,但阅读头文件明确说明了这一点。

/*! @method generateCGImagesAsynchronouslyForTimes:completionHandler: @abstract Returns a series of CGImageRefs for an asset at or near the specified times. @param requestedTimes An NSArray of NSValues, each containing a CMTime, specifying the asset times at which an image is requested. @param handler A block that will be called when an image request is complete. @discussion Employs an efficient "batch mode" for getting images in time order. The client will receive exactly one handler callback for each requested time in requestedTimes. Changes to generator properties (snap behavior, maximum size, etc...) will not affect outstanding asynchronous image generation requests. The generated image is not retained. Clients should retain the image if they wish it to persist after the completion handler returns. */ - (void)generateCGImagesAsynchronouslyForTimes:(NSArray<NSValue *> *)requestedTimes completionHandler:(AVAssetImageGeneratorCompletionHandler)handler;

我相信保留那些 CGImage 可以解决问题。