基于AVFoundation实现视频录制的两种方式

打印 上一主题 下一主题

主题 893|帖子 893|积分 2679

目录

一、前言

AVCaptureSession 是 AVFoundation 的核心类,用于管理捕获对象 AVCaptureInput 的视频和音频的输入,协调捕获的输出 AVCaptureOutput。
AVCaptureOutput 的输出有两种方法:

  • 一种是直接以 movieFileUrl 方式输出;
  • 一种是以原始数据流 data 的方式输出
流程对比图如下:

下面详细讲解两种录制视频的方案:
二、方案一:AVCaptureSession + AVCaptureMovieFileOutput

1.创建AVCaptureSession
  1. //导入 AVFoundation.framework
  2. #import <AVFoundation/AVFoundation.h>
  3. //声明属性
  4. @property (nonatomic, strong) AVCaptureSession *captureSession;
  5. //懒加载 AVCapturesession
  6. - (AVCaptureSession *)captureSession {
  7.     if (!_captureSession) {
  8.         _captureSession = [[AVCaptureSession alloc] init];
  9.         
  10.         //设置分辨率
  11.         if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
  12.             [_captureSession setSessionPreset:AVCaptureSessionPresetHigh];
  13.         }
  14.     }
  15.     return _captureSession;
  16. }
复制代码
注意:AVCaptureSession 的调用是会阻塞线程的,建议单独开辟子线程处理。
2.设置音频、视频输入
  1. //声明属性
  2. @property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
  3. @property (nonatomic, strong) AVCaptureDeviceInput *audioInput;
  4. //设置视频,音频输入源
  5. - (void)setCaptureDeviceInput {
  6.     //1. 视频输入源
  7.     //获取视频输入设备, 默认后置摄像头
  8.     AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  9.    
  10.     NSError *error = nil;
  11.     self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
  12.    
  13.     if ([self.captureSession canAddInput:self.videoInput]) {
  14.         [self.captureSession addInput:self.videoInput];
  15.     }
  16.    
  17.    
  18.     //2. 音频输入源
  19.     AVCaptureDevice *audioCaptureDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
  20.     self.audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error];
  21.     if ([self.captureSession canAddInput:self.audioInput]) {
  22.         [self.captureSession addInput:self.audioInput];
  23.     }
  24.    
  25. }
复制代码
3.设置文件输出源
  1. //声明属性
  2. @property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput;
  3. @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
  4. //设置文件输出源
  5. - (void)setDeviceFileOutput {
  6.    
  7.     //初始化文件输出对象
  8.     self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
  9.    
  10.     //捕获会话中特定捕获输入对象和捕获输出对象之间的连接
  11.     AVCaptureConnection *captureConnection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
  12.    
  13.     //设置防抖
  14.     if ([captureConnection isVideoStabilizationSupported]) {
  15.         captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
  16.     }
  17.    
  18.     //预览图层和视频方向保持一致
  19.     captureConnection.videoOrientation = [self.previewLayer connection].videoOrientation;
  20.    
  21.     //添加文件输出源
  22.     if ([self.captureSession canAddOutput:self.movieFileOutput]) {
  23.         [self.captureSession addOutput:self.movieFileOutput];
  24.     }
  25.    
  26. }
复制代码
4.添加视频预览层
  1. - (void)setVideoPreviewLayer {
  2.     self.previewLayer.frame = [UIScreen mainScreen].bounds;
  3.    
  4.     [self.superView.layer addSubLayer:self.previewLayer];
  5. }
  6. - (AVCaptureVideoPreviewLayer *)previewLayer {
  7.     if (!_previewLayer) {
  8.         _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
  9.         _previewLayer.masksToBounds = YES;
  10.         _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;//填充模式
  11.     }
  12.     return _previewLayer;
  13. }
复制代码
5. 开始采集
  1. //声明属性
  2. @property (nonatomic, strong) dispatch_queue_t sessionQueue;
  3. //开始采集
  4. - (void)startCapture {
  5.         self.sessionQueue = dispatch_queue_create("com.capturesession.queue", DISPATCH_QUEUE_CONCURRENT);
  6.     if (![self.captureSession isRunning]) {
  7.         __weak __typeof(self) weakSelf = self;
  8.         
  9.         dispatch_async(self.sessionQueue, ^{
  10.             [weakSelf.captureSession startRunning];
  11.         });
  12.         
  13.     }
  14. }
复制代码
6. 开始录制
  1. //开始录制
  2. - (void)startRecord {
  3.    
  4.     [self.movieFileOutput startRecordingToOutputFileURL:[self createVideoPath] recordingDelegate:self];
  5. }
复制代码
当实际的录制开始或停止时,系统会有代理回调。当开始录制之后,这时可能还没有真正写入,真正开始写入会回调下面代理,停止录制也是如此,所以如果你需要对录制视频起始点操作,建议通过系统的回调代理:
  1. //实现协议 <AVCaptureFileOutputRecordingDelegate>中的方法
  2. #pragma mark _ AVCaptureFileOutputRecordingDelegate
  3. //起始点 - 开始录制
  4. - (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray<AVCaptureConnection *> *)connections {
  5.    
  6. }
  7. //结束录制
  8. -(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
  9. {
  10.     NSLog(@"视频录制完成. 文件路径:%@",[outputFileURL absoluteString]);
  11. }
复制代码
7.停止录制
  1. //停止录制
  2. - (void)stopRecord {
  3.     if ([self.movieFileOutput isRecording]) {
  4.         [self.movieFileOutput stopRecording];
  5.     }
  6. }
复制代码
8.停止采集
  1. //停止采集
  2. - (void)stopCapture {
  3.     if ([self.captureSession isRunning]) {
  4.         __weak __typeof(self) weakSelf = self;
  5.         dispatch_async(self.sessionQueue, ^{
  6.             [weakSelf.captureSession stopRunning];
  7.             weakSelf.captureSession = nil;
  8.         });
  9.     }
  10. }
复制代码
三、方案二:AVCaptureSession + AVAssetWriter

方案二及更多内容,请访问: 基于AVFoundation实现视频录制的两种方式

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王海鱼

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表