網站首頁 編程語言 正文
一、前言
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;
? ? ? ? });
? ? }
}
原文鏈接:https://www.cnblogs.com/reyzhang/archive/2022/09/01/16646673.html
相關推薦
- 2024-03-16 docker 獲取鏡像幾種方式
- 2022-05-27 利用Python/R語言分別解決金字塔數求和問題_python
- 2023-03-13 ViewModel中StateFlow和SharedFlow單元測試使用詳解_Android
- 2022-08-01 React中的Hooks進階理解教程_React
- 2023-02-04 python協程之yield和yield?from實例詳解_python
- 2022-07-04 C#實現進制轉換_C#教程
- 2022-09-21 Redis實現多級緩存_Redis
- 2022-04-12 用python繪制極坐標雷達圖_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支