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.