老爷爷 發表於 2022-9-5 08:44:44

使用AVFoundation实现视频录制详解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、前言</li><li>二、AVCaptureSession + AVCaptureMovieFileOutput</li></ul></div><p class="maodian"></p><h2>一、前言</h2>
<p>AVCaptureSession 是 AVFoundation 的核心类,用于管理捕获对象 AVCaptureInput 的视频和音频的输入,协调捕获的输出 AVCaptureOutput。</p>
<p>AVCaptureOutput 的输出有两种方法:</p>
<ul><li>一种是直接以 movieFileUrl 方式输出;</li><li>一种是以原始数据流 data 的方式输出</li></ul>
<p>流程对比图如下:</p>
<p><img alt="" src="https://img.jbzj.com/file_images/article/202209/20229584229147.png?20228584427" /></p>
<p>下面详细讲解录制视频的方案:</p>
<p class="maodian"></p><h2>二、AVCaptureSession + AVCaptureMovieFileOutput</h2>
<p>1.创建AVCaptureSession</p>
<div class="jb51code"><pre class="brush:java;">//导入 AVFoundation.framework 
#import &lt;AVFoundation/AVFoundation.h&gt;

//声明属性
@property (nonatomic, strong) AVCaptureSession *captureSession;

//懒加载 AVCapturesession
- (AVCaptureSession *)captureSession {
    if (!_captureSession) {
        _captureSession = [ init];
        
        //设置分辨率
        if () {
            ;
        }
    }
    return _captureSession;
}</pre></div>
<p>注意:AVCaptureSession 的调用是会阻塞线程的,建议单独开辟子线程处理。2.设置音频、视频输入</p>
<div class="jb51code"><pre class="brush:java;">//声明属性
@property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
@property (nonatomic, strong) AVCaptureDeviceInput *audioInput;


//设置视频,音频输入源
- (void)setCaptureDeviceInput {
    //1. 视频输入源
    //获取视频输入设备, 默认后置摄像头
    AVCaptureDevice *videoCaptureDevice = ;
    
    NSError *error = nil;
    self.videoInput = ;
    
    if () {
        ;
    }
    
    
    //2. 音频输入源
    AVCaptureDevice *audioCaptureDevice = [ firstObject];
    self.audioInput = ;
    if () {
        ;
    }
    
}</pre></div>
<p>3.设置文件输出源</p>
<div class="jb51code"><pre class="brush:java;">//声明属性
@property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;


//设置文件输出源
- (void)setDeviceFileOutput {
    
    //初始化文件输出对象
    self.movieFileOutput = [ init];
    
    //捕获会话中特定捕获输入对象和捕获输出对象之间的连接
    AVCaptureConnection *captureConnection = ;
    
    //设置防抖
    if () {
        captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
    
    //预览图层和视频方向保持一致
    captureConnection.videoOrientation = .videoOrientation;
    
    //添加文件输出源
    if () {
        ;
    }
    
}</pre></div>
<p>4.添加视频预览层</p>
<div class="jb51code"><pre class="brush:java;">- (void)setVideoPreviewLayer {
    self.previewLayer.frame = .bounds;
    
    ;
}


- (AVCaptureVideoPreviewLayer *)previewLayer {
    if (!_previewLayer) {
        _previewLayer = ;
        _previewLayer.masksToBounds = YES;
        _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;//填充模式
    }
    return _previewLayer;
}</pre></div>
<p>5. 开始采集</p>
<div class="jb51code"><pre class="brush:java;">//声明属性
@property (nonatomic, strong) dispatch_queue_t sessionQueue;

//开始采集
- (void)startCapture {
    self.sessionQueue = dispatch_queue_create("com.capturesession.queue", DISPATCH_QUEUE_CONCURRENT);

    if (!) {
        __weak __typeof(self) weakSelf = self;
        
        dispatch_async(self.sessionQueue, ^{
            ;
        });
        
    }
}</pre></div>
<p>6. 开始录制</p>
<div class="jb51code"><pre class="brush:java;">//开始录制
- (void)startRecord {
    
    recordingDelegate:self];
}</pre></div>
<p>当实际的录制开始或停止时,系统会有代理回调。当开始录制之后,这时可能还没有真正写入,真正开始写入会回调下面代理,停止录制也是如此,所以如果你需要对录制视频起始点操作,建议通过系统的回调代理:</p>
<div class="jb51code"><pre class="brush:java;">//实现协议 &lt;AVCaptureFileOutputRecordingDelegate&gt;中的方法


#pragma mark _ AVCaptureFileOutputRecordingDelegate

//起始点 - 开始录制
- (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray&lt;AVCaptureConnection *&gt; *)connections {
    
}

//结束录制
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
    NSLog(@"视频录制完成. 文件路径:%@",);
}</pre></div>
<p>7.停止录制</p>
<div class="jb51code"><pre class="brush:java;">//停止录制
- (void)stopRecord {
    if () {
        ;
    }
}</pre></div>
<p>8.停止采集</p>
<div class="jb51code"><pre class="brush:java;">//停止采集
- (void)stopCapture {
    if () {
        __weak __typeof(self) weakSelf = self;
        dispatch_async(self.sessionQueue, ^{
            ;
            weakSelf.captureSession = nil;
        });
    }
}
</pre></div>
<p>到此这篇关于使用AVFoundation实现视频录制详解的文章就介绍到这了,更多相关AVFoundation实现视频录制内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>iOS基于AVFoundation&nbsp;制作用于剪辑视频项目</li><li>iOS使用视听媒体框架AVFoundation实现照片拍摄</li><li>iOS使用AVFoundation展示视频</li><li>iOS框架AVFoundation实现相机拍照、录制视频</li><li>ios使用AVFoundation读取二维码的方法</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 使用AVFoundation实现视频录制详解