2017-01-23 8 views
2

결과없이 문제를 처리하는 데 상당한 시간이 걸린 후에 여기에서 질문하기로했습니다.스위프트에서 AVCaptureVideoDataOutput을 사용하여 비디오 녹화하기

우리는 AVCaptureVideoDataOutput을 사용하여 카메라의 라이브 비디오의 픽셀 데이터를 얻고 captureOutput 기능을 사용합니다. 그러나 우리는 또한 그 데이터를 사용하여 비디오를 녹화하기를 원합니다. 게다가이 비디오 녹화가 AVCaptureMovieFileOutput으로 녹화 된 비디오만큼 압축되었는지 궁금합니다.

AVCaptureMovieFileOutput을 사용하여 문제없이 녹화했음을 알려드립니다. 그러나 AVCaptureMovieFileOutputAVCaptureVideoDataOutput은 동시에 작동하지 않습니다.

아래의 기능은 captureOutput입니다.

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) { 

    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! 

    CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 

    let baseAddress    = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) 
    let bytesPerRow    = CVPixelBufferGetBytesPerRow(imageBuffer) 
     videoWidth    = CVPixelBufferGetWidth(imageBuffer) 
     videoHeight    = CVPixelBufferGetHeight(imageBuffer) 
    let colorSpace    = CGColorSpaceCreateDeviceRGB() 

    var bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) 

    let context = CGContext(data: baseAddress, width: videoWidth, height: videoHeight, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) 

    let imageRef = context!.makeImage() 

    CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 

    let data = imageRef!.dataProvider!.data as! NSData 
    let pixels = data.bytes.assumingMemoryBound(to: UInt8.self) 


    /* Because what we are doing with pixel data irrelevant to the question we omitted the rest of the code to make it simple */ 




} 

답변

1

라이브 비디오의 기본적인 분석을 위해 픽셀 정보를 얻을 때 비디오를 녹화하는 방법을 찾았습니다.

먼저 AVAssetWriter를 설정하고 실제 녹음 순서를 지정하기 전에 해당 함수를 호출합니다.

var sampleBufferGlobal : CMSampleBuffer? 
let writerFileName = "tempVideoAsset.mov" 
var presentationTime : CMTime! 
var outputSettings = [String: Any]() 
var videoWriterInput: AVAssetWriterInput! 
var assetWriter: AVAssetWriter! 


func setupAssetWriter() { 

    eraseFile(fileToErase: writerFileName) 

    presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBufferGlobal!) 

    outputSettings = [AVVideoCodecKey : AVVideoCodecH264, 
         AVVideoWidthKey : NSNumber(value: Float(videoWidth)), 
         AVVideoHeightKey : NSNumber(value: Float(videoHeight))] as [String : Any] 

    videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings) 


    assetWriter = try? AVAssetWriter(outputURL: createFileURL(writerFileName), fileType: AVFileTypeQuickTimeMovie) 

    assetWriter.add(videoWriterInput) 

} 

나는 녹음 할 수있는 다른 기능을 쓰고 나는 동일한 기능에, sampleBufferGlobal, sampleBufferGlobal = sampleBuffer에 sampleBuffer을 복사 한 후 녹음을 할 captureOutput 기능에서 해당 기능을했다.

func writeVideoFromData() { 

    if assetWriter?.status == AVAssetWriterStatus.unknown { 

     if ((assetWriter?.startWriting) != nil) { 

      assetWriter?.startWriting() 
      assetWriter?.startSession(atSourceTime: presentationTime) 

     } 
    } 



     if assetWriter?.status == AVAssetWriterStatus.writing { 

      if (videoWriterInput.isReadyForMoreMediaData == true) { 


       if videoWriterInput.append(sampleBufferGlobal!) == false { 

        print(" we have a problem writing video") 

       } 
      } 
     }   
    } 

다음 녹음 기능을 사용하여 다음 기능을 사용했습니다.

func stopAssetWriter() { 

    videoWriterInput.markAsFinished() 

    assetWriter?.finishWriting(completionHandler: { 


     if (self.assetWriter?.status == AVAssetWriterStatus.failed) { 

      print("creating movie file is failed ") 

     } else { 

      print(" creating movie file was a success ") 

      DispatchQueue.main.async(execute: {() -> Void in 




      }) 

     } 

    }) 

}