2016-08-24 12 views
4

ビデオにCIFilterを適用する方法は、軽量で可能な限り速い方法はありますか?それが言及される前に、私はを見てGPUImageを見た - それは非常に強力なの魔法コードのように見えるが、それは私がやろうとしているもののために本当に残酷だ。ビデオファイルにCIFilterを適用して保存する

基本的に、私は/tmp/myVideoFile.mp4

  • CIFilter異なる(または同じ)にビデオファイルを保存
  • この動画ファイルを適用で保存され、ビデオファイルを取る
    1. したいと言うだろうlocation、say /tmp/anotherVideoFile.mp4

    を使用して非常に簡単にすばやく再生される動画に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を適用して新しいビデオを別の場所に保存します。

    +0

    私はこれを実行することができました。コードは[GitHubで利用可能です](https://github.com/jojodmo/VideoFilterExporter) – Jojodmo

    答えて

    10

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

    も、たとえばin Apple's Core Image Programming Guideあります:一部の構図を設定

    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(/*...*/) 
    

    このin the WWDC15 session on Core Image, starting around 20 minutes inについてもう少しがあります。


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

    脇に:あなたが本当にサポートする必要があるかについて考えてみましょう。 As of August 15, 2016、デバイスの87%がiOS 9に搭載されています。0以上、97%がiOS 8.0以降の にあります。潜在的な顧客ベースの小さな部分をサポートするために多くの努力を払っています。これは、プロジェクトを完了して展開する準備ができて、コストがそれほど高くない場合でも、さらに小さくなります。

    これにはいくつかの方法があります。いずれにしても、ソースフレームを表すCVPixelBuffercreating CIImages from them、フィルタを適用する、rendering out new CVPixelBuffersが表示されます。ピクセルバッファを読み書きする

    1. 使用AVAssetReaderAVAssetWriter。 AppleのAVFoundation Programming GuideのExportの章で、これを行う方法(読み書き部分、それでもフィルタリングを行う必要があります)の例があります。

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

    これら2つのうち、AVVideoCompositionルートは、再生とエクスポートの両方の構成を使用できるため、柔軟性があります。

    +0

    あなたの答えをありがとう!私は 'AVVideoComposition'で多くのことをやったことがありますが、私は[' startVideoCompositionRequest() '](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVVideoCompositing_Protocol /#// apple_ref/occ/intfm/AVVideoCompositing/startVideoCompositionRequest:CVPixelBufferを取得する関数です。私の 'AVVideoCompositionInstruction'クラスに' passthroughTrackID'を設定すると、呼び出されますが、トラックID(したがってピクセルバッファもありません)はありません。ただし、トラックIDを設定しないと呼び出されることはありません。 – Jojodmo

    +0

    何が原因なのか考えていますか?もしそれがもっと複​​雑なのであれば(それはおそらく)、私は別の質問を掲示してそれを聞いてきます - 私はあなたに最初に何かを本当に明かに入れて尋ねると思った。 – Jojodmo

    +0

    何も見ないと言うのは難しい)コードであり、おそらく独自の質問としては良いでしょう。 – rickster

    関連する問題