2016-09-22 11 views
2

私はビデオを撮影し、各フレームを画像に変換し、これらの画像をディスクに保存する必要があります。私は、効率のためにAVAssetImageGeneratorを使用したい、と次のようなコードを持っていると思います:generateCGImagesAsynchronouslyが完全に終了したときは、どうすればわかりますか?

問題がすべて画像生成が完了したとき、私は知らないということですが、私は一度、すべてのフレームを行動を取る必要がありますディスクに書き込まれます。例:

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を使用してみてください:これはCVPixelBuffer sとあなたのすべてのフレームを与える

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) 
    } 
} 

。コードlike thisを使用して簡単に他のタイプに変換できます。フレームのタイムスタンプに興味がある場合は、CMSampleBufferGetPresentationTimeStamp(sampleBuffer)に電話してください。

+0

ありがとうございます、これはより良いソリューションのようです。 – terrafirma9

+0

良い答えです。できます。 – Leo

関連する問題