【问题标题】:generateCGImagesAsynchronouslyForTimes sometimes don't generate entire thumbnailsgenerateCGImagesAsynchronouslyForTimes 有时不会生成整个缩略图
【发布时间】:2016-12-09 09:02:59
【问题描述】:

我正在开发一个使用 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
}

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

【问题讨论】:

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

标签: swift avfoundation thumbnails avassetimagegenerator


【解决方案1】:

您可以使用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)
}

【讨论】:

    【解决方案2】:

    我认为您的问题实际上是没有保留从 AVAssetImageGenerator.generateCGImagesAsynchronouslyForTimes 返回的 CGImages。有趣的是,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;

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

    【讨论】:

    • 非常感谢!尽管我已经完成了这个项目,但知道可能发生的事情还是很有趣的。令人沮丧的是,Apple 文档没有提到这样的事情......
    猜你喜欢
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2013-11-23
    相关资源
    最近更新 更多