一、前言 AVCaptureSession 是 AVFoundation 的核心類,用於管理捕獲對象 AVCaptureInput 的視頻和音頻的輸入,協調捕獲的輸出 AVCaptureOutput。 AVCaptureOutput 的輸出有兩種方法: 一種是直接以 movieFileUrl 方式輸 ...
目錄
一、前言
AVCaptureSession
是 AVFoundation
的核心類
,用於管理捕獲
對象 AVCaptureInput 的視頻和音頻的輸入
,協調捕獲
的輸出 AVCaptureOutput
。
AVCaptureOutput
的輸出有兩種方法:
- 一種是直接以 movieFileUrl 方式輸出;
- 一種是以原始數據流 data 的方式輸出
流程對比圖如下:
下麵詳細講解兩種錄製視頻的方案:
二、方案一:AVCaptureSession + AVCaptureMovieFileOutput
1.創建AVCaptureSession
//導入 AVFoundation.framework
#import <AVFoundation/AVFoundation.h>
//聲明屬性
@property (nonatomic, strong) AVCaptureSession *captureSession;
//懶載入 AVCapturesession
- (AVCaptureSession *)captureSession {
if (!_captureSession) {
_captureSession = [[AVCaptureSession alloc] init];
//設置解析度
if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
[_captureSession setSessionPreset:AVCaptureSessionPresetHigh];
}
}
return _captureSession;
}
註意:AVCaptureSession 的調用是會阻塞線程的,建議單獨開闢子線程處理。
2.設置音頻、視頻輸入
//聲明屬性
@property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
@property (nonatomic, strong) AVCaptureDeviceInput *audioInput;
//設置視頻,音頻輸入源
- (void)setCaptureDeviceInput {
//1. 視頻輸入源
//獲取視頻輸入設備, 預設後置攝像頭
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.設置文件輸出源
//聲明屬性
@property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
//設置文件輸出源
- (void)setDeviceFileOutput {
//初始化文件輸出對象
self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
//捕獲會話中特定捕獲輸入對象和捕獲輸出對象之間的連接
AVCaptureConnection *captureConnection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
//設置防抖
if ([captureConnection isVideoStabilizationSupported]) {
captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}
//預覽圖層和視頻方向保持一致
captureConnection.videoOrientation = [self.previewLayer connection].videoOrientation;
//添加文件輸出源
if ([self.captureSession canAddOutput:self.movieFileOutput]) {
[self.captureSession addOutput:self.movieFileOutput];
}
}
4.添加視頻預覽層
- (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];
}
當實際的錄製開始或停止時,系統會有代理回調。當開始錄製之後,這時可能還沒有真正寫入,真正開始寫入會回調下麵代理,停止錄製也是如此,所以如果你需要對錄製視頻起始點操作,建議通過系統的回調代理:
//實現協議 <AVCaptureFileOutputRecordingDelegate>中的方法
#pragma mark _ AVCaptureFileOutputRecordingDelegate
//起始點 - 開始錄製
- (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray<AVCaptureConnection *> *)connections {
}
//結束錄製
-(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;
});
}
}
三、方案二:AVCaptureSession + AVAssetWriter
方案二及更多內容,請訪問: 基於AVFoundation實現視頻錄製的兩種方式
本文來自博客園,作者:reyzhang,轉載請註明原文鏈接:https://www.cnblogs.com/reyzhang/p/16646673.html