カテゴリー
iOS Swift

Videoファイルからフレームを抽出

Vision Frameworkを使って動画解析をするための前準備として、動画ファイルから毎フレームを抽出し、UIImageViewへ描画するにはどうしたら良いのか。Appleのサンプルコードを勉強し、ミニマム実装をしてみました。

このコードのキモは、AVAssetReaderTrackOutputクラスのcopyNextSampleBuffer()メソッドを利用し、CVPixelBufferオブジェクトを得て、UIImageへ描画することです。

func nextFrame() -> CVPixelBuffer? { 
    guard let sampleBuffer = self.videoAssetReaderOutput.copyNextSampleBuffer() else {
        return nil
    }
    return CMSampleBufferGetImageBuffer(sampleBuffer)
}

while loop内で nextFrame == true を満たす場合にフレームの抽出を続け、

while true {
    guard let frame = videoReader.nextFrame() else {
        break
    }
    // Draw results
    delegate?.displayFrame(frame, withAffineTransform: videoReader.affineTransform)
    usleep(useconds_t(videoReader.frameRateInSeconds))
}

得たframe: CVPixelBufferをdelegateメソッドに送り、ViewController内のUIImageViewに描画します。

func displayFrame(_ frame: CVPixelBuffer?, withAffineTransform transform: CGAffineTransform) {
    DispatchQueue.main.async {
        if let frame = frame {
            let ciImage = CIImage(cvPixelBuffer: frame).transformed(by: transform)
            let uiImage = UIImage(ciImage: ciImage)
            self.imageView.image = uiImage
        }
    }
}