I'm trying to record video via AVAssetWriter. NSData is successfully written to the file path that I specify and extracted as an AVAsset, but it seems to be data representing only 1 frame of the recording, not multiple frames appended together as a video. When I try to play the video in the UI, it immediately completes. And the size of the NSData object is much smaller than expected for a video. That's what makes me think it's only appending 1 frame. Here's my code:
func setupCaptureSession() {
self.session = AVCaptureSession()
session!.sessionPreset = AVCaptureSessionPresetMedium
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
do {
let input = try AVCaptureDeviceInput(device: device)
session!.addInput(input)
} catch {
}
let captureLayer = AVCaptureVideoPreviewLayer(session: session)
captureLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
let window = UIApplication.sharedApplication().keyWindow!
let layerRect = window.layer.bounds
captureLayer.bounds = layerRect
captureLayer.position = CGPointMake(CGRectGetMidX(layerRect), CGRectGetMidY(layerRect))
self.cameraView = NSBundle.mainBundle().loadNibNamed("CameraView", owner: self, options: nil)[0] as? CameraView
cameraView!.frame = layerRect
cameraView!.layer.insertSublayer(captureLayer, atIndex: 0)
window.addSubview(cameraView!)
let output = AVCaptureVideoDataOutput()
session!.addOutput(output)
let queue = dispatch_queue_create("myQueue", nil)
output.setSampleBufferDelegate(self, queue: queue)
output.videoSettings = [kCVPixelBufferPixelFormatTypeKey: NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)]
output.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = .Portrait
session!.startRunning()
}
Sample buffer delegate:
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
if self.recording == true {
let window = UIApplication.sharedApplication().keyWindow!
if let path = Utils.documentDirectory().URLByAppendingPathComponent("temp_video").path {
print("recording")
self.videoFromBuffer(sampleBuffer, path: path, size: window.frame.size, duration: self.duration)
}
}
}
And the AVAssetWriter:
private func videoFromBuffer(buffer: CMSampleBuffer, path: String, size: CGSize, duration: Int64) {
do {
let writer = try AVAssetWriter(URL: NSURL(fileURLWithPath: path), fileType: AVFileTypeMPEG4)
let settings = [AVVideoCodecKey: AVVideoCodecH264,
AVVideoWidthKey: NSNumber(integer: Int(size.width)),
AVVideoHeightKey: NSNumber(integer: Int(size.height))]
let writerInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: settings)
writerInput.expectsMediaDataInRealTime = true
writer.addInput(writerInput)
writer.startWriting()
writer.startSessionAtSourceTime(kCMTimeZero)
writerInput.appendSampleBuffer(buffer)
writerInput.markAsFinished()
writer.endSessionAtSourceTime(CMTimeMake(duration, 1))
writer.finishWritingWithCompletionHandler({ () -> Void in
})
} catch {
print(error)
}
}
Why is the resulting data not a full video?