SCRecorder录制视频导出时间过长的优化

SCRecorder录制视频导出时间过长的优化

IOS视频录制 AVFoundation SCRecorder[1]

遇到问题

在项目中需要录制视频,为图方便使用SCRecorder第三方库进行开发,谁知遇到的坑还是挺多,在保存视频的时候遇到导出视频时间过长的问题,录制完成后还需要导出视频,估计在导出时做了视频转码和压缩等工作,10分钟视频要等个1分钟实在让人抓狂,代码如下:

// Merge all the segments into one file using an AVAssetExportSession
[recordSession mergeSegmentsUsingPreset:AVAssetExportPresetHighestQuality completionHandler:^(NSURL *url, NSError *error) {
    if (error == nil) {
        // Easily save to camera roll
        [url saveToCameraRollWithCompletion:^(NSString *path, NSError *saveError) {

        }];
    } else {
        NSLog(@"Bad things happened: %@", error);
    }
}];

解决方案1——使用系统框架AVFoundation

放弃使用SCRecorder,使用IOS系统的AVFoundation,AVCaptureSession[2]和AVCaptureMovieFileOutput[3]可以很方便的录制出MP4文件。这种方式在百度上很容易找到,这里不再详述。

优势:
高度订制,SCRecorder也是基于AVFoundation实现的。

劣势:
配置AVCaptureSession过于麻烦,对于切换摄像头和闪光灯开关等设置不太方便。还有就是已经入了SCRecorder的坑,改用AVFoundation来实现有点过于麻烦

解决方案2——启用SCRecorder的fastRecordMethodEnabled属性

在查看SCRecorder的文档时发现一个fastRecordMethodEnabled属性,文档内容如下:

Whether the fast recording method should be enabled.
Enabling this will disallow pretty much every features provided
by SCVideoConfiguration and SCAudioConfiguration. It will internally
uses a AVCaptureMovieFileOutput that provides no settings. If you have
some performance issue, you can try enabling this.
Default is NO.

(注:本人英文半瓶子水在这里就不翻译了,自行度娘)

配置代码:

SCRecorder *recorder = [SCRecorder recorder];
[recorder startRunning]
recorder.session = [SCRecordSession recordSession];

recorder.fastRecordMethodEnabled = YES;

[recorder record];

然后结束录制后在SCRecorderDelegate的- (void)recorder:(SCRecorder *__nonnull)recorder didCompleteSession:(SCRecordSession *__nonnull)session;中就可以拿到录制好的视频了,session中有一个只读的outputUrl属性就是了

有一个缺点就是路径还是TM不能自己指定,蛋疼。
后来研究了下他的源代码,可以看到SCRecorder.m里面的定义如下:

    AVCaptureVideoPreviewLayer *_previewLayer;
    AVCaptureSession *_captureSession;
    UIView *_previewView;
    AVCaptureVideoDataOutput *_videoOutput;
    AVCaptureMovieFileOutput *_movieOutput;
    AVCaptureAudioDataOutput *_audioOutput;
    AVCaptureStillImageOutput *_photoOutput;

可以看到里面有一个_movieOutput的属性,只要拿到他我们就可以为所欲为啦:(OC动态运行机制闪亮登场)

let movieFileOutput = recorder?.value(forKeyPath: "_movieOutput")

后续可以使用movieFileOutput来指定存储路径啦!!
注:提取_movieOutput的方案没有亲身实践过,不知道是否可行!

解决方案3——替换SCRecorder的AVCaptureMovieFileOutput

创建一个AVCaptureMovieFileOutput然后add到Recorder的AVCatureSession上经行录制,不需要再调用Recorder的record方法,但是需要调用Recorder的startRunning方法。不然catureSession的值会是nil。
直接贴代码

let movieOutput = AVCaptureMovieFileOutput()
recorder?.captureSession?.addOutput(movieOutput)

movieOutput.startRecording(toOutputFileURL: self.outputUrl, recordingDelegate: self)

so easy!

第一次写技术文档,有什么疏漏或者不正确的地方还请指出,互相学习。


2016年12月16日更新

目前本人已经弃用SCRecoder,改用AVFoundation框架来实现录制视频功能,直接放出代码:
github地址


  1. GitHub: SCRecorder ↩

  2. Apple官方文档:AVCaptureSession ↩

  3. Apple官方文档:MovieFileOutpu ↩

你可能感兴趣的:(SCRecorder录制视频导出时间过长的优化)