(Swift) Save video output to file

I am collecting video, audio and photos in one view controller, ideally with one capture session.

The problem I am currently facing is with video recording. It displays the output in my preview. I have the AVCaptureFileOutputRecordingDelegate

following method enabled and implemented.

func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!)

      


var outputUrl = NSURL(fileURLWithPath: NSTemporaryDirectory() + "test.mp4")
movieOutput?.startRecordingToOutputFileURL(outputUrl, recordingDelegate: self)

      

I am getting this error when I run the code above:

'NSInvalidArgumentException', reason: '*** -[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] - no active/enabled connections.'

      

My config:

func configureCaptureSession() {
    capturedPhoto.contentMode = .ScaleAspectFill
    capturedPhoto.clipsToBounds = true
    capturedPhoto.hidden = true

    captureSession = AVCaptureSession()

    captureSession!.beginConfiguration()

    captureSession!.sessionPreset = AVCaptureSessionPresetPhoto


    var error: NSError?

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryRecord, error: &error)
    AVAudioSession.sharedInstance().setActive(true, error: &error)

    var audioDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio)
    var audioInput = AVCaptureDeviceInput(device: audioDevice, error: &error)

    if error == nil && captureSession!.canAddInput(audioInput) {
        captureSession!.addInput(audioInput)
    }

    photoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    photoDeviceInput = AVCaptureDeviceInput(device: photoCaptureDevice, error: &error)

    if error == nil && captureSession!.canAddInput(photoDeviceInput) {
        captureSession!.addInput(photoDeviceInput)

        stillImageOutput = AVCaptureStillImageOutput()
        stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
        if captureSession!.canAddOutput(stillImageOutput) {
            captureSession!.addOutput(stillImageOutput)
        }

        movieOutput = AVCaptureMovieFileOutput()
        if captureSession!.canAddOutput(movieOutput) {
            captureSession!.addOutput(movieOutput)
        }

        photoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        photoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
        photoPreviewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait

        cameraView.layer.addSublayer(photoPreviewLayer)

        contentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "focusPhoto:"))

    }

    captureSession!.commitConfiguration()
    captureSession!.startRunning()
}

      

+3


source to share


1 answer


I found two problems in your code.

Duplicate file

According to Apple documentation startRecordingToOutputFileURL:recordingDelegate:

:

Starts recording to the specified URL. The method sets the URL of the file to which the receiver is currently writing the output medium. If a file at the specified URL already exists when you start capturing, writing to the new file will fail.

IOS does not support this precise file switching. You must call stopRecording before calling this method again to avoid errors. When recording stops, either by calling stopRecording, by modifying files using this method, or due to an error, the rest of the data that needs to be included in the file will be recorded in the background. Hence, you must specify a delegate that will be notified when all data has been written to the file using the captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:

.

In your case, if it test.mp4

already exists when you start a new entry, it won't work. Therefore, it is best to give the recorded file a unique name each time. For example, use the current timestamp.

Session preset



In your code, you have set sessionPreset

to AVCaptureSessionPresetPhoto

:

captureSession!.sessionPreset = AVCaptureSessionPresetPhoto

      

But in my personal experience it is not suitable for video output and will lead to your error. Please go to AVCaptureSessionPresetHigh

and try again. It is also recommended to call canSetSessionPreset:

and apply the preset only if it canSetSessionPreset:

returns YES

.

Sample code

Apple offers a good code sample for usage AVFoundation

, you can check it out.

+3


source







All Articles