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地址
-
GitHub: SCRecorder ↩
-
Apple官方文档:AVCaptureSession ↩
-
Apple官方文档:MovieFileOutpu ↩