前言####
這些年App的呈現(xiàn)方式不斷在進(jìn)化,從最初的文字到圖片,再到gif動(dòng)態(tài)圖片,現(xiàn)在是視頻展示,所以我覺得我們的技術(shù)也要不斷的更新,那么今天就從錄制小視頻開始吧。
錄制視頻的方式###
簡單的來講主要有兩種
1、UIImagePickerController,比較簡單,功能單一
2、AVFoundation的AVCaptureSession視頻捕獲類(本文主講)
由于考慮到視頻錄制以后可能會(huì)用到,所以我把錄制視頻封裝成工具類。視頻源碼地址:自定義視頻錄制之AVCaptureSession
錄制效果:

錄制視頻的步驟####
1、相機(jī)、麥克風(fēng)、保存視頻的相冊是否授權(quán)
//相機(jī)是否可以用
- (BOOL)isAvailableWithCamera
{
return [self isAvailableWithDeviveMediaType:AVMediaTypeVideo];
}
//麥克風(fēng)是否可以用
- (BOOL)isAvailableWithMic
{
return [self isAvailableWithDeviveMediaType:AVMediaTypeAudio];
}
- (BOOL)isAvailableWithDeviveMediaType:(NSString *)mediaType
{
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(status == ALAuthorizationStatusDenied||status == ALAuthorizationStatusRestricted)
return NO;
else
return YES;
}
2、初始化輸入輸出、攝像頭、數(shù)據(jù)流管理、視頻預(yù)覽層
@property (strong, nonatomic) AVCaptureSession *captureSession; //負(fù)責(zé)輸入和輸出設(shè)備之間的連接會(huì)話,數(shù)據(jù)流的管理控制
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer;//捕獲到的視頻呈現(xiàn)的layer
@property (strong, nonatomic) AVCaptureDeviceInput *backCameraInput;//后置攝像頭輸入
@property (strong, nonatomic) AVCaptureDeviceInput *frontCameraInput;//前置攝像頭輸入
@property (strong, nonatomic) AVCaptureDeviceInput *audioMicInput;//麥克風(fēng)輸入
@property (strong, nonatomic) AVCaptureConnection *videoConnection;//視頻錄制連接
@property (strong,nonatomic) AVCaptureMovieFileOutput *captureMovieFileOutput;//視頻輸出流
由于初始化的東西比較多,那么我就簡單的列舉幾個(gè),詳情可以查看demo自定義視頻錄制之AVCaptureSession
//捕獲視頻的會(huì)話
- (AVCaptureSession *)captureSession
{
if(_captureSession == nil)
{
_captureSession = [[AVCaptureSession alloc] init];
//設(shè)置分辨率
if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
_captureSession.sessionPreset=AVCaptureSessionPreset1280x720;
}
//添加后置攝像頭的輸入
if ([_captureSession canAddInput:self.backCameraInput]) {
[_captureSession addInput:self.backCameraInput];
}
//添加后置麥克風(fēng)的輸入
if ([_captureSession canAddInput:self.audioMicInput]) {
[_captureSession addInput:self.audioMicInput];
}
//將設(shè)備輸出添加到會(huì)話中
if ([_captureSession canAddOutput:self.captureMovieFileOutput]) {
[_captureSession addOutput:self.captureMovieFileOutput];
}
//設(shè)置視頻錄制的方向
self.videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
}
return _captureSession;
}
初始化錄制視頻的預(yù)覽層
//捕獲到的視頻呈現(xiàn)的layer
- (AVCaptureVideoPreviewLayer *)previewLayer {
if (_previewLayer == nil) {
//通過AVCaptureSession初始化
AVCaptureVideoPreviewLayer *preview = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
//設(shè)置比例為鋪滿全屏
preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
_previewLayer = preview;
}
return _previewLayer;
}
4、初始化完成之后,就可以啟動(dòng)錄制功能(注意:是啟動(dòng)錄制功能,并不是開始錄制),啟動(dòng)錄制功能的之前一定要把視頻預(yù)覽層放到你想要的錄制區(qū)域,這樣開啟錄制功能就能預(yù)覽錄制效果
//啟動(dòng)錄制功能
- (void)startRecordFunction
{
[self.captureSession startRunning];
}
//關(guān)閉錄制功能
- (void)stopRecordFunction
{
if(self.captureSession)
[self.captureSession stopRunning];
}
5、在錄制視頻開始之前要設(shè)置錄制視頻的輸入視頻流的存放地址,你可以存放到您想存放的地方,本文存放到temp文件中
#pragma mark - 視頻地址
- (NSString *)getVideoPathCache
{
NSString *videoCache = [NSTemporaryDirectory() stringByAppendingPathComponent:@"videos"] ;
BOOL isDir = NO;
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL existed = [fileManager fileExistsAtPath:videoCache isDirectory:&isDir];
if ( !(isDir == YES && existed == YES) ) {
[fileManager createDirectoryAtPath:videoCache withIntermediateDirectories:YES attributes:nil error:nil];
};
return videoCache;
}
- (NSString *)getVideoNameWithType:(NSString *)fileType
{
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HHmmss"];
NSDate * NowDate = [NSDate dateWithTimeIntervalSince1970:now];
;
NSString * timeStr = [formatter stringFromDate:NowDate];
NSString *fileName = [NSString stringWithFormat:@"video_%@.%@",timeStr,fileType];
return fileName;
}
6、開始錄制
//開始錄制
- (void)startCapture
{
if(self.captureMovieFileOutput.isRecording)
return;
NSString *defultPath = [self getVideoPathCache];
NSString *outputFielPath=[ defultPath stringByAppendingPathComponent:[self getVideoNameWithType:@"mp4"]];
NSLog(@"save path is :%@",outputFielPath);
NSURL *fileUrl=[NSURL fileURLWithPath:outputFielPath];
//設(shè)置錄制視頻流輸出的路徑
[self.captureMovieFileOutput startRecordingToOutputFileURL:fileUrl recordingDelegate:self];
}
//停止錄制
- (void) stopCapture
{
if ([self.captureMovieFileOutput isRecording]) {
[self.captureMovieFileOutput stopRecording];//停止錄制
}
}
7、視頻錄制過程中有AVCaptureFileOutputRecordingDelegate記錄監(jiān)聽錄制過程,我們可以實(shí)現(xiàn)代理方法查看,并且在錄制完成,我們希望把視頻保存到我們的相冊中
#pragma mark - 視頻輸出代理
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections{
NSLog(@"開始錄制...");
}
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
NSLog(@"視頻錄制完成.");
//視頻錄入完成之后在后臺(tái)將視頻存儲(chǔ)到相
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:outputFileURL];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (error) {
NSLog(@"保存視頻到相簿過程中發(fā)生錯(cuò)誤,錯(cuò)誤信息:%@",error.localizedDescription);
}
NSLog(@"成功保存視頻到相簿.");
}];
}
8、在錄制過程中我們有時(shí)候還要增加一些功能,比如切換攝像頭、開啟閃光燈、錄制進(jìn)度顯示等
#注意:改變會(huì)話的配置前一定要先開啟配置,配置完成后提交配置改變
//開啟閃光燈
- (void)openFlashLight
{
//改變會(huì)話的配置前一定要先開啟配置,配置完成后提交配置改變
[self.captureSession beginConfiguration];
AVCaptureDevice *backCamera = [self backCamera];
if (backCamera.torchMode == AVCaptureTorchModeOff) {
[backCamera lockForConfiguration:nil];
backCamera.torchMode = AVCaptureTorchModeOn;
backCamera.flashMode = AVCaptureFlashModeOn;
[backCamera unlockForConfiguration];
}
//提交會(huì)話配置
[self.captureSession commitConfiguration];
[self startRecordFunction];
}
詳情代碼請直接下載demo查看:
自定義視頻錄制之AVCaptureSession
最后贈(zèng)言###
如果覺得文章對您有幫助,不要忘記star哦!??,star 是對程序猿最大的鼓勵(lì)!