How to save a live video capture where CIFilter is applied, in Swift 3.0?

Viewed 359

I have an imageView, beneath that a 'record' button. When app starts, video capture starts (just capture, no saving anywhere) using AVCaptureSession object. Tap the record button, recording (actual saving) should start, tap the same again and the same will stop.

Plain video capturing starts using below code.

    let captureSession = AVCaptureSession()
    captureSession.sessionPreset = AVCaptureSessionPresetPhoto
    let videoOutput = AVCaptureVideoDataOutput()

    videoOutput.setSampleBufferDelegate(self as AVCaptureVideoDataOutputSampleBufferDelegate, queue: DispatchQueue(label: "sample buffer delegate"))
    captureSession.addOutput(videoOutput)
    captureSession.startRunning()

Below is the record button action

@IBAction func recordFunc() {

    if(startRecording) {
       //Initialise the saving video tools

       let fileUrl = docsurl.appendingPathComponent("newMovie1.mp4") 
       //docsurl has the document directory path
       videoWriter = try? AVAssetWriter(outputURL: fileUrl, fileType: AVFileTypeQuickTimeMovie)

       let outputSettings: [String : Any] = [AVVideoCodecKey : AVVideoCodecH264, AVVideoWidthKey : NSNumber(value: Float(outputSize.width)), AVVideoHeightKey : NSNumber(value: Float(outputSize.height))]

       writerInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings)
       writerInput.expectsMediaDataInRealTime = true     
       videoWriter.add(writerInput)

       //Now, the killer line for saving the video
       adapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: writerInput, sourcePixelBufferAttributes: nil)  

       videoWriter.startWriting()
       videoWriter.startSession(atSourceTime: kCMTimeZero)
    }
    else {
       //Video saving is complete !!

       self.writerInput.markAsFinished()
       self.videoWriter.finishWriting { () -> Void in
            print("FINISHED.")
       }
    }
}

In the above code, adapter - AVAssetWriterInputPixelBufferAdaptor type, has some special role in saving video.


Now the main the decisive code block, causing pain is here:
The AVCaptureVideoDataOutputSampleBufferDelegate's captureOutput() method

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

        connection.videoOrientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!

        let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
        cameraImage = CIImage(cvPixelBuffer: pixelBuffer!)

        let comicEffect = CIFilter(name: "CIComicEffect")!  // The great 'CIFilter'

        //Below 2 lines calls a function which detects a face and attaches two cartoon eye images to the user's eye positions.
        let leftEyeImage = eyeImage(cameraImage: cameraImage!, backgroundImage: cameraImage!, leftEye: true)
        let rightEyeImage = eyeImage(cameraImage: cameraImage!, backgroundImage: leftEyeImage, leftEye: false)

        comicEffect.setValue(rightEyeImage, forKey: kCIInputImageKey)

        let outputImage = comicEffect.value(forKey: kCIOutputImageKey) as! CIImage
        let filteredImage = UIImage(ciImage: outputImage) 

        //Feed the imageView, the UIImage thing 'filteredImage'
        DispatchQueue.main.async(){
            self.imgViewActual.image = filteredImage 
        }

        //The MAIN line, only responsible for saving is below.  
        self.adapter.append(somePixelBuffr , withPresentationTime: someTime)
    }

So, somePixelBuffr = ??? and someTime = ???
Or is there anything I should add here or modify here. Please suggest.

Constraints: Solution in Swift >=3.0, Video capturing should not lag.

0 Answers
Related