我怎么知道 generateCGImagesAsynchronously 何时完全完成?
How do I know when generateCGImagesAsynchronously has completely finished?
我需要拍摄一段视频,将每一帧转换为图像并将这些图像保存到磁盘。为了效率起见,我想使用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
})
上面的第 2 步让我感到困惑。我想我可以尝试计算调用完成处理程序的次数,并在计数等于帧数时触发适当的方法。
但我想知道是否有一种方法可以使用 API 来了解每一帧的处理时间?也许只是我错过了什么?任何指导或建议将不胜感激。
我会逐步处理图像,无论如何你无法一次将它们全部放入内存。为此,您可以使用 assetGenerator.copyCGImageAtTime
.
在特定时间对视频进行采样
但是你可能会过采样(重复帧)或欠采样(跳帧)。如果您关心这一点,请尝试使用 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)
}
}
这会为您提供 CVPixelBuffer
的所有帧。您可以使用代码 like this 轻松地将它们转换为其他类型。如果您对帧的时间戳感兴趣,请调用 CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
.
我需要拍摄一段视频,将每一帧转换为图像并将这些图像保存到磁盘。为了效率起见,我想使用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
})
上面的第 2 步让我感到困惑。我想我可以尝试计算调用完成处理程序的次数,并在计数等于帧数时触发适当的方法。
但我想知道是否有一种方法可以使用 API 来了解每一帧的处理时间?也许只是我错过了什么?任何指导或建议将不胜感激。
我会逐步处理图像,无论如何你无法一次将它们全部放入内存。为此,您可以使用 assetGenerator.copyCGImageAtTime
.
但是你可能会过采样(重复帧)或欠采样(跳帧)。如果您关心这一点,请尝试使用 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)
}
}
这会为您提供 CVPixelBuffer
的所有帧。您可以使用代码 like this 轻松地将它们转换为其他类型。如果您对帧的时间戳感兴趣,请调用 CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
.