2017-09-08 10 views
2

ビデオにオーバーレイを追加するAVAssetWriterでアプリケーションを構築しています。オーバーレイを追加しようとしないときはうまく動作します。しかし、オーバーレイを追加すると、ビデオが半分から切り取られて見えます(スクリーンショットで見ることができます)。ここでオーバーレイを追加すると、キャプチャされたビデオが非常に遅い

は私addOverlayToImage機能である:

func addOverlayToImage(from filteredImage: UIImage) -> UIImage { 
    UIGraphicsBeginImageContextWithOptions(self.imageView.frame.size, false, 1.0); 
    self.imageView.layer.render(in: UIGraphicsGetCurrentContext()!) 
    let imageWithText = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext(); 
    return imageWithText! 
} 

私はcaptureOutput内部関数を呼び出す:

func captureOutput(_ captureOutput: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection) { 
    self.bufferVideoQueue.async() { 
    let imageWithOverlay = self.addOverlayToImage(from: self.filteredImage) 
    let buffer = self.imageToBuffer(from: imageWithOverlay) 
    self.assetWriterPixelBufferInput?.append(buffer!, withPresentationTime: self.currentTime) 
    } 
} 

そしてimageToBuffer機能:

func imageToBuffer(from image: UIImage) -> CVPixelBuffer? { 
    let attrs = [ 
     String(kCVPixelBufferCGImageCompatibilityKey) : kCFBooleanTrue, 
     String(kCVPixelBufferCGBitmapContextCompatibilityKey) : kCFBooleanTrue 
    ] as [String : Any] 
    var buffer : CVPixelBuffer? 
    let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs as CFDictionary, &buffer) 
    guard (status == kCVReturnSuccess) else { 
     return nil 
    } 

    CVPixelBufferLockBaseAddress(buffer!, CVPixelBufferLockFlags(rawValue: 0)) 
    let pixelData = CVPixelBufferGetBaseAddress(buffer!) 

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB() 
    let context = CGContext(data: pixelData, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(buffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) 

    context?.translateBy(x: 0, y: image.size.height) 
    context?.scaleBy(x: 1.0, y: -1.0) 

    UIGraphicsPushContext(context!) 
    image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) 
    UIGraphicsPopContext() 
    CVPixelBufferUnlockBaseAddress(buffer!, CVPixelBufferLockFlags(rawValue: 0)) 

    return buffer 
} 

やビデオからのスクリーンショット:

enter image description here

+0

は、あなたが 'addOverlayToImage(...)'を呼び出すコードを表示することができますか?フレームごとに毎回呼び出す場合は、デバイスが各フレームをレンダリングするのに十分な時間が得られていない可能性があります。 – EmilioPelaez

+0

@EmilioPelaezねえ、私は質問を更新しました。プレビューbtwには遅延がありません。出力にのみ表示されます。 – hackio

+0

これを解決しましたか? – Crashalot

答えて

0

私はそのエラーを見たことがないので、私は確信していませんが、フレームで処理中の処理がフレーム時間(1 /おそらく30分の1)。

可能な限り時間を短縮することをお勧めします。私が見ることのできるところから、UIViewからUIImageを作成し、それをCVPixelBufferに変換しています。

これはすべてのフレームで起こっていますが、コンテンツはすべてのようには見えません。すべてのフレームを変更するにはが必要です。

バッファーを保存し、captureOutput(...)に内容が変更されているかどうかを確認することをお勧めします。保存されたバッファを使用できない場合は、再計算することができますが、今は毎分だけ発生します(私はあなたのスクリーンショットから推測しています)ので、ビデオには影響しません。

最後に、コードを非同期で実行しているため、問題が発生している可能性があります。その部分を削除し、そのコードをデリゲートメソッドで実行することをお勧めします。 (注:ドキュメントで非同期に指示する場合は無視してください)

+0

答えをありがとう。実際にはフレームごとに変化する可能性のあるオーバーレイを追加する予定ですので、これは私にとっては解決策ではありません。 – hackio

+0

現在の設定で解決策を試してみてください。その場合、オーバーレイをレンダリングするのにかかる時間を短縮する必要があります。今では 'CGContext'にレンダリングした' CALayer'を持って、 'CGContext'に描画して' CVPixelBuffer'にコピーする 'UIImage'を作成しています。 'imageView'の内容をどのように作成しているかによって、すべてのプロセスを単一のステップに減らすことができます。 – EmilioPelaez

+0

同様の問題が発生しています。 'imageView'の内容を作成するためにあなたが参照している単一のステップは何でしょうか?たとえば、5秒ごとに1回だけ変更する必要があるテキストオーバーレイがあります。 – Crashalot

1

AVAssetWriterInputを設定して、リアルタイムでデータを指定しようとしましたか(expectsMediaDataInRealTimeをtrueに設定しましたか?これはリアルタイム(ライブカメラ)データを書き込むときに大きな違いをもたらし、適切に設定されていないと出力が遅くなる可能性があります。

https://developer.apple.com/documentation/avfoundation/avassetwriterinput

https://developer.apple.com/documentation/avfoundation/avassetwriterinput/1387827-expectsmediadatainrealtime

+0

また、オーバーレイを追加しない限り、ビデオは遅くはありません。 addOverlayToImage関数はそれを遅らせます。 – hackio

+0

残念ながらCVPixelBufferの変換は非常に遅いです。あなたが見ることができる1つのことは、どれくらいのバッファが販売されているのか、そしてどれだけ多くのバッファが変換されているのかを数えることです。あなたが30FPSの標準レートでビデオを書いているなら、それ以上のCVPixelBuffersを販売している可能性があります。その場合、変換が過剰です。バッファーを数えてみて、できるだけ所望のフレームレートに必要なものに近いものに変換していることを確認してください。 –

+0

ちょっとティム、詳細なアンワーのおかげで、私は実際にコントロールを行う方法を理解できませんでした。 Btw私はfpsで何も変更しなかったので、私はそれがデフォルト値だと思います。 – hackio

関連する問題