日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

使用AVFoundation實現視頻錄制詳解_IOS

作者:reyzhang ? 更新時間: 2022-10-30 編程語言

一、前言

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

欄目分類
最近更新