我需要拍摄视频,将每个帧转换为图像并将这些图像保存到磁盘。为了提高效率,我想使用AVAssetImageGenerator
,并且代码类似于以下代码:
问题是我不知道所有图像生成何时完成,但是我需要在所有帧都写入磁盘后采取措施。例如:
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
})
这是上面的第二步,这让我感到沮丧。我想我可以尝试计算调用完成处理程序的次数,并在计数等于帧数时触发适当的方法。
但是我想知道是否有办法使用API来了解每个帧何时被处理?也许只是我错过的东西?任何指导或建议将不胜感激。
答案 0 :(得分:6)
我会逐步处理图像,无论如何你都无法将它们全部放入内存中。为此,您可以使用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
这会将所有帧都显示为CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
。您可以使用代码like this轻松将它们转换为其他类型。如果您对帧的时间戳感兴趣,请致电 $foobar = $foo?->bar();
。