简体   繁体   English

(Swift)将视频输出保存到文件

[英](Swift) Saving video output to file

I'm capturing video, audio, and photos in one view controller, ideally with one capture session. 我在一个视图控制器中捕获视频,音频和照片,理想情况下是一个捕获会话。

The issue I'm currently having is with recording video. 我目前遇到的问题是录制视频。 It displays output to my preview fine. 它显示输出到我的预览正常。 I have the AVCaptureFileOutputRecordingDelegate enabled and the following method implemented. 我启用了AVCaptureFileOutputRecordingDelegate并实现了以下方法。

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'm getting this error when I run the above code though: 我在运行上面的代码时遇到了这个错误:

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

My configuration: 我的配置:

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()
}

I found two problems in your code. 我在你的代码中发现了两个问题。

Duplicated file 重复的文件

As per Apple documentation of startRecordingToOutputFileURL:recordingDelegate: : 根据Apple的startRecordingToOutputFileURL:recordingDelegate:文档startRecordingToOutputFileURL:recordingDelegate: ::

Starts recording to a given URL. 开始录制到给定的URL。 The method sets the file URL to which the receiver is currently writing output media. 该方法设置接收器当前正在写入输出媒体的文件URL。 If a file at the given URL already exists when capturing starts, recording to the new file will fail. 如果捕获开始时已存在给定URL的文件,则记录到新文件将失败。

In iOS, this frame accurate file switching is not supported. 在iOS中,不支持此帧精确文件切换。 You must call stopRecording before calling this method again to avoid any errors. 在再次调用此方法之前,必须调用stopRecording以避免任何错误。 When recording is stopped either by calling stopRecording, by changing files using this method, or because of an error, the remaining data that needs to be included to the file will be written in the background. 通过调用stopRecording,通过使用此方法更改文件或由于错误停止记录时,需要包含在文件中的剩余数据将在后台写入。 Therefore, you must specify a delegate that will be notified when all data has been written to the file using the captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error: method. 因此,您必须指定一个委托,当使用captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:将所有数据写入文件时将通知该captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error: method。

In your case, if test.mp4 is already exist when you start a new recording, it will fail. 在您的情况下,如果在开始新录制时test.mp4已存在,则会失败。 So it's better to give the recorded file an unique name each time. 因此,最好每次都为录制的文件指定一个唯一的名称。 For example, use the current timestamp. 例如,使用当前时间戳。

Session preset 会话预设

In your code, you set sessionPreset to AVCaptureSessionPresetPhoto : 在您的代码中,将sessionPreset设置为AVCaptureSessionPresetPhoto

captureSession!.sessionPreset = AVCaptureSessionPresetPhoto

But according to my personal experience, it is not suitable for an video output and will result in your error. 但根据我的个人经验,它不适合视频输出,并会导致您的错误。 Change to AVCaptureSessionPresetHigh and try again. 切换到AVCaptureSessionPresetHigh并再试一次。 Also it's recommended to call canSetSessionPreset: and apply the preset only if canSetSessionPreset: returns YES . 此外,建议调用canSetSessionPreset:并仅在canSetSessionPreset:返回YES应用预设。

Sample code 示例代码

Apple offers a nice sample code on the usage of AVFoundation , you may want to check it out. Apple提供了一个关于AVFoundation使用的很好的示例代码 ,您可能想要查看它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM