[英]How do I know when generateCGImagesAsynchronously has completely finished?
I have a requirement to take a video, convert each frame to and image and save these images to disk.我需要拍摄视频,将每一帧转换为图像并将这些图像保存到磁盘。 I'd like to use
AVAssetImageGenerator
for efficiency's sake, and have code similar to the following:我想使用
AVAssetImageGenerator
以提高效率,并具有类似于以下的代码:
The issue is that I don't know when all image generation is complete, but I need to take action once all frames are written to disk.问题是我不知道所有图像生成何时完成,但是一旦所有帧都写入磁盘,我需要采取行动。 For example:
例如:
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
})
It's step 2 above that's tripping me up.上面的第 2 步让我绊倒了。 I imagine I can try to count the number of times the completion handler gets called, and trigger the appropriate method when the count equals the number of frames.
我想我可以尝试计算调用完成处理程序的次数,并在计数等于帧数时触发适当的方法。
But I'm wondering if there's a way to use the API to know when every frame has been processed?但我想知道是否有一种方法可以使用 API 来知道何时处理了每一帧? Maybe just something I've missed?
也许只是我错过了什么? Any guidance or advice would be appreciated.
任何指导或建议将不胜感激。
I would progressively process the images, you won't be able to fit them all in memory at once anyway.我会逐步处理图像,无论如何您都无法一次将它们全部放入内存中。 To do that you could sample the video at certain times using
assetGenerator.copyCGImageAtTime
.为此,您可以使用
assetGenerator.copyCGImageAtTime
在特定时间对视频进行assetGenerator.copyCGImageAtTime
。
But then you may oversample (repeating frames) or undersample (skipping frames).但是你可能会过度采样(重复帧)或采样不足(跳帧)。 If you care about that, then try using
AVAssetReader
to read all the frames in the video:如果您关心这一点,请尝试使用
AVAssetReader
读取视频中的所有帧:
let reader = try! AVAssetReader(asset: asset)
let videoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]
// read video frames as BGRA
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:[String(kCVPixelBufferPixelFormatTypeKey): NSNumber(value: kCVPixelFormatType_32BGRA)])
reader.add(trackReaderOutput)
reader.startReading()
while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
if let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
// now you have images as CVImageBuffers/CVPixelBuffers
process(imageBuffer)
}
}
This gives you all the frames as CVPixelBuffer
s.这将为您提供所有帧作为
CVPixelBuffer
s。 You can easily convert them to other types using code like this .您可以轻松地将它们转换为其他类型的使用代码这样。 If you're interested in the timestamp of the frames, call
CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
.如果您对帧的时间戳感兴趣,请调用
CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.