2016-09-22 77 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

相關問題