使用AVFoundation實(shí)現(xiàn)視頻錄制詳解
一、前言
AVCaptureSession 是 AVFoundation 的核心類,用于管理捕獲對(duì)象 AVCaptureInput 的視頻和音頻的輸入,協(xié)調(diào)捕獲的輸出 AVCaptureOutput。
AVCaptureOutput 的輸出有兩種方法:
- 一種是直接以 movieFileUrl 方式輸出;
- 一種是以原始數(shù)據(jù)流 data 的方式輸出
流程對(duì)比圖如下:
下面詳細(xì)講解錄制視頻的方案:
二、AVCaptureSession + AVCaptureMovieFileOutput
1.創(chuàng)建AVCaptureSession
//導(dǎo)入 AVFoundation.framework? #import <AVFoundation/AVFoundation.h> //聲明屬性 @property (nonatomic, strong) AVCaptureSession *captureSession; //懶加載 AVCapturesession - (AVCaptureSession *)captureSession { ? ? if (!_captureSession) { ? ? ? ? _captureSession = [[AVCaptureSession alloc] init]; ? ? ? ?? ? ? ? ? //設(shè)置分辨率 ? ? ? ? if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) { ? ? ? ? ? ? [_captureSession setSessionPreset:AVCaptureSessionPresetHigh]; ? ? ? ? } ? ? } ? ? return _captureSession; }
注意:AVCaptureSession 的調(diào)用是會(huì)阻塞線程的,建議單獨(dú)開辟子線程處理。2.設(shè)置音頻、視頻輸入
//聲明屬性 @property (nonatomic, strong) AVCaptureDeviceInput *videoInput; @property (nonatomic, strong) AVCaptureDeviceInput *audioInput; //設(shè)置視頻,音頻輸入源 - (void)setCaptureDeviceInput { ? ? //1. 視頻輸入源 ? ? //獲取視頻輸入設(shè)備, 默認(rèn)后置攝像頭 ? ? AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; ? ?? ? ? NSError *error = nil; ? ? self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error]; ? ?? ? ? if ([self.captureSession canAddInput:self.videoInput]) { ? ? ? ? [self.captureSession addInput:self.videoInput]; ? ? } ? ?? ? ?? ? ? //2. 音頻輸入源 ? ? AVCaptureDevice *audioCaptureDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject]; ? ? self.audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error]; ? ? if ([self.captureSession canAddInput:self.audioInput]) { ? ? ? ? [self.captureSession addInput:self.audioInput]; ? ? } ? ?? }
3.設(shè)置文件輸出源
//聲明屬性 @property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput; @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer; //設(shè)置文件輸出源 - (void)setDeviceFileOutput { ? ?? ? ? //初始化文件輸出對(duì)象 ? ? self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; ? ?? ? ? //捕獲會(huì)話中特定捕獲輸入對(duì)象和捕獲輸出對(duì)象之間的連接 ? ? AVCaptureConnection *captureConnection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; ? ?? ? ? //設(shè)置防抖 ? ? if ([captureConnection isVideoStabilizationSupported]) { ? ? ? ? captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; ? ? } ? ?? ? ? //預(yù)覽圖層和視頻方向保持一致 ? ? captureConnection.videoOrientation = [self.previewLayer connection].videoOrientation; ? ?? ? ? //添加文件輸出源 ? ? if ([self.captureSession canAddOutput:self.movieFileOutput]) { ? ? ? ? [self.captureSession addOutput:self.movieFileOutput]; ? ? } ? ?? }
4.添加視頻預(yù)覽層
- (void)setVideoPreviewLayer { ? ? self.previewLayer.frame = [UIScreen mainScreen].bounds; ? ?? ? ? [self.superView.layer addSubLayer:self.previewLayer]; } - (AVCaptureVideoPreviewLayer *)previewLayer { ? ? if (!_previewLayer) { ? ? ? ? _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; ? ? ? ? _previewLayer.masksToBounds = YES; ? ? ? ? _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;//填充模式 ? ? } ? ? return _previewLayer; }
5. 開始采集
//聲明屬性 @property (nonatomic, strong) dispatch_queue_t sessionQueue; //開始采集 - (void)startCapture { ?? ?self.sessionQueue = dispatch_queue_create("com.capturesession.queue", DISPATCH_QUEUE_CONCURRENT); ? ? if (![self.captureSession isRunning]) { ? ? ? ? __weak __typeof(self) weakSelf = self; ? ? ? ?? ? ? ? ? dispatch_async(self.sessionQueue, ^{ ? ? ? ? ? ? [weakSelf.captureSession startRunning]; ? ? ? ? }); ? ? ? ?? ? ? } }
6. 開始錄制
//開始錄制 - (void)startRecord { ? ?? ? ? [self.movieFileOutput startRecordingToOutputFileURL:[self createVideoPath] recordingDelegate:self]; }
當(dāng)實(shí)際的錄制開始或停止時(shí),系統(tǒng)會(huì)有代理回調(diào)。當(dāng)開始錄制之后,這時(shí)可能還沒有真正寫入,真正開始寫入會(huì)回調(diào)下面代理,停止錄制也是如此,所以如果你需要對(duì)錄制視頻起始點(diǎn)操作,建議通過(guò)系統(tǒng)的回調(diào)代理:
//實(shí)現(xiàn)協(xié)議 <AVCaptureFileOutputRecordingDelegate>中的方法 #pragma mark _ AVCaptureFileOutputRecordingDelegate //起始點(diǎn) - 開始錄制 - (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray<AVCaptureConnection *> *)connections { ? ?? } //結(jié)束錄制 -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { ? ? NSLog(@"視頻錄制完成. 文件路徑:%@",[outputFileURL absoluteString]); }
7.停止錄制
//停止錄制 - (void)stopRecord { ? ? if ([self.movieFileOutput isRecording]) { ? ? ? ? [self.movieFileOutput stopRecording]; ? ? } }
8.停止采集
//停止采集 - (void)stopCapture { ? ? if ([self.captureSession isRunning]) { ? ? ? ? __weak __typeof(self) weakSelf = self; ? ? ? ? dispatch_async(self.sessionQueue, ^{ ? ? ? ? ? ? [weakSelf.captureSession stopRunning]; ? ? ? ? ? ? weakSelf.captureSession = nil; ? ? ? ? }); ? ? } }
到此這篇關(guān)于使用AVFoundation實(shí)現(xiàn)視頻錄制詳解的文章就介紹到這了,更多相關(guān)AVFoundation實(shí)現(xiàn)視頻錄制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ajax 三種實(shí)現(xiàn)方法實(shí)例代碼
這篇文章主要介紹了ajax 三種實(shí)現(xiàn)方法實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-09-09iOS實(shí)現(xiàn)去除html標(biāo)簽的方法匯總
相信大家在做網(wǎng)站的時(shí)候,經(jīng)常會(huì)遇到去除html標(biāo)簽的問(wèn)題,下面這篇文章主要給大家總結(jié)介紹了關(guān)于iOS如何實(shí)現(xiàn)去除html標(biāo)簽的一些方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10ios 不支持 iframe 的完美解決方法(兼容iOS&安卓)
下面小編就為大家?guī)?lái)一篇ios 不支持 iframe 的完美解決方法(兼容iOS&安卓)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Xcode 10升級(jí)導(dǎo)致項(xiàng)目報(bào)錯(cuò)的常見問(wèn)題解決
這篇文章主要給大家介紹了關(guān)于Xcode 10升級(jí)導(dǎo)致項(xiàng)目報(bào)錯(cuò)的常見問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12IOS點(diǎn)擊按鈕隱藏狀態(tài)欄詳解及實(shí)例代碼
這篇文章主要介紹了IOS點(diǎn)擊按鈕隱藏狀態(tài)欄詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02