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

4
我将在一个视图控制器中捕获视频、音频和照片,理想情况下只需要一个捕获会话。
目前我遇到的问题是录制视频时出现了一些问题。虽然预览正常地显示了输出内容,但启用了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)

当我运行上面的代码时,出现了以下错误:
'NSInvalidArgumentException', reason: '*** -[AVCaptureMovieFileOutput startRecordingToOutputFileURL:recordingDelegate:] - no active/enabled connections.'

我的配置:

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()
}
1个回答

3

我在你的代码中发现了两个问题。

文件重复

根据苹果文档 startRecordingToOutputFileURL:recordingDelegate: 的说明:

开始录制给定 URL。 该方法设置接收器当前正在写入输出媒体的文件 URL。如果在捕获开始时已经存在给定 URL 上的文件,则新文件的录制将失败。

iOS 中不支持帧准确的文件切换。您必须在再次调用此方法之前调用 stopRecording,以避免任何错误。 通过调用 stopRecording,使用此方法更改文件或因错误而停止录制时,需要包括到文件中的剩余数据将在后台写入。因此,您必须指定一个代理,在所有数据已经使用 captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error: 方法写入文件时通知它。

在你的代码中,如果在开始新的录制时 test.mp4 已经存在,则录制将失败。因此最好每次都为记录的文件命名唯一名称,例如使用当前时间戳。

会话预设

在你的代码中,你将sessionPreset 设置为AVCaptureSessionPresetPhoto

captureSession!.sessionPreset = AVCaptureSessionPresetPhoto

根据我的个人经验,该设置不适合用于视频输出,并会导致错误。请更改为AVCaptureSessionPresetHigh并重试。另外建议调用canSetSessionPreset:方法,仅在返回YES时应用预设。

示例代码

Apple提供了一个很好的示例代码,演示了如何使用AVFoundation,您可以查看一下。


问题出在预设上。我有一段代码,用于在使用录制内容之前删除 mp4 文件,但是我忘记把它包括进去了。不过对于实际产品,我们将使用时间戳。谢谢。 - Max Hudson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接