1小时学会:最简单的iOS直播推流(三)使用系统接口捕获音视频数据

本文介绍了如何在iOS上通过系统接口捕获音视频数据进行直播推流,包括相机数据获取的步骤、初始化输入输出设备、创建AVCaptureSession、预览UI、切换摄像头、设置fps等关键操作。提供了详细代码和注释,适合学习iOS直播技术的开发者。
部署运行你感兴趣的模型镜像

最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!!

通过系统相机录制视频获取音视频数据,是推流的第一步。 源码中提供2种获取音视频数据的方法:一是使用系统自带接口;二是使用GPUImage。

本篇首先介绍第一种。

网络上关于获取视频数据的代码有不少,但是为了方便代码阅读,这里简要介绍一下。

[注意]请仔细阅读代码注释

1、相关代码入口

整套推流代码的入口:AWAVCaptureManager,它是根据参数创建上述2种获取数据方法的一个工厂类。

可以通过设置 captureType 来决定使用哪种数据获取方式。

AWAVCaptureManager部分代码如下:

typedef enum : NSUInteger {
    AWAVCaptureTypeNone,
    AWAVCaptureTypeSystem,
    AWAVCaptureTypeGPUImage,
} AWAVCaptureType;
​
@interface AWAVCaptureManager : NSObject
//视频捕获类型
@property (nonatomic, unsafe_unretained) AWAVCaptureType captureType;
@property (nonatomic, weak) AWAVCapture *avCapture;
​
//省略其他代码
......
@end

设置了captureType之后,直接可以通过avCapture获取到正确的捕获视频数据的对象了。

AWAVCapture 是一个虚基类(c++中的说法,不会直接产生对象,只用来继承的类,java中叫做抽象类)。 它的两个子类分别是 AWSystemAVCapture 和 AWGPUImageAVCapture。

这里使用了多态。

如果 captureType设置的是 AWAVCaptureTypeSystem,avCapture获取到的真实对象就是 AWSystemAVCapture类型; 如果 captureType设置的是 AWAVCaptureTypeGPUImage,avCapture获取到的真实对象就是 AWGPUImageAVCapture类型。

AWSystemAVCapture类的功能只有一个:调用系统相机,获取音视频数据。

2、相机数据获取的方法

分为3步骤:

  1. 初始化输入输出设备。

  2. 创建AVCaptureSession,用来管理视频与数据的捕获。

  3. 创建预览UI。 还包括一些其他功能:

  4. 切换摄像头

  5. 更改fps

在代码中对应的是 AWSystemAVCapture中的 onInit方法。只要初始化就会调用。

【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

【注意】请仔细阅读下文代码中的注释 初始化输入设备

-(void) createCaptureDevice{
    // 初始化前后摄像头
    // 执行这几句代码后,系统会弹框提示:应用想要访问您的相机。请点击同意
    // 另外iOS10 需要在info.plist中添加字段NSCameraUsageDescription。否则会闪退,具体请自行baidu。
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    self.frontCamera = [AVCaptureDeviceInput deviceInputWithDevice:videoDevices.firstObject error:nil];
    self.backCamera =[AVCaptureDeviceInput deviceInputWithDevice:videoDevices.lastObject error:nil];
    
    // 初始化麦克风
    // 执行这几句代码后,系统会弹框提示:应用想要访问您的麦克风。请点击同意
    // 另外iOS10 需要在info.plist中添加字段NSMicrophoneUsageDescription。否则会闪退,具体请自行baidu。
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    self.audioInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
    
    //省略其他代码
    ...
}

3、初始化输出设备

-(void) createOutput{   
    //创建数据获取线程
    dispatch_queue_t captureQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //视频数据输出
    self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    //设置代理,需要当前类实现protocol:AVCaptureVideoDataOutputSampleBufferDelegate
    [self.videoDataOutput setSampleBufferDelegate:self queue:captureQueue];
    //抛弃过期帧,保证实时性
    [self.videoDataOutput setAlwaysDiscardsLateVideoFrames:YES];
    //设置输出格式为 yuv420
    [self.videoDataOutput setVideoSettings:@{
                                             (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
                                             }];
​
    //音频数据输出
    self.audioDataOutput = [[AVCaptureAudioDataOutput alloc] init];
    //设置代理,需要当前类实现protocol:AVCaptureAudioDataOutputSampleBufferDelegate
    [self.audioDataOutput setSampleBufferDelegate:self queue:captureQueue];
​
    // AVCaptureVideoDataOutputSampleBufferDelegate 和 AVCaptureAudioDataOutputSampleBufferDelegate 回调方法名相同都是:
    // captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    // 最终视频和音频数据都可以在此方法中获取。
}

4、创建 captureSession

// AVCaptureSession 创建逻辑很简单,它像是一个中介者,从音视频输入设备获取数据,处理后,传递给输出设备(数据代理/预览layer)。
-(void) createCaptureSession{
    //初始化
    self.captureSession = [AVCaptureSession new];
    
    //修改配置
    [self.captureSession beginConfiguration];
    
    //加入视频输入设备
    if ([self.captureSession canAddInput:self.videoInputDevice]) {
        [self.captureSession addInput:self.videoInputDevice];
    }
    
    //加入音频输入设备
    if ([self.captureSession canAddInput:self.audioInputDevice]) {
        [self.captureSession addInput:self.audioInputDevice];
    }
    
    //加入视频输出
    if([self.captureSession canAddOutput:self.videoDataOutput]){
        [self.captureSession addOutput:self.videoDataOutput];
        [self setVideoOutConfig];
    }
    
    //加入音频输出
    if([self.captureSession canAddOutput:self.audioDataOutput]){
        [self.captureSession addOutput:self.audioDataOutput];
    }
    
    //设置预览分辨率
    //这个分辨率有一个值得注意的点:
    //iphone4录制视频时 前置摄像头只能支持 480*640 后置摄像头不支持 540*960 但是支持 720*1280
    //诸如此类的限制,所以需要写一些对分辨率进行管理的代码。
    //目前的处理是,对于不支持的分辨率会抛出一个异常
    //但是这样做是不够、不完整的,最好的方案是,根据设备,提供不同的分辨率。
    //如果必须要用一个不支持的分辨率,那么需要根据需求对数据和预览进行裁剪,缩放。
    if (![self.captureSession canSetSessionPreset:self.captureSessionPreset]) {
        @throw [NSException exceptionWithName:@"Not supported captureSessionPreset" reason:[NSString stringWithFormat:@"captureSessionPreset is [%@]", self.captureSessionPreset] userInfo:nil];
    }
​
    self.captureSession.sessionPreset = self.captureSessionPreset;
    
    //提交配置变更
    [self.captureSession commitConfiguration];
    
    //开始运行,此时,CaptureSession将从输入设备获取数据,处理后,传递给输出设备。
    [self.captureSession startRunning];
}

5、创建预览UI

// 其实只有一句代码:CALayer layer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
// 它其实是 AVCaptureSession的一个输出方式而已。
// CaptureSession会将从input设备得到的数据,处理后,显示到此layer上。
// 我们可以将此layer变换后加入到任意UIView中。
-(void) createPreviewLayer{
    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
    self.previewLayer.frame = self.preview.bounds;
    [self.preview.layer addSublayer:self.previewLayer];
}

6、切换摄像头

-(void)setVideoInputDevice:(AVCaptureDeviceInput *)videoInputDevice{
    if ([videoInputDevice isEqual:_videoInputDevice]) {
        return;
    }
    //captureSession 修改配置
    [self.captureSession beginConfiguration];
    //移除当前输入设备
    if (_videoInputDevice) {
        [self.captureSession removeInput:_videoInputDevice];
    }
    //增加新的输入设备
    if (videoInputDevice) {
        [self.captureSession addInput:videoInputDevice];
    }
    
    //提交配置,至此前后摄像头切换完毕
    [self.captureSession commitConfiguration];
    
    _videoInputDevice = videoInputDevice;
}

7、设置fps

-(void) updateFps:(NSInteger) fps{
    //获取当前capture设备
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    
    //遍历所有设备(前后摄像头)
    for (AVCaptureDevice *vDevice in videoDevices) {
        //获取当前支持的最大fps
        float maxRate = [(AVFrameRateRange *)[vDevice.activeFormat.videoSupportedFrameRateRanges objectAtIndex:0] maxFrameRate];
        //如果想要设置的fps小于或等于做大fps,就进行修改
        if (maxRate >= fps) {
            //实际修改fps的代码
            if ([vDevice lockForConfiguration:NULL]) {
                vDevice.activeVideoMinFrameDuration = CMTimeMake(10, (int)(fps * 10));
                vDevice.activeVideoMaxFrameDuration = vDevice.activeVideoMinFrameDuration;
                [vDevice unlockForConfiguration];
            }
        }
    }
}

8、获取音视频数据

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    if (self.isCapturing) {
        if ([self.videoDataOutput isEqual:captureOutput]) {
            //捕获到视频数据,通过sendVideoSampleBuffer发送出去,后续文章会解释接下来的详细流程。
            [self sendVideoSampleBuffer:sampleBuffer];
        }else if([self.audioDataOutput isEqual:captureOutput]){
            //捕获到音频数据,通过sendVideoSampleBuffer发送出去
            [self sendAudioSampleBuffer:sampleBuffer];
        }
    }
}

至此,我们达到了所有目标:能够录制视频,预览,获取音视频数据,切换前后摄像头,修改捕获视频的fps。

原文链接:1小时学会:最简单的iOS直播推流(三)使用系统接口捕获音视频数据 - 掘金

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值