一对一直播软件源码开发,直播相关技术详解

一对一直播软件源码中直播流程图
在这里插入图片描述
一、数据采集
通过一对一直播软件源码移动设备的端麦克风摄像头采集音视频数据。
视频采集

  • AVCaptureDevice 前后摄像头作为视频源生成输入
  • AVCaptureDeviceInput 视频输入 加入到 👇 session
  • AVCaptureSession 视频对话
  • AVCaptureVideoDataOutput 会话session 导出视频输出

帧率

  • 帧率表示图形处理器处理场时每秒钟能够更新的次数,即:每秒视频播放的图片数。
  • 人眼舒适放松时可视帧数是每秒24帧,集中精神时不超过30帧。眨眼时睁开眼瞬间可以捕捉到的帧数是30帧以上。
  • 帧率过小会造成一对一直播软件源码中直播视频卡顿,帧率过大会造成视频过大。
  • 一对一直播软件源码默认输出的视频帧率为30帧/秒,普通用途的话设置成24~30就够用了。

音频采集

  • AVAudioSession
  • AudioComponentDescription
  • AudioComponentFindNext
        AVAudioSession *session = [AVAudioSession sharedInstance];
        
        // 监听声音路线改变
        [[NSNotificationCenter defaultCenter] addObserver: self
                                                 selector: @selector(handleRouteChange:)
                                                     name: AVAudioSessionRouteChangeNotification
                                                   object: session];
        // 监听声音被打断
        [[NSNotificationCenter defaultCenter] addObserver: self
                                                 selector: @selector(handleInterruption:)
                                                     name: AVAudioSessionInterruptionNotification
                                                   object: session];
        /// 创建AudioComponent
        AudioComponentDescription acd;
        acd.componentType = kAudioUnitType_Output;
        //acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
        acd.componentSubType = kAudioUnitSubType_RemoteIO;
        acd.componentManufacturer = kAudioUnitManufacturer_Apple; // 厂商 直接写kAudioUnitManufacturer_Apple
        acd.componentFlags = 0; // 没有明确值时必须设为0
        acd.componentFlagsMask = 0; // 没有明确值时必须设为0
        self.component = AudioComponentFindNext(NULL, &acd);
        
        OSStatus status = noErr;
        status = AudioComponentInstanceNew(self.component, &_componetInstance);
        
        if (noErr != status) {
            [self handleAudioComponentCreationFailure];
        }
        
        /// 连接麦克风
        UInt32 flagOne = 1;
        AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flagOne, sizeof(flagOne));
        
        AudioStreamBasicDescription desc = {0};
        desc.mSampleRate = _configuration.audioSampleRate; // 采样率
        desc.mFormatID = kAudioFormatLinearPCM;
        desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
        desc.mChannelsPerFrame = (UInt32)_configuration.numberOfChannels;
        desc.mFramesPerPacket = 1;
        desc.mBitsPerChannel = 16; // 表示每个声道的音频数据要多少位,一个字节是8位,所以用8 * 每个采样的字节数
        desc.mBytesPerFrame = desc.mBitsPerChannel / 8 * desc.mChannelsPerFrame;
        desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket; // 根据mFormatFlags指定的Float类型非交错存储,就设置为bytesPerSample表示每个采样的字节数。但如果是Interleaved交错存储的,就应该设置为bytesPerSample * mChannelsPerFrame 因为左右声道数据是交错存在一起的。
        

        // 连接扬声器
        AudioUnitSetProperty(self.componetInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desc, sizeof(desc));
        
        // 设置声音回调
        AURenderCallbackStruct cb;
        cb.inputProcRefCon = (__bridge void *)(self);
        cb.inputProc = handleInputBuffer;
        AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb));
        
        // 初始化AudioComponentInstance
        status = AudioUnitInitialize(self.componetInstance);
        
        if (noErr != status) {
            [self handleAudioComponentCreationFailure];
        }
        
        [session setPreferredSampleRate:_configuration.audioSampleRate error:nil];
        /// AVAudioSessionCategoryPlayAndRecord 支持音频播放和录音、打断其他不支持混音APP、不会被静音键或锁屏键静音
        /// AVAudioSessionCategoryOptionDefaultToSpeaker 系统会自动选择最佳的内置麦克风组合支持视频聊天。
        /// AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers 支持和其他APP音频混合
        [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:nil];
        [session setActive:YES withOptions:kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation error:nil];
        
        [session setActive:YES error:nil];

音频采样率

  • 音频采样率是指录音设备在一秒钟内对声音信号的采样次数,采样频率越高声音的还原就越真实越自然。
  • 在当今的主流采集卡上,采样频率一般共分为11025Hz、22050Hz、24000Hz、44100Hz、48000Hz五个等级,11025Hz能达到AM调幅广播的声音品质,而22050Hz和24000HZ能达到FM调频广播的声音品质,44100Hz则是理论上的CD音质界限,48000Hz则更加精确一些。
  • 一对一直播软件源码中一般音频质量采用44100Hz, 高等音频质量采用48000Hz

配置采样参数
音频配置:码率(128)和采样率(44100HZ)
视频配置:视频分辨率(720P )、码率(2000KB/S)和帧率(30FPS)

音频录制实时转为 aac

aac 是为了取代 MP3,压缩了一对一直播软件源码中原始文件,但是取决于比特率,合适的比特率人耳分辨不出

二、图像处理

将一对一直播软件源码中采集到的音视频数据进行实时滤镜, 美颜

特效滤镜处理
GPUImage (开源) 只有iOS 小型的可以做 封装和思维基于 OpenGL ES
OpenGL PC
OpenGL ES 线路 手机

三、音视频编码(压缩)

在这里插入图片描述
一、音频编码

AudioToolBox FFmpeg AAC
软解码:使用 fdk_aac 将 PCM 转为 AAC

常用音频压缩编码格式

有损压缩和无损压缩
人耳掩盖效应:去除冗余信息

目前在一对一直播软件源码开发中使用有损压缩比较多

  • 有损压缩:解压后的数据完全可以复原
  • 有损压缩:解压后的音视频数据不能完全复原,会丢失一部分信息,压缩比越大,丢失的信息越多,信号还原的失真就越大

WAV

  • 未进行压缩
  • 在 PCM 裸数据前面加了44个字节,包含了采样率,声道数,数据格式等信息
  • 音质非常好

MP3

  • 不错的压缩比,接近于 WAV
  • 高比特率下,128kbs表现很好,应用很广

AAC

  • 目前很热门的有损压缩格式
  • 多适用于小比特率下,并且多用于一对一直播软件源码中的音频编码

OGG

  • 潜力可用于一对一直播软件源码中的语音聊天场景
  • 但是软硬件支持问题

二、视频编码

VideoToolBox FFmpeg H264

  • 软编码: FFmpeg X264 用到CPU
  • 硬编码 VideoToolBox AudioToolBox 商业项目 通用 硬编码 GPU (运算大于CPU) 硬件加速器
    视频编码 VideoToolBox FFmpeg H264
    音频编码 AudioToolBox FFmpeg AAC

编码到底做了什么

YUV 而不是用 rgba

1s 内 60张照片

10张为一组 进行压缩

​ 取第一帧为I帧,后面称之为 P帧,只保留和前一帧的不同点

​ B 帧 是保留和后一帧的差异。

为了追求高压缩(如小视频),可使用 I P B

但是一对一直播软件源码是为了追求高实时性,因此使用I P,而不使用B帧

使用 VideoToolBox 框架的流程

1、创建编码会话 session

    VTCompressionSessionCreate

2、设置编码相关参数

  • 设置是否实时编码
  • 是否使用B帧
  • GOP 关键帧的间隔
  • 设置帧率
  • 设置码率

3、开始编码
4、循环获取采集数据
5、获取编码后的数据
通过 AVFoundation 获取捕获结果回调
在这里插入图片描述

  • 原始数据封装为 CVPixelBuffers,
    CVPixelBuffers 为主内存存储的所有像素点数据的对象

  • encode 为 CMSampleBuffers

在这里插入图片描述
6、将数据写入 H264 文件
获取到 SPS/PPS, 第一帧写入 SPS/PPS
VideoToolBox 在没一个关键帧前面都会输出 SPS/PPS信息,如果本帧为关键帧,则可以取出对应的 PPS / SPS 信息。

四、推流
将采集的音视频信息通过一对一直播软件源码流媒体协议发送到流媒体服务器

推流技术
封包

  • 视频封装格式: FLV / TS
  • 音视频封装格式: MP3 / AAC

上传

  • 流媒体协议: RTMP / HLS / RTSP / FLV

五、流媒体服务器处理

  • 数据分发 CDN
  • 截屏
  • 录制
  • 实时转码

六、播放器
负责一对一直播软件源码中流媒体的拉流、解码和播放

拉流:

  • 流媒体协议: RTMP / HLS / RTSP / FLV

音视频解码

  • 硬解码 : videoToolbox audioToolBox
  • 软解码 : 视频 FFmpeg x264算法视频解码, 使用 fdk_aac 音频解码

七、流媒体协议的区别

RTMP

相对于 HLS 来说,采用 RTMP 协议时,从采集推流端到流媒体服务器再到播放端是一条数据流,因此在一对一直播软件源码的服务器不会有落地文件。这样 RTMP 相对来说就有这些优点:

延时较小,通常为 1-3s。
基于 TCP 长连接,不需要多次建连。
因此业界大部分直播业务都会选择用 RTMP 作为流媒体协议。通常会将数据流封装成 FLV 通过 HTTP 提供出去。但是这样也有一些问题需要解决:

iOS 平台没有提供原生支持 RTMP 或 HTTP-FLV 的播放器,这就需要开发支持相关协议的播放器。

HLS

HLS 的基本原理就是当一对一直播软件源码采集推流端将视频流推送到流媒体服务器时,服务器将收到的流信息每缓存一段时间就封包成一个新的 ts 文件,同时服务器会建立一个 m3u8 的索引文件来维护最新几个 ts 片段的索引。当一对一直播软件源码播放端获取直播时,它是从 m3u8 索引文件获取最新的 ts 视频文件片段来播放,从而保证用户在任何时候连接进来时都会看到较新的内容,实现近似直播的体验。相对于常见的流媒体直播协议,例如 RTMP 协议、RTSP 协议等,HLS 最大的不同在于直播客户端获取到的并不是一个完整的数据流,而是连续的、短时长的媒体文件,客户端不断的下载并播放这些小文件。这种方式的理论最小延时为一个 ts 文件的时长,一般情况为 2-3 个 ts 文件的时长。HLS 的分段策略,基本上推荐是 10 秒一个分片,这就看出了 HLS 的缺点:

通常 HLS一对一直播软件源码延时会达到 20-30s,而高延时对于需要实时互动体验的直播来说是不可接受的。
HLS 基于短连接 HTTP,HTTP 是基于 TCP 的,这就意味着 HLS 需要不断地与服务器建立连接,TCP 每次建立连接时的三次握手、慢启动过程、断开连接时的四次挥手都会产生消耗。

不过 HLS 也有它的优点:

数据通过 HTTP 协议传输,所以采用 HLS 时不用考虑防火墙或者代理的问题。
使用短时长的分片文件来播放,一对一直播软件源码客户端可以平滑的切换码率,以适应不同带宽条件下的播放。

HLS 是苹果推出的流媒体协议,在 iOS 平台上可以获得天然的支持,采用系统提供的 AVPlayer 就能直接播放,不用自己开发播放器。
image

HTTP FLV

先通过服务器将FLV下载到本地缓存,然后再通过NetConnection的本地连接来播放这个FLV,这种方法是播放本地的视频,并不是播放服务器的视频。因此在本地缓存里可以找到这个FLV。
其优点就是服务器下载完这个FLV,服务器就没有消耗了,节省服务器消耗。
其缺点就是FLV会缓存在客户端,对FLV的保密性不好。
是一种将直播流模拟成FLV文件,通过HTTP协议进行下载的模式来实现流媒体传输的协议,端口号80
一般建议使用HTTP FLV,实时性和RTMP相等。
优点:HTTP相比于RTMP省去了一些协议交互时间,首屏时间更短。HTTP可拓展的功能更多。

协议差别

  • HLS:HTTP Live Streaming;基于短连接 HTTP;集合一段时间的数据生成 ts 切片文件,更新 m3u8 文件;延时
    25s+。
  • RTMP:Real Time Messaging Protocal;基于长连接TCP;每个时刻收到的数据立即转发;延时 1~3s。
  • HTTP-FLV: RTMP over HTTP;基于长连接 HTTP;在一对一直播软件源码每个时刻收到的数据立即转发,使用 HTTP 协议;延时 1~3s。
    以上就是“一对一直播软件源码开发,直播相关技术详解”的全部内容,希望对大家有帮助。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值