web-dev-qa-db-ja.com

CIFilterをビデオファイルに適用して保存する

CIFilterをビデオに適用するための高速で軽量な方法はありますか?言及する前に、私はhaveを見て GPUImage -それは非常に強力なように見えます 魔法 コードですが、私がやろうとしていることには本当にやり過ぎです。

本質的に、私はしたい

  1. /tmp/myVideoFile.mp4に保存されていると言うビデオファイルを取ります
  2. このビデオファイルにCIFilterを適用します
  3. ビデオファイルを別の(または同じ)場所、たとえば/tmp/anotherVideoFile.mp4に保存します

AVPlayerItemVideoOutputを使用して、非常に簡単かつ迅速に再生されるビデオにCIFilterを適用することができました。

let player = AVPlayer(playerItem: AVPlayerItem(asset: video))
let output = AVPlayerItemVideoOutput(pixelBufferAttributes: nil)
player.currentItem?.addOutput(self.output)
player.play()

let displayLink = CADisplayLink(target: self, selector: #selector(self.displayLinkDidRefresh(_:)))
displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)

func displayLinkDidRefresh(link: CADisplayLink){
    let itemTime = output.itemTimeForHostTime(CACurrentMediaTime())
    if output.hasNewPixelBufferForItemTime(itemTime){
        if let pixelBuffer = output.copyPixelBufferForItemTime(itemTime, itemTimeForDisplay: nil){
            let image = CIImage(CVPixelBuffer: pixelBuffer)
            // apply filters to image
            // display image
        }
    }
}

これはうまくいきますが、私は持っています たくさん すでに保存されているビデオファイルにフィルターを適用する方法を見つけるのにほんの少しの問題があります。基本的に、上記で行ったことを実行し、AVPlayerを使用してビデオを再生し、再生時にすべてのフレームからピクセルバッファーを取得するオプションがありますが、これはバックグラウンドでのビデオ処理では機能しません。 。フィルターが適用されるのがビデオである限り、ユーザーが待たなければならないことをユーザーは喜ばないと思います。

過度に単純化されたコードで、私は次のようなものを探しています:

var newVideo = AVMutableAsset() // We'll just pretend like this is a thing

var originalVideo = AVAsset(url: NSURL(urlString: "/example/location.mp4"))
originalVideo.getAllFrames(){(pixelBuffer: CVPixelBuffer) -> Void in
    let image = CIImage(CVPixelBuffer: pixelBuffer)
        .imageByApplyingFilter("Filter", withInputParameters: [:])

    newVideo.addFrame(image)
}

newVideo.exportTo(url: NSURL(urlString: "/this/isAnother/example.mp4"))

ビデオファイルにフィルターを適用して保存する方法はありますか(ここでも、GPUImageを使用せず、理想的にはiOS 7で動作します)。たとえば、これは保存されたビデオを取得し、それをAVAssetにロードし、CIFilterを適用してから、新しいビデオを別の場所に保存します。

13
Jojodmo

IOS 9/OS X 10.11/tvOSには、ビデオにCIFiltersを適用するための便利な方法があります。 AVVideoCompositionで動作するため、再生とファイル間のインポート/エクスポートの両方に使用できます。メソッドのドキュメントについては、 AVVideoComposition.init(asset:applyingCIFiltersWithHandler:) を参照してください。

例があります AppleのCore Imageプログラミングガイド もあります:

let filter = CIFilter(name: "CIGaussianBlur")!
let composition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in

    // Clamp to avoid blurring transparent pixels at the image edges
    let source = request.sourceImage.clampingToExtent()
    filter.setValue(source, forKey: kCIInputImageKey)

    // Vary filter parameters based on video timing
    let seconds = CMTimeGetSeconds(request.compositionTime)
    filter.setValue(seconds * 10.0, forKey: kCIInputRadiusKey)

    // Crop the blurred output to the bounds of the original image
    let output = filter.outputImage!.cropping(to: request.sourceImage.extent)

    // Provide the filter output to the composition
    request.finish(with: output, context: nil)
})

その部分が構成を設定します。それが終わったら、それをAVPlayerに割り当てて再生するか、AVAssetExportSessionを使用してファイルに書き込むことができます。あなたは後者を追いかけているので、ここにその例があります:

let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset1920x1200)
export.outputFileType = AVFileTypeQuickTimeMovie
export.outputURL = outURL
export.videoComposition = composition

export.exportAsynchronouslyWithCompletionHandler(/*...*/)

これについてはもう少しあります Core ImageのWWDC15セッションで、約20分で始まります


以前のOSで動作するソリューションが必要な場合は、もう少し複雑です。

余談ですが、本当にサポートする必要があるのはどれくらい前かを考えてください。 2016年8月15日現在 、デバイスの87%がiOS 9.0以降を使用し、97%がiOS8.0以降を使用しています。潜在的な顧客ベースのごく一部をサポートするために多大な努力を払うと、プロジェクトが完了して展開の準備が整うまでにさらに小さくなりますが、コストに見合う価値はないかもしれません。

これを行うには、いくつかの方法があります。いずれにせよ、ソースフレームを表すCVPixelBuffersを取得し、 それらからCIImagesを作成 、フィルターを適用し、 新しいCVPixelBuffers

  1. ピクセルバッファの読み取りと書き込みには、AVAssetReaderAVAssetWriterを使用します。これを行う方法の例(読み取りと書き込みの部分。その間にフィルタリングを行う必要があります)は、AppleのAVFoundationプログラミングガイドの Export の章にあります。

  2. カスタムコンポジタークラスでAVVideoCompositionを使用します。カスタムコンポジターには、ピクセルバッファーへのアクセスを提供するオブジェクトと、処理されたピクセルバッファーを提供する方法が提供されます AVAsynchronousVideoCompositionRequest Appleには AVCustomEdit というサンプルコードプロジェクトがあり、これを行う方法を示しています(ここでも、サンプルバッファの取得と戻りの部分だけです。Coreで処理する必要があります) GLレンダラー)を使用する代わりに画像。

これら2つのうち、AVVideoCompositionルートは、再生とエクスポートの両方にコンポジションを使用できるため、より柔軟です。

22
rickster