9

我需要拍摄视频,将每一帧转换为图像并将这些图像保存到磁盘。为了提高效率,我想使用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 来了解每一帧的处理时间?也许只是我错过了什么?任何指导或建议将不胜感激。

4

1 回答 1

8

我会逐步处理图像,无论如何您将无法一次将它们全部放入内存中。为此,您可以在特定时间使用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)
        }
    }

这为您提供了所有帧为CVPixelBuffers。您可以使用这样的代码轻松地将它们转换为其他类型。如果您对帧的时间戳感兴趣,请致电CMSampleBufferGetPresentationTimeStamp(sampleBuffer).

于 2016-09-23T00:51:44.643 回答