直播流程图
一、数据采集
通过麦克风摄像头采集音视频数据
复制代码
视频采集
- AVCaptureDevice 前后摄像头作为视频源生成输入
- AVCaptureDeviceInput 视频输入 加入到 ? session
- AVCaptureSession 视频对话
- AVCaptureVideoDataOutput 会话session 导出视频输出
帧率
- 帧率表示图形处理器处理场时每秒钟能够更新的次数,即:每秒视频播放的图片数
- 人眼舒适放松时可视帧数是每秒24帧,集中精神时不超过30帧。眨眼时睁开眼瞬间可以捕捉到的帧数是30帧以上。
- 帧率过小会造成视频卡顿,帧率过大会造成视频过大。
- iOS默认输出的视频帧率为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
苹果默认是 PCM
aac 是为了取代 MP3,压缩了原始文件,但是取决于比特率,合适的比特率人耳分辨不出
二、图像处理
将数据采集的输入流进行实时滤镜, 美颜
复制代码
特效滤镜处理
GPUImage (开源) 只有iOS 小型的可以做 封装和思维基于 OpenGL ES
Metal 苹果 新开发的
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帧
复制代码
四、推流
将采集的音视频信息通过流媒体协议发送到流媒体服务器
复制代码
推流技术
封包
- 视频封装格式: 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。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END