本文根据又拍云内部技术分享会的演讲整理而成,主要内容:图像和音频数据采集、处理;音视频编码、封包发送、云端(服务端)及播放器。


直播无疑是2016年大热话题,去年4月份,又拍云基于内容分发网络推出一站式直播解决方案,包括实时转码、实时录制、分发加速、水印、截图、秒级禁播、延时直播等功能。本文希望系统介绍直播各个环节,帮助视频直播创业者们更全面、深入地了解直播技术,更好地进行技术选型。


△ 直播流程图


一、采集音视频数据

采集摄像头和麦克风的数据。


图像采集

图像采集和编码面临的主要挑战在于:设备兼容性差、卡顿敏感以及各种对图像的处理操作如美颜和水印等。


图像采集设置前置摄像头、后置摄像头,并配置采集的参数、图像数据的长宽、fps、输出的方向、横屏竖屏等,然后从回调中取到数据。处理如下:


_videoCamera.outputImageOrientation = videoCameraOrientation;

// 设置拍摄帧频 _videoCamera.frameRate = _fps

音频采集

音频采集和编码主要面临的挑战在于:噪声消除(Denoise)、回声消除(AEC)算法等。


前期不需要音频数据处理需求的时候, 只需配置音频采集的采样频率、采样精度和声道,处理如下:


_audioFormat0.mSampleRate = 44100.00;

_audioFormat0.mFormatID = kAudioFormatLinearPCM;

_audioFormat0.mBitsPerChannel = 16;


二、数据处理

音频处理中具体包含混音、降噪和声音特效等处理。视频处理中包含美颜、水印、以及各种自定义滤镜等处理。


音频处理是直播难点之一,尤其主播离手机有一段距离,直播环境会有噪音,所以直播的音频处理是整体降噪的过程。增益降噪等处理可直接从 speex 项目中抽出来的声音处理代码,然后调用、处理。如有类似在直播的时候播放背景音乐的混音需求,就需要使用 Audio Unit 来实现音频数据的混音,而还需要将混音的背景音乐转成 PCM 数据,拷贝一份送入混音,原来的数据送入播放器。


滤镜、美颜功能是直播标配,如果需要美白、水印、裁剪等处理效果,就必须处理拿到的buffer, 这个时候还要考虑到拿到的数据是YUV 还是 RGB。iOS 上是不能对 YUV 格式直接进行美颜处理,只能是 RGB 格式。可选择使用 GPUImage 库,调用 GPUImage 来进行采集和美白、水印、裁剪的处理,然后取出来进行编码上传,并显示在预览画面上。


三、音视频编码

视频编码的意义

  • 原始视频数据存储空间大,一个 1080P 的 7 s 视频需要 817 MB

  • 原始视频数据传输占用带宽大,10 Mbps 的带宽传输上述 7 s 视频需要 11 分钟


而经过 H.264 编码压缩之后,视频大小只有 708 k ,10 Mbps 的带宽仅仅需要 500 ms ,可以满足实时传输的需求,所以从视频采集传感器采集来的原始视频势必要经过视频编码。


编码首先要开启编码器,软编码就是利用CPU资源来压缩音视频数据,硬编码与之相反。


软编码: 现在广泛采用FFmpeg库结合编码库来实现,FFmpeg + x264 来编码视频数据YUV/RGB输出H264数据, FFmpeg+fdk_aac 来编码音频数据PCM输出AAC数据。


硬编码: iOS 8之后开放了硬解码和硬编码AP,所以基本上都是选择VideoToolBox 和 AudioToolBox 进行图像和音频的硬编码。


四、封包发送

将音频,视频打包成packet。


又拍云播放器采用 FFMPEG 进行数据的接收,推流端默认使用 FFMPEG 进行数据的封包发送。


相对来说,封包主要注意的一个点是时间戳。因为用的AVPacket封包,每个包都会有一个DST(Decode Time Stamp)、PST (Presentation Time Stamp)参数,从字面上可以理解,就是解码时间和显示时间,在没有B帧存在的情况下DTS的顺序和PTS的顺序应该是一样的。


这块还涉及到重连和丢帧,用户的网络情况波动断开了,会进行重连。重连失败之后才会发送失败回调。丢帧是一个弱网情况的策略,根据音视频数据的缓冲区大小来判断是否丢帧,丢帧会优先丢非关键帧,保留关键帧,而一旦需要丢关键帧的时,关键帧后的非关键帧也会一起丢掉直到下一个关键帧.来保证画面不会花屏。


五、云端(服务端)

对比两种推送协议在直播领域的现状和优缺点。


  • RTMP

  • HLS


1、RTMP

RTMP (Real Time Messaging Protocol)实时消息传输协议,该协议基于 TCP,是一个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等多种变种。RTMP 是一种设计用来进行实时数据通信的网络协议,主要用来在 Flash/AIR 平台和支持 RTMP 协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括 Adobe Media Server/Ultrant Media Server/red5 等。


RTMP 是目前主流的流媒体传输协议,广泛用于直播领域,可以说市面上绝大多数的直播产品都采用了这个协议。


优点


  • CDN 支持良好,主流的 CDN 厂商都支持

  • 协议简单,在各平台上实现容易


缺点


  • 基于 TCP ,传输成本高,在弱网环境丢包率高的情况下问题显著

  • 不支持浏览器推送

  • Adobe 私有协议,Adobe 已经不再更新


2、HLS


HLS(HTTP Live Streaming)协议,是苹果公司实现的基于HTTP的流媒体传输协议,可实现流媒体的直播和点播。


HLS主要应用在iOS系统,为iOS设备(如iPhone、iPad)提供音视频直播和点播方案。HLS点播,基本上就是常见的分段HTTP点播,不同在于,它的分段非常小。


优点


  • 不用考虑防火墙或者代理的问题

  • 分段文件时长很短,客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。


缺点


  • 延迟一般会高于普通的流媒体直播协议


对直播延迟比较敏感的服务请慎用HLS。


根据所选流媒体协议,发送相应指令连接服务器,连接服务器成功后,就可以发送packet数据了。 又拍云采用用的是 RTMP,服务端会进行转码、录制、转 HLS 的操作。


六、播放器


播放器主要负责拉流、解码、播放。

拉流端


拉流,就是从流媒体服务器获取音频、视频数据。


1、解析协议


播放器端根据URL解析所用的流媒体协议(RTMP,HLS)。


2、解封装


解封装,就是demux的过程,从容器格式(FLV,TS)中,分离出音视频数据。


3、解码


解码,就是把获取到的数据解压缩,恢复成原始数据。解码就是将H264变成YUV,AAC变成PCM。解码可以使用软解码,硬解码。


软解码就是利用CPU资源去解压缩数据,采用的方式是FFmpeg解码。


硬解码,对于iOS平台来说,可以使用VideoToolbox.Framework(该框架只能在iOS 8.0及以上系统使用) 硬解码视频数据。Android平台上,可以使用MediaCodec来硬解码视频数据。


4、渲染数据

采用OpenGL渲染YUV数据,呈现视频画面。将PCM送入设备的硬件资源播放,产生声音。

iOS播放流式音频,使用Audio Queue 的方式,即利用AudioToolbox.Framework 框架。