2016-09-22 81 views
2

我有一个需要拍摄视频,将每帧转换为图像并将这些图像保存到磁盘。我想使用AVAssetImageGenerator效率的缘故,并有类似的代码如下:如何知道generateCGImages异步完成的时间?

的问题是,我不知道什么时候所有图像生成完成,但我需要采取行动,一旦所有帧写入磁盘。例如:

assetGenerator.generateCGImagesAsynchronously(forTimes: frameTimes, completionHandler: { (requestedTime, image, actualTime, result, error) in 
    // 1. Keep a reference to each image 
    // 2. Wait until all images are generated 
    // 3. Process images as a set 
}) 

这是上面的第2步,让我绊倒。我想我可以尝试计算完成处理程序被调用的次数,并在计数等于帧数时触发适当的方法。

但我想知道是否有一种方法来使用API​​来知道每一帧的处理?也许只是我错过了什么?任何指导或建议,将不胜感激。

回答

4

我会逐步处理图像,无论如何您都无法将它们全部放入内存中。为此,您可以使用assetGenerator.copyCGImageAtTime在特定时间对视频进行采样。

但是,你可能过采样(重复帧)或欠采样(跳帧)。如果你关心这一点,那么请尝试使用AVAssetReader读取视频中的所有帧:

let reader = try! AVAssetReader(asset: asset) 

let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0] 

// read video frames as BGRA 
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:[String(kCVPixelBufferPixelFormatTypeKey): NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)]) 

reader.addOutput(trackReaderOutput) 
reader.startReading() 

while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() { 
    if let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) { 
     // now you have images as CVImageBuffers/CVPixelBuffers 
     process(imageBuffer) 
    } 
} 

这给你所有的帧为CVPixelBuffer秒。您可以使用代码like this轻松将它们转换为其他类型。如果您对帧的时间戳感兴趣,请致电CMSampleBufferGetPresentationTimeStamp(sampleBuffer)

+0

谢谢,这看起来像一个更好的解决方案。 – terrafirma9

+0

很好的答案。有用。 – Leo

相关问题