视频云,是以Paas服务模式,向开发者提供音视频编解码SDK和开放API,助力移动APP接入音视频功能,用户不需要后台开发和运维人员,就可以开发自己的视频网站或者移动APP应用。视频云主要使用的是流媒体技术,下面就来给大家介绍一下视频云相关的技术。
流媒体是指将一连串的媒体数据压缩后,经过网络分段发送数据,在网络上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如果不使用此技术,就必须在使用前下载整个媒体文件。流媒体的本质上是原始画面,经过视频采集设备,然后通过编码器编码压缩,生成点播文件或者直播流,经过网络的传输,在各种终端进行解压解码,然后播放器进行画面渲染,最终展示在用户眼前。流媒体可以分为点播和直播,点播技术经过多年的发展,基本上沦为HTTP文件下载,唯一与流媒体相关的就剩下不同码率、格式、不同分辨率之间的转换了。点播是把事先录制到的视频文件,通过网络分发给用户终端。流媒体直播是有实时性的要求,直播的数据都是存在内存中,过时的数据会被丢掉,如果需要持久化数据,就必须对直播流进行录制,转化为视频文件保存起来,可以转化为点播的内容。点播的内容源是静态的,直播的数据源是动态的。
视频是一种有结构的数据,包含图像,音频,元数据。
编码格式,组织数据采用各种各样的格式,比较常用的有视频格式H.264,H.265,音频格式AAC,HE-AAC。
容器封装,MP4,MOV,FLV,RM,RMVB,AVI。
任何一个视频Video文件,从结构上讲,都是下面组成方式:
n由图像和音频构成最基本的内容元素
n经过视频编码压缩格式处理(通常H.264)
n音频经过音频编码压缩格式处理(例如AAC)
n注明相应的元信息(Metadata)
n最后经过容器(Container)封装打包(例如MP4),构成一个完成的视频文件
市场上流媒体文件存储格式非常多,MPEG系列,DivX/XviD,AVI,WMV,Real,RMVB,Flash,MOV,ASF,DV-AVI,H.261, H.263/H.263+,H.264/AVC,VP6/7,M-JPEG,HLS等,由于网络带宽资源有限,流媒体数据需要进行高度的压缩,编解码要方便简单,不能耗费大量计算资源,还要方便切割,容易在互联网上传输,容错率高,丢掉部分非关键数据,不影响正常播放,因此真正适合互联网的媒体格式不多。互联网上使用比较广泛的视频格式主要有两种:MPEG的.mp4和Flash的.flv,以及移动端的HLS(hls即可用于点播,也可以用户直播)。
https://blog.qiniu.com/archives/6816
媒体数据分为视频和音频,视频和音频采用不同的编码格式。
视频编码格式(Video Coding Format),又称视频编码规范,视频压缩格式。常见的有H.264、H.265。由于原始的视音频数据非常大,不方便存储和传输,通过压缩编码的方式将原始视音频进行压缩。它定义了视频数据在存储和传输过程中的规范。
音频编码格式(Audio Coding Format),又称音频编码规范,音频压缩格式。常见的有ACC、MP3等。同样也是为了将原始的音频数据进行压缩,它定义了音频数据在存储和传输过程中的规范。
封装文件中包括视频数据、音频数据以及其他数据。将原始的视频和音频数据通过压缩编码之后要封装成一个文件,比如avi、rmvb、mp4等,就是我们平常所说的“视频格式”,“视频格式”是一种不严谨的表述。将视频和音频数据以及其他数据,比如字幕信息等,打包成一个文件的规范称为封装格式。打包的文件像容器一样,将视频和音频数据放在里面,所以封装格式也成为容器格式(Container Format)。
下面对集中比较常见的封装格式进行详细介绍。
MP4是一套用于音频、视频信息的压缩编码标准,由国际标准化组织(ISO)和国际电工委员会(IEC)下属的“动态图像专家组”(Moving Picture Experts Group,即MPEG)制定,第一版在1998年10月通过,第二版在1999年12月通过。MPEG-4格式的主要用途在于网上流、光盘、语音发送(视频电话),以及电视广播。MP4是非常经典的文件格式,在移动端好和PC浏览器上的支持度都很好,在IOS和大部分Android设备上,都可以使用系统浏览器进行播放,在PC上可以用FLASH控件进行播放。但是MP4的视频文件格式比较复杂,处理成本高,由于索引复杂度高,导致时长稍大(比如半小时)的文件在线播放时加载速度会很慢。MP4对小文件支持非常好,在移动端上播放质量非常好,主要适用于点播。
FLV 是FLASH VIDEO的简称,FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等缺点。
FLV作为一种新兴的网络视频格式,能得到众多的网站支持并非偶然。除了FLV视频格式本身占有率低、视频质量良好、体积小等特点适合网络发展外,丰富、多样的资源也是FLV视频格式统一在线播放视频格式的一个重要因素。介绍完当前流行的流媒体文件格式,下面来介绍一下常见的直播协议。FLV由于对flash支持非常好,因此非常适合直播。
从整个文件上开看,FLV是由FLV header和FLV File Body组成.
FLV文件格式
1、FLV header
Signature: FLV 文件的前3个字节为固定的‘F’‘L’‘V’,用来标识这个文件是flv格式的.在做格式探测的时候,
如果发现前3个字节为“FLV”,就认为它是flv文件.
Version: 第4个字节表示flv版本号.
Flags: 第5个字节中的第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)
DataOffset : 最后4个字节表示FLV header 长度.
2、FLV Body
FLV header之后,就是 FLV File Body.
FLV File Body是由一连串的back-pointers + tags构成.back-pointers就是4个字节数据,表示前一个tag的size.
FLV Tag格式
FLV文件中的数据都是由一个个TAG组成,TAG里面的数据可能是video、audio、scripts.
下表是TAG的结构:
TagType: TAG中第1个字节中的前5位表示这个TAG中包含数据的类型,8 = audio,9 = video,18 = script data.
DataSize:StreamID之后的数据长度.
Timestamp和TimestampExtended组成了这个TAG包数据的PTS信息,记得刚开始做FVL demux的时候,并没有考虑TimestampExtended的值,直接就把Timestamp默认为是PTS,后来发生的现 象就是画面有跳帧的现象,后来才仔细看了一下文档发现真正数据的PTS是PTS= Timestamp | TimestampExtended<<24.
StreamID之后的数据就是每种格式的情况不一样了,接下格式进行详细的介绍.
Audio Tags
如果TAG包中的TagType==8时,就表示这个TAG是audio。
StreamID之后的数据就表示是AudioTagHeader,AudioTagHeader结构如下:
AudioTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着音频类型、采样率等的基本信息.表里列的十分清楚.
AudioTagHeader之后跟着的就是AUDIODATA数据了,也就是audio payload 但是这里有个特例,如果音频格式(SoundFormat)是10 = AAC,AudioTagHeader中会多出1个字节的数据AACPacketType,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。
AAC sequence header也就是包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细音频的信息,AudioSpecificConfig的定义在ISO14496-3中1.6.2.1 AudioSpecificConfig,这里就不详细贴了。而且在ffmpeg中有对AudioSpecificConfig解析的函数,ff_mpeg4audio_get_config()(我的ffmpeg版本中是avpriv_mpeg4audio_get_config()),可以对比的看一下,理解更深刻。
AAC raw 这种包含的就是音频ES流了,也就是audio payload.
在FLV的文件中,一般情况下 AAC sequence header 这种包只出现1次,而且是第一个audio tag,为什么要提到这种tag,因为当时在做FLVdemux的时候,如果是AAC的音频,需要在每帧AAC ES流前边添加7个字节ADST头,ADST在音频的格式中会详细解读,这是解码器通用的格式,就是AAC的纯ES流要打包成ADST格式的AAC文件,解码器才能正常播放.就是在打包ADST的时候,需要samplingFrequencyIndex这个信息,samplingFrequencyIndex最准确的信息是在AudioSpecificConfig中,所以就对AudioSpecificConfig进行解析并得到了samplingFrequencyIndex。
到这步你就完全可以把FLV 文件中的音频信息及数据提取出来,送给音频解码器正常播放了。
Video Tags
如果TAG包中的TagType==9时,就表示这个TAG是video.
StreamID之后的数据就表示是VideoTagHeader,VideoTagHeader结构如下:
VideoTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着视频帧类型及视频CodecID最基本信息.表里列的十分清楚.
VideoTagHeader之后跟着的就是VIDEODATA数据了,也就是video payload.当然就像音频AAC一样,这里也有特例就是如果视频的格式是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息.
AVCPacketType 和 CompositionTime。AVCPacketType 表示接下来 VIDEODATA (AVCVIDEOPACKET)的内容:
IF AVCPacketType == 0 AVCDecoderConfigurationRecord(AVC sequence header) IF AVCPacketType == 1 One or more NALUs (Full frames are required)
AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag.
AVCDecoderConfigurationRecord的定义在ISO 14496-15, 5.2.4.1中,这里不在详细贴,
SCRIPTDATA
如果TAG包中的TagType==18时,就表示这个TAG是SCRIPT.
SCRIPTDATA 结构十分复杂,定义了很多格式类型,每个类型对应一种结构.
类型在FLV的官方文档中都有详细介绍
onMetaData
onMetaData 是SCRIPTDATA中对我们来说十分重要的信息,结构如下表:
这里面的duration、filesize、视频的width、height等这些信息对我们来说很有用.
NALU
h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件。
每个NALU单元开头第一个byte的低5bits表示着该单元的类型,即:
NAL nal_unit_type:
#define NALU_TYPE_SLICE 1 #define NALU_TYPE_DPA 2 #define NALU_TYPE_DPB 3 #define NALU_TYPE_DPC 4 #define NALU_TYPE_IDR 5 #define NALU_TYPE_SEI 6 #define NALU_TYPE_SPS 7 #define NALU_TYPE_PPS 8 #define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10 #define NALU_TYPE_EOSTREAM 11 #define NALU_TYPE_FILL 12
每个NALU第一个byte & 0x1f 就可以得出它的类型,比如上图第一个NALU:67 & 0x1f = 7,则此单元是SPS,第三个:68 & 0x1f = 8,则此单元是PPS
现在开始封装h264数据吧,前一章提到了flv关于AVC的格式,除开元数据,其他数据是:一个byte的video信息+一个byte的AVCPacket type+3个bytes的无用数据(composition time,当AVC时无用,全是0)+ 4个bytes的NALU单元长度 + N个bytes的NALU数据,所以包头数据长度信息是刚才提到的信息的总和长度。要强调下,当音视频配置信息tag的时候,是没有4个bytes的NALU单元长度的。
AVC的配置信息时,先上一个图,
17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 后面一个byte 0x00,AVCPacket type,代表AVC sequence header。后3个bytes无意义,之后就是decoder configuration record的内容了。 图中绿色后面 00 00 00 28就是前面tag的总长度。
当NALU第一个byte xx & 0x1f == 5的时候,说明该单元是一个I frame,关键帧
17 -- 和上面的一样。 01 -- AVC NALU。蓝色框内的4个bytes记录后面NALU数据的长度。65 & 0x1f == 5.
如果NALU第一个byte xx & 0x1f != 5的时候,就不是一个I frame
27 -- 高4bits:2,inter frame ,P frame。 低4bits:7,AVC NALU。其他都一样。图中绿色后面 00 00 00 19就是前面tag的总长度。
SPS和PPS
SPS:序列参数集Sequence Parameter Set
PPS:图像参数集Picture Parameter Set
H.264的SPS和PPS串,包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高,deblock滤波器等。
SPS和PPS都是NAL层的概念,是为了适应更多的网络环境,SPS信息在整个视频编码序列中是不变的,PPS信息在一幅编码图像之内是不变的。
首先SPS和PPS包含在FLV的AVCDecoderConfigurationRecord结构中,而AVCDecoderConfigurationRecord就是经FFMPEG分析后,AVCodecContext里面的extradata,先列一下这个结构吧。
FFMPEG获取相应数据的代码类似于下面。代码中的m_formatCtx为AVFormatContext实例。
打印结果例如下面。
根据AVCDecoderConfigurationRecord结构:
lconfigurationVersion为第1字节,即0x01;
lAVCProfileIndication为第2字节,即SPS[1];
lprofile_compatibility为第3字节,即SPS[2];
lprofile_compatibility为第4字节,即SPS[3];
llengthSizeMinusOne为第5字节的后2个bit,是NALUnitLength的长度-1,一般为3;
lnumOfSequenceParameterSets为第6字节的后5个bit,是SPS的个数,即1;
lsequenceParameterSetLength为第7、8字节,是SPS的长度,即0x0019;
lsequenceParameterSetNALUnits为接下来的25个字节,是SPS的内容,即:
lnumOfPictureParameterSets为接下来的1字节,是PPS的个数,即0x01;
lpictureParameterSetLength为接下来的2字节,是PPS的长度,即0x0004;
lpictureParameterSetNALUnit为最后的4字节,是PPS的内容,即:
HLS是基于HTTP协议实现,为移动设备开发的基于HTTP的流媒体解决方案,传输内容包括两部分,一是m3u8描述文件,二是ts媒体文件。
M3u8文件,用文本方式对媒体文件进行描述,由一系列标签组成。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-ALLOW-CACHE:NO #EXT-X-MEDIA-SEQUENCE:1494939524 #EXT-X-TARGETDURATION:5 #EXTINF:3.967, 2000_8bb38e793a2c11e791eae435c87f075e-1494939524.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0 #EXTINF:3.967, 2000_8bb38e793a2c11e791eae435c87f075e-1494939525.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0 #EXTINF:4.33, 2000_8bb38e793a2c11e791eae435c87f075e-1494939526.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0 #EXTINF:4.133, 2000_8bb38e793a2c11e791eae435c87f075e-1494939527.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0 #EXTINF:2.867, 2000_8bb38e793a2c11e791eae435c87f075e-1494939528.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0
#EXTM3U:每个M3U8文件第一行必须是这个tag。
#EXT-X-TARGETDURATION:指定最大的媒体段时间长度(秒),#EXTINF中指定的时间长度必须小于或等于这个最大值。该值只能出现一次。
#EXTINF:描述单个媒体文件的长度。后面为媒体文件,如2000_8bb38e793a2c11e791eae435c87f075e-1494939524.ts?cdncode=/18907E7BE0798990/&sdtfrom=v0
TS文件为传输流文件,视频编码主要格式h264/mpeg4,音频为aac/mp3.
ts文件分为三层:ts层transport stream,pes层packet element stream,es层elementary stream。Es层就是音视频数据,pes层实在音视频数据上加了时间戳等对数据帧的说明信息,ts层就是在pes层加入数据流的识别和传输必须的信息。
音频帧一般可以独立解码,可以直接播放。
而视频分为视频关键帧和非关键帧,关键帧可以独立解码渲染,播放器拿到后可以直接看到画面,一般10K以上甚至几十K;其他非关键帧依赖于前面的一些视频帧,播放器会根据前面的帧和当前帧来解码产生画面,非关键帧一般大小是几K甚至不到1K。对于播放器来说,服务器一般会从视频关键帧开始发送,才不会产生花屏。
下面的图里我们可以看到,当前的服务器缓存了V1-V3五帧数据,当V4这个关键帧出现了,服务器把之前的丢掉,开始缓存V4开始的音视频数据,以这个策略保证过来的播放端都是当前最新的数据。一般直播服务器都是用这个策略来进行服务器缓存的。
流式传输,就是将音频、视频以及其他多媒体文件经过某种算法编码压缩成一个个很小的压缩包,流媒体服务器通过特定网络协议进行连续、实时的传送,用户端接收到压缩包后由播放软件实时解压缩实现播放的过程。从传输方式上大致可以分发传统文件下载、http渐进式下载、http流式传输、实时流媒体传输四大类。
分发传统文件下载,直接下载整个文件,早些时候看视频,都是把整个视频文件下载本地,然后通过本地播放器进行播放。
http渐进式是指通过支持Seek,终端播放器可以从没有下载完成部分中任意选取一个时间点开始播放,如此来满足不用等待整个文件下载完快速播放的需求,一般MP4和flv格式的文件支持较好,打开一个视频拖拽到中部,短暂缓冲即可播放,点击暂停后文件仍将被持续下载就是典型的渐进式下载,目前大型点播网站如YouTube、优酷等均采用这种方式。
http流式传输或者http流化技术,不同厂商有不同做法,但主要思路都是在服务器端将媒体文件分割成一个个很小的独立切片文件,文件分片时需要同时产生用于跟踪切片的索引文件(描述文件),播放器在通过http协议向服务器请求一个小的媒体切片实现点播或直播的播放,我们平常听到的HLS(Apple)、HDS(Adobe)、MSS(Microsoft),DASH(MPEG通用标准)均属于HTTP流的范畴。
不同流式传输对比
流媒体数据从采集到最终播放的路径,就是一套完整的流媒体系统所需的组成部分。
从系统层面上来看,编码层负责对音视频文件编码压缩(h.264/h.265/VP9/AAC等);封装层负责对数据包进行容器封装(flv/ts等);协议层负责网络打包(RTMP/HTTP等);传输层负责网络传输(socket/st等);播放层负责对图像进行解码显示(FLASH/VLS/VIDEO JS等)。
从我们所熟知的产品服务层面,一套完整的流媒体系统所需的组件一般包括:
(1)编码器:用于流媒体文件生成的编码工具,如OBS,XSplit等;
(2)流媒体数据:直播信号、点播文件;
(3)流媒体服务器:用于控制、传送、处理流媒体数据的流媒体服务器
(4)传输网络:能够支持特定流式数据传输协议的传输网络
(5)多终端播放器:各操作平台用于显示流式数据的播放器。
以上5大组件是一个流媒体系统所必须要的基本组件,随着今年来的迅猛发展,能够承载大规模流媒体应用的内容分发网络(CDN)也有必要纳入流媒体系统的范畴了。除了这些基本系统外,大型的运营及流媒体系统还会有流媒体内容制作生产、内容管理控制、数据监控等周边系统和中间件等。
流媒体技术诞生的主要目的的是要在目前“尽力而为”的Internet上传输数据量非常大的音视频文件,所以流媒体技术最核心的就是音视频编解码技术和流式传输技术。
然而,在今天这个“体验为王”的时代,我们需要面临的流媒体,不论从用户量级上还是应用场景上来说都是极为复杂的。靠堆砌几台流媒体服务器,架个开源的OBS和播放器简单实现功能的时代早已过去。从当下成熟的大型流媒体系统来看,要完成一个支撑高体验大规模的流媒体系统,必要考虑的技术层面有:
这几年音视频技术、终端硬件平台、用户需求急速增长的同时,骨干网、跨运营商等基础设施的建设却明显没有跟上趟。这种现状下,要实现高稳定、高并发、低延时的流媒体应用,基于云架构的计算、网络、存储、CDN等底层基础服务已经变成了必须。硬件虚拟化,网络虚拟化能够最大程度保障音视频播放的稳定行;CDN内容分发网络能够有效应对高并发和突增流量的需求,对流媒体传输所有环节进行针对性优化能够大幅降低延时;对象存储满足了流媒体数据的大规模存储要求。
这个层面包括了音视频的编解码、4K、VR等音视频核心技术能力,尤其是在新形势下移动端编码和播放的优化。这里面包括了对不同硬件平台、操作系统的实践,固网移动网等不同网络环境下的理解,以及在弱网情况下的解决方案等。另外,4K、VR、AR等新技术的发展能提升用户观看体验,甚至引发全新应用场景;新的编码标准如H.265等能进一步提升音视频编码效率,降低对CDN网络带宽的消耗。
虽说流媒体的核心知识音视频编解码和流媒体传输,但针对当下不同垂直领域对于流媒体的应用,其中一些场景化功能需求,流媒体系统也不得不去考虑。比如秀场娱乐直播的实时录制,实时水印,实时鉴黄;社交直播的连麦;IPTV/OTT的时移回看;现场直播的云端导播;视频网站的版权保护等等。
实现一个点播系统需要解决视频转码和流媒体数据下载两个问题。
点播转码技术,唯一和流媒体相关的地方。用户录制完视频文件后,原始视频的格式和码率都是唯一的。在多终端复杂的网络环境下,移动环境下,网络环境非常复杂,网络不稳定,移动设备的性能也多种多样,为了保证用户的播放质量,选用较低的码率流媒体数据提供给用户,在PC端有线网络,或者wifi网络环境下,网络非常稳定,带宽也非常充足,为了提供更好的用户体验,会自动选择较高的码率的内容给用户,因此多码率是必不可少的。为了适应多用户需求和播放器环境,点播对多种格式的支持也是必须的,特别是移动端,对流媒体的播放限制比较大,比较通用的hls。由于转码技术发展历史比较长,使用非常广泛,开源支持的非常成熟和完善,ffmpeg对文件的转码已经做的非常好,直接使用就行了,不需要过多的开发。流媒体的转码是非常耗时和耗cpu的,因此只需要准备足够的机器资源就OK了。
从点播流媒体技术来看,基本上可以认为不属于流媒体了。电影或者录像,传输给各个终端是不变的,每个人看到的画面都是一样的,因此只需要将流媒体文件通过http下载到本地,就可以正常观看了。
点播P2P,分为客户端的P2P和web P2P,通过p2p技术,降低下载带宽成本,与流媒体没有任何关系。点播文件切片,DRM,弹幕,短视频分享,多终端封装,文件调度,视频文件存储,视频热点,mp4/flv-range请求等。与HTTP下载一样,都有成熟的方案,与流媒体没有任何关系。
CDN技术是流媒体最重要的技术之一,增强了用户到服务下载文件的接入质量,提高了用户的下载质量和速度。本质上也是HTTP,这也是为何CDN支持点播支持得很得心应手,几乎所有的CDN都能直接支持点播分发,甚至一些新兴的行业公司,譬如在线教育,点播都能自己做。
HTTP点播本质上是文件分发,直播流的本质是流媒体服务器在内存中将直播的包,打包成RTSP、RTMP、HTTP后发送给每个客户端。大部分公司都是使用直播的标准协议,使用开源的流媒体服务器,也有开始做直播比较早的,使用私有协议,推流和播放都只能使用自己的客户端,而且CDN上都得部署自己的流媒体。虽然私有协议,在灵活性上占优,但在与外部公司对接和交流,服务扩容成本,服务运维等方面,私有协议存在很大的弊端,很难做大做强,总的来讲,使用私有协议得不偿失,最终是要被社会给抛弃的。现在整个互联网都在强调开放,强调做生态,每个公司都是社会中的一员,公司之间的交流和沟通也越来越多,如果想要快速的做大做强,就必须开放标准,使用标准协议。
直播的本质需要解决两个问题,视频数据编解码和视频数据网络传输。一套大规模的流媒体系统,由编码工具负责对音视频文件编码压缩(h.264/h.265/VP9/AAC等);由流媒体服务器负责对数据包进行容器封装(flv/ts等)以及负责网络协议打包(RTMP/HTTP等);由CDN网络进行全网分发;由播放层负责对图像进行解码显示(FLASH/VLS/VIDEO JS等)。流媒体系统所需的核心组件包括:
编码工具:用于流媒体文件生成的编码工具
流媒体服务器:用于控制、传送流媒体数据的流媒体服务器
CDN网络:用户支撑流媒体的全网分发网络
网络协议:用于支持特定的流式传输的网络协议
播放器:各操作平台用户显示流式数据的播放器
视频直播是实时传输的视频,理论上来讲视频是不可能进行实时传输的。经过容器封装后的视频,一定是不可变的视频文件,不可变的视频文件已经是一个生产结果,这个生产结果显然不可能精确到实时的程度,它已经是一段时空的记忆。
因此视频直播,一定是一个“边生产,边传输,边消费”的过程。视频从原始的内容元素(图像和音频)到成品(视频文件)中间需要转码。
所谓的音视频编码,其实就是对一个数据进行压缩的过程。编解码技术设计到深奥的数学原理和计算机算法,如果不是专业研究编解码技术,不需要了解那么深,只需要搞清楚下面两个问题即可,一是为什么要压缩?二是为什么能压缩?
为什么要压缩,如果采用原始数字格式,一部1小时的电影大约几百个G,根本无法再网络上传输,同时也不方便存储。因此,必须通过编码技术将原始音视频数据进行大幅度的压缩,以能在互联网上传输及存储。
为什么能压缩,主要是由于原始音视频数据存在以下两种冗余数据:
数据冗余:视频画面的众多像素在空间上、时间上、结构上等方面存在很强的相似性甚至是完全一模一样。消除这些冗余数据并不会导致信息损失,此为无损压缩。
视觉/听觉冗余:人眼对亮度和色度的敏感度不同,使得数据在一定的范围内压缩引入误差,也基本不会有显著感知;人耳对20Hz~20KHz范围外的声音无法察觉,或者一定程度引入误差也无法感知。利用人类眼睛和耳朵的特性,在不影响正常的感知的情况下对数据进行压缩,此为有损压缩。
编码工作一般由硬件编码器、PC端OBS/FMLE、移动端各种采集SDK来完成。这些编码工具除了压缩编码外,其实还完成了采集、编码、封装、协议打包、推流等5大环节。
采集:该环节作用是通过音视频硬件采集卡、桌面采集程序、移动端采集程序将音视信号变为YUV/PCM等数字音视频信号。
编码:该环节作用是通过特定的视频、音频编码算法,将原始的YUV/PCM数据进行数量级的压缩,压缩后成为H.264/AAC等压缩数据。
封装:该环节将H.264/AAC等压缩数据按照一个统一的格式组装到一个文件里面,这就是我们经常所说的音视频文件格式,也就是文件的后缀名,文件只有有了格式,客户端才知道该用什么程序打开。
协议打包:该环节将上述如flv等封装数据加上一些信令数据后进行流媒体协议打包。
推流:就是编码工具将编码、封装好的音视频最终通过流媒体协议发送给流媒体服务器。
为了便于视频内容的存储和传输,通常需要减少视频内容的体积,也就是需要将原始的内容元素(图像和音频)经过压缩,压缩算法也简称编码格式。例如视频里边的原始图像数据会采用H.264编码格式进行压缩,音频采样数据会采用AAC编码格式进行压缩。
视频内容经过编码压缩后,确实有利于存储和传输;不过当要观看播放时,相应地也需要解码过程。因此编码和解码之间,显然要约定一种编码器和解码器都可以理解的约定。就视频图像和解码而言,这种约定很简单:
编码器讲很多张图像进行编码后生产成一段一段的GOP(Group of Pictures),解码器在播放时则是读取一段一段的GOP进行解码后读取画面再渲染显示。GOP是一组连续的画面,由一张I帧和数张B/P帧组成,是视频图像编码器和解码器存储的基本单位,它的排列顺序将会一直重复到影像结束。I帧是内部编码帧(也称为关键帧),P帧是前向预测帧(前向参考帧),B帧是双向内插帧(双向参考帧)。简单讲,I帧是一个完整的画面,而P帧和B帧记录的是相对于I帧的变化。如果没有I帧,P帧和B帧是无法解码。
视频直播是将每一帧数据(Video/Audio/DataFrame),打上时序标签(Timestamp)后进行流式传输的过程。发送端源源不断的采集音视频数据,经过编码、封包、推流,再经过中继分发网络进行扩散传输,播放端再源源不断地下载数据并按时序进行解码播放。如此就实现了“边生产、边传输、边消费”的直播过程。
一次完整的直播过程,包括但不限于以下环节:采集、处理、编码、封包、推流、传输、转码、分发、拉流、解码、播放。从推流到播放,在经过中间转发环节,延迟越低,用户体验越好。直播所有的数据都是在内存中,所有的这些工作都必须在1~3秒钟完成。直播主要的流程如下图所示。
直播模块图
上图中的直播推流端,通常是主播,负责流媒体数据的生产;传输分发,通常是流媒体服务器,负责流媒体数据的加工和传输;播放观看端,通常是用户,负责流媒体数据的消费。一次完整的直播,是有主播,流媒体服务器,和用户三方合作完成,三方属于不通的客体,之间需要进行数据传输,必不可少的需要涉及到传输协议。流媒体数据涉及到音频和视频,以及音频和视频之间的同步信息。
我们在基于一些商用编码设备、开源编码工具搭建流媒体系统或者操作直播相关业务时,掌握了基本概念后,其实更重要的是对编码相关的参数要有深刻的认识和熟练的配置优化。以下给出一些比较重要的参数概念:
GOP(Group of Pictures):一个GOP就是一组连续的画面,每个画面就是一帧, GOP就是很多帧的集合。这里面有I/P/B帧的概念,播放器显示画面是去找到最近的I帧(关键帧)来显示,所以为了实现秒开的体验,一般流媒体服务器会有GOP Cache配置,GOP Cache越长,播放体验会越好,但不好的一面是GOP Cache会增加直播的延迟。所以,我们在配置时一方面要做好延时与画质的平衡,另一方面可以通过追帧播放等技术来进行优化。
关键帧距离:关键帧(I帧)之间的最大距离(单位:秒),它是根据视频内容中的场景变换自动决策的,但两个关键帧之间的最大距离不超过该设定值,推荐配置:5-10。这个参数会影响到直播的延时,如果为了追求最低延时,可将其配置为1。
码率控制VBR/CBR/ABR:
CBR(Constant Bitrate):固定比特率,又称固定码率,相对于VBR和ABR来讲,它无法根据视频内容的变换而动态变换,导致某些情况下图像质量较差或某些情况下浪费带宽 。
ABR(Average Bitrate):平均比特率,又称平均码率,是介于CBR和VBR之间的一种折中算法。 对于较简单的图像或场景使用相对低的码率,高复杂度和大动态表现时使用高码率。互联网直播推荐使用才控制策略。
VBR(Variable Bitrate):动态比特率,又称动态码率,也就是没有固定的比特率,保持恒定质量的参数,推荐用于内网视频应用或视频存档。动态码率算法比固定码率复杂,消耗的CPU资源多,对硬件性能要求比较高。
码率控制缓冲区时长:缓冲区起到平滑码率波动的作用。在编码端,数据输入缓冲区的码率是变化的,而输出端则取决于码率控制模式。缓冲区越大平滑效果就越好同时延时也越大,缓冲区小能保证低延时同时可能由于上溢导致跳帧。
前向预测延迟:单位为秒,通过缓冲一定数量的视频帧(提高编码延迟)来提高编码质量,默认为自动,该参数跟编码延迟有关
超低延迟:如广电级编码器等部分编码设备或者编码工具由此选项,启用超低延迟,将关闭B帧、关闭MBtree、关闭码率控制前向预测,使编码的同时能够同步输出;由于启用低延迟模式,会在一定程度上降低视频质量,适用于视频通话和视频会议等。
参考帧数:控制DPB (Decoded Picture Buffer)的大小。可以在0-16之间选择。简单地说,就是设置P帧可以选择它之前的多少帧作为参照帧。最小可以选择值1,只参照自己前面的那帧。注意H.264标准限制了每个level可以参照的帧的数量。如果选择level4.1,1080p最大选4,720p最大选9。推荐设置为自动,将根据编码复杂度中相关参数设置。
B帧数量:手动指定在I帧或P帧之间创建的连续B帧的数量,范围是0-16。推荐设置为自动,将根据编码复杂度中相关参数设置。
视频质量与体验质量:视频是由图像和声音组成的,所以它本身是有质量属性的,我们可以简单的用清晰度、流畅感(帧率)来描述它。但我们在互联网上看视频尤其是直播,其实更需要整体的视听体验要好,这里面大致会涉及到的参数有采样率、帧率、分辨率、码率等,另外还和接入带宽、每个人不同的眼镜、耳朵感知程度等都有关系,是个比较复杂的过程。参数的具体含义之前文章的术语表中都能找到,总体来说,我们需要做的是一种各参数之间的平衡,来保障最终的观看体验。以下是观止云的编码参数配置建议:
以下几点需要提醒:
1080P VBR的码率范围一般为2.3-4Mbps,新闻类节目一般建议采用2.3Mbps,运动类节目一般建议采用4Mbps,观止推荐3Mbps;
720P VBR的码率范围一般为1.2-2Mbps,新闻类节目一般建议采用1.2Mbps,运动类节目一般建议采用2Mbps,观止推荐1.5Mbps;
576P VBR的码率范围一般为600k-1Mbp,新闻类节目一般建议采用1.2Mbps,运动类节目一般建议采用2Mbps,观止推荐800kbps;
480P VBR的码率范围一般为400kbps-600kbps,新闻类节目一般建议采用400kMbps,运动类节目一般建议采用600kbps,观止推荐500kbps;
360P VBR的码率范围一般为200kbps-400kbps,新闻类节目一般建议采用200kMbps,运动类节目一般建议采用400kbps,观止推荐300kbps;
本编码建议不适合IPTV、数字电视等采用CBR编码方式,通常采用IPTV和数字电视指提供576P和1080P两个选项,码率为2.5Mbps(576P 720x576)和8Mbps(1080P 1920x1080),个别地方提供720P,码率为4Mbps左右(720P 1280x720)
移动端的编码参数可参照PC-720P、PC-576P
视频质量评价:它讲的是如何评价视频本身质量,一般分为主观评价方法和客观评价方法。当下有多种成熟的评价模型、评价工具可供直接使用。目前使用的比较广泛的是客观质量评价SSIM和峰值信噪比PSNR,网络上有大量的其算法模型文章。
编码级别(Level):该指标是用来标识解码端解码能力的重要参数,跟每秒解码器能够处理的数据量相关,如果你的编码端有此选项,建议设置为自动,它就会根据当前编码复杂度、分辨率、帧率等配置计算出合适的Level值。如果很懂该参数,那就可以手动限制输出码流的Level值,以适配相应设备。
直播作为流媒体,需要解决的问题仍然是转码和流媒体数据下载。现在普遍上行都是采用RTMP协议进行推流,各种摄像机、视频采集设备、开源推流软件都支持标准的RTMP协议,而下行cdn播放的流,需要支持多码率,以适应复杂的网络环境。大部分公司不是单独只支持一种下行播放协议,特别是在移动互联网为主要应用场景的今天。在PC端,HTTP+FLV占主流,rtmp也占优一定的市场。在移动端,HLS是主流,HLS的播放地址,在手机浏览器里面就可以直接播放。为了支持移动端,hls协议是必须的要支持的。因此直播的转码操作是必不可少的。目前市场上开源的ffmpeg对视频转码的支持,做的非常好,很多开源的流媒体服务器直接集成了ffmpeg源码,转码技术也非常的成熟。
直播的流媒体数据下载,由于直播的流媒体数据是实时产生的,都是保存在内存中,因此需要专门的流媒体进行分发,至少需要直播转码服务器进行HLS切片后分发。目前市面上主流的流媒体服务器,有以Adobe FMS、Real Helix、Wowza为代表的第一代产品,它们的特点是单进程多线程。基于Linux2.7 epoll技术,出现了以多进程单线程为特点的第二代流媒体服务器,NginxRTMP、Crtmpd为其优秀的代表,另外还有基于JAVA的流媒体祖先Red5等。其中Red5,crtmpd,nginx-rtmp,SRS是开源的。
Red5性能有瓶颈,与新的一下rtmp服务器对接会有问题。CRTMP功能很完善,架构上却很复杂,C++代码写的很晦涩难懂。Nginx-rtmp,基于nginx,性能比CRTMP还要好,,单进程支持3000路并发。SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码,性能非常高,单进程能够支持9000路并发,是nginx-rtmp的三倍。是纯国产的开源Server,在中国流媒体业界实属难能可贵。但在这4个开源的软件中nginx-rtmp使用最为广泛,具体原因如下:
l2012年CDN业务开始急速增长,随之直播需求也越来越多,当时还没有一套公认的特别满意的流媒体服务器;
lnginx是HTTP领域的绝对霸主,大家对nginx的熟悉程度都非常高,易于运维。
l基于nginx,直播和点播使用同一套服务器,非常容易管理。
lCDN是靠运维的行业,运维的信心都是长年运出来的,nginx在web服务器上那么优秀,nginx-rtmp也差不到哪里去。
Nginx rtmp功能点
1.支持音视频直播
直接进行流分发,流媒体直播
2.支持flv/mp4视频格式,输入可以是文件或者HTTP流
3.支持两种流的分发模式(push and pull)
Push:直接进行转推,可以通过域名直接转推
Pull:拉流转推,也可直接配置域名,由播放请求触发拉流操作
application mypush { live on; # Every stream published here # is automatically pushed to # these two machines push rtmp1.example.com; push rtmp2.example.com:1934; } application mypull { live on; # Pull all streams from remote machine # and play locally pull rtmp://rtmp3.example.com; }
4.可以将直播流录制成flv文件
录制功能,默认录制为flv,需要注意录制路径权限
application myapp {
live on;
record all; //录制音频和视频
record_path /tmp;
record_max_size 2048M;
#record_interval 30s;
record_suffix .flv;
#on_publish http://localhost:8080/publish;
#on_play http://localhost:8080/play;
#on_record_done http://localhost:8080/record_done;
}
5.H264/AAC编码
H264是视频编码,AAC是音频编码
6.支持在线转码Onlinetranscoding with FFmpeg
直播转码,利用ffmpeg进行在线转码
# Transcoding (ffmpeg needed) application big { live on; # Multiple exec lines can be specified. exec /usr/bin/ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32x32 -f flv rtmp://localhost:1935/small/${name}; } application small { live on; # Video with reduced resolution comes here from ffmpeg }
7.支持HLS
默认就是支持hls的,已经验证
#放在1935的端口下面
application hls { hls on; hls_path /tmp/app; hls_fragment 10s; }
#放在80端口下面,走的是http的协议 location /hls { # Serve HLS fragments alias /tmp/app; }
hls_fragment:设置分片时长,默认是5s
hls_playlist_length:播放列表时长,默认是30s
hls_cleanup:是否开启自动清理hls分片功能,默认是开启的
8.HTTP callbacks(push/play/record/update etc)
on_connect:
设置HTTP连接的回调。当客户端连接问题的命令HTTP请求是异步发出命令和处理被挂起,直到它返回结果代码。如果返回HTTP 2XX代码,然后RTMP会话继续。
3XX的代码使RTMP重定向到另一个应用程序的名字是从位置HTTP响应头拍摄。否则,连接被丢弃。
在实际的系统中实现推流鉴权
on_publish:
推流回调,向业务逻辑服务上报推流信息,业务逻辑server可以向转码和截图模块,发送启动转码任务和截图任务
on_publish_done:
断流回调,向业务逻辑服务上报断流信息。清楚流状态。
on_record_one:
录制完成,录制完成后,可以再回调函数中,启动文件上传功能。
9.支持外部程序(exec)
10.HTTP control module for recording audio/video and dropping clients
支持开启停止录制,停止主播推流,停止观众播放流
http {
...
server {
listen 8080;
server_name localhost;
....
location /control {
rtmp_control all;
}
}
}
在实际的系统中实现禁播功能,主播推流过程中,实现断流处理
11.先进内存控制技术,可以在使用少量内存的情况下完成流畅的直播功能
12.可以和以下协同工作。FMS server,Player,外部程序
13.Statistics in XML/XSL in machine & human readable form
监控nginx-rtmp server运行状态
#http协议,需要坚挺8080端口,或者80端口
location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root /home/rarutyunyan/nginx-rtmp-module/; //源码路径 }
14.支持跨平台Linux/FreeBSD/MacOS
Rtmp直播的一般格式是: rtmp://youdomain.com/app/name,其中app的名字对于application的名字
CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。
CDN技术有非常成熟解决方案,技术上各家公司都不存在门槛,功能倾如一致。客户在各CDN厂商之间都可以进行无缝的切换。CDN逐步沦为资金密集型和人力密集型行业了,需要购买大量带宽和服务器,各个重要的网络节点建立机房,部署机器,建立基础的网络,建设周期长,并需要技术人员长时间的运维。小型公司或创业公司,是内有财力和精力,业务变化突然,cdn的建设周期满足不了业务的需求,一般都是通过其它专业cdn厂商购买服务。虽然核心技术都大同小异,但是实现细节还是差别比较大。
直播的最大成本是转码和带宽,其中带宽成本占了绝大部分,为了降低带宽成本,流媒体CDN一般采用三级架构,中心节点--中间源—边缘节点,中心节点一般直接从转码机器获取流数据,边缘节点是直接对用户的,节点非常多,中心节点的出口带宽有限,如果都去中心节点拉流,带宽会超过限制,因此增加中间源节点,降低CDN的回源量。为了降低回源带宽,一般会把边缘节点,分成一个个的单元,每个单元每条直播流,只会去中间源回源一路,从而降低中间源的回源带宽。
国内常见公开的直播协议有:RTMP、RTP、RTCP、RTSP,下面来进行逐一介绍。
RTMP(Real Time Messaging Protocol)实时消息传送协议,是Adobe的专利协议,为Flash和服务器之间音频、视频和数据传输开发的私有协议,大部分国外的CDN已经不支持,在国内还是非常流行。开源软件和开源库支持稳定,播放端有斗鱼常用的OBS软件,开源的librtmp,服务器端有nginx-rtmp插件。只要浏览器支持FlashPlayer就能非常简易的播放RTMP的直播,相对其他协议而言,RTMP协议初次建立连接的时候握手过程过于复杂(底层基于TCP,这里说的是RTMP协议本身的交互),视不同的网络状况会带来给首开带来100ms以上的延迟。基于RTMP的直播一般内容延迟在1~3秒。由于RTMP协议比较复杂,对rtmp协议的优化非常困难,在播放并发量比较大的情况,容易出现各种奇怪的问题。Rtmp是建立在tcp协议上应用层协议,使用默认端口是1935。
RTMP交互图
虽然RTMP在直播领域不是特别流行,但是在推流服务,也就是从【主播】-->【流媒体服务器】这个方向上,RTMP居于主导地位,目前国内的视频云服务都是以RTMP为主要要推流协议,市场上大部分硬件推流设备,都对RTMP协议支持的非常好。
RTP协议,即Real-time Transport Protocol,用于Internet上针对多媒体数据流的一种传输层协议。实际应用场景下经常需要RTCP(RTP Control Protocol)配合来使用,可以简单理解为RTCP传输交互控制的信令,RTP传输实际的媒体数据。RTP在视频监控、视频会议、IP电话上有广泛的应用,因为视频会议、IP电话的一个重要的使用体验:内容实时性强。
RTCP协议,实时传输控制协议(Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP)是实时传输协议(RTP)的一个姐妹协议。RTCP为RTP媒体流提供信道外(out-of-band)控制。RTCP本身并不传输数据,但和RTP一起协作将多媒体数据打包和发送。RTCP定期在流多媒体会话参加者之间传输控制数据。RTCP的主要功能是为RTP所提供的服务质量(Quality of Service)提供反馈。
RTSP(Real Time Streaming Protocol)协议,是由Real Networks和Netscape共同提出的。该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP提供了一个可扩展框架,使实时数据,如音频与视频的受控、点播成为可能。数据源包括现场数据与存储在剪辑中的数据。该协议目的在于控制多个数据发送连接,为选择发送通道,如UDP、多播UDP与TCP提供途径,并为选择基于RTP上发送机制提供方法。RTSP是用来控制声音或影像的多媒体串流协议,并允许同时多个串流需求控制,传输时所用的网络通讯协定并不在其定义的范围内,服务器端可以自行选择使用TCP或UDP来传送串流内容,它的语法和运作跟HTTP 1.1类似,但并不特别强调时间同步,所以比较能容忍网络延迟。Rtsp协议在监控行业占主导地址,暂时还没有看到有被替代的迹象。
RTP与其它协议有一个重要的区别就是默认使用UDP协议来传输数据,而其它协议都是基于TCP协议传输。实时音视频流的场景不需要可靠保障,因此也不需要有重传的机制,实时看到图像声音,网络抖动时丢了一些内容,画面模糊和花屏,完全不重要。TCP为了重传造成延迟和不同步,如果某一截内容因为重传,导致1秒以后才到,那个整个对话就延迟了1秒,随着网络抖动,延迟还会增加2秒、3秒,如果客户端播放是不加以处理将严重影响直播的体验。
RTMP协议比较全能,既可以用来推送又可以用来直播,其核心理念是将大块的视频帧和音频帧“剁碎”,然后以小数据包的形式在互联网上进行传输,而且支持加密,因此隐私性相对比较理想,但拆包组包的过程比较复杂,所以在海量并发时也容易出现一些不可预期的稳定性问题。因此不建议用户采用RTMP协议进行大并发的下行直播。
HLS协议,即Http Live Streaming,是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。是苹果公司QuickTime X和iPhone软件系统的一部分。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。hls文件分片,是MPEG-II进行压缩编码的,视频格式是ts,视频的编码格式是H264,音频编码格式为MP3、AAC或者AC-3。
简单的来讲,HLS将视频分成5-10s的视频小分片,然后用m3u8索引表进行管理,由于用户客户端下载到的视频都是5-10s的完整数据,故视频的流畅性很好,但也同样引入了很大的延迟(HLS的一般延迟在10-30s左右)。
HLS对移动端支持非常好,iPhone和大部分android手机浏览器上都能直接播放,常用于QQ和微信朋友圈的URL分享,不需要安装任何独立的APP。HLS在点播和直播都有比较广泛的应用,由于HLS默认就支持分片,不用额外去实现。随着移动互联网发展,促进了HLS的应用,hls即适用直播也适用于点播。
HLS是伪HTTP流,因为体验上类似流,但本质上依然是HTTP文件下载。
HTTP+FLV协议,即使用HTTP协议流式的传输媒体内容。相对于RTMP,FLV格式极其简单,只是在大块的视频帧和音视频头部加入一些标记信息,因此在延迟和大规模并发方面都很成熟,延迟同样可以做到2~5秒,打开速度更快,因为HTTP本身没有复杂的状态交互。所以从延迟角度来看,HTTP-FLV要优于RTMP。HTTP+FLV是类似于RTMP流式协议的HTTP长连接,需由特定流媒体服务器分发的,是真正HTTP流媒体传输方式,在延时、首画等体验上跟RTMP等流式协议拥有完全一致的表现,同时继承了部分HTTP的优势。
HTTP+FLV一般的实现是:服务器响应http请求时候不回复content-length字段;这样客户端就会一直接受数据,从而实现了流媒体的传输。不足的地方是flv在播放的时候需要通过flash插件来播放的,作为手机端APP直播协议却异常合适。
三种协议进行对比如下:
常用直播协议对比图
各种协议的优缺点:
1、编码工具最好都输出RTMP
2、流媒体服务器接入使用RTMP
3、流媒体系统内部全部使用RTMP
4、PC+直播+实时性要求高:使用RTMP,播放使用FLASH
5、PC+点播:使用HTTP文件分发或者HLS
6、IOS/Andorid+直播+实时性要求高:都使用HTTP-FLV,播放器自己开发
7、IOS/Android+直播+实时性要求低:都使用HLS
8、http协议的可以一定程度上避免防火墙的干扰
9、http协议可以很好的兼容http 302跳转,做到灵活调度
10、https可以使用https做加密通道
11、http可以很好的支持移动端
直播这么多协议,该如何选择合适的协议?只要问自己三个问题就可以了:
延迟要求,是否要求低于5秒的延迟?如果是硬指标,就只能选择RTMP或HTTP-FLV流。移动端需要自己编译ffmpeg支持,无法直接播放。
终端适配,是否要求支持PC和移动端(IOS和Android)?如果需要广泛支持移动端,HLS是最好的选择。
节约带宽,是否要求支持WebP2P?如果需要支持FlashP2P,或者移动端P2P,选择HLS。
如果用一句话说流媒体直播:实时性要求高的用RTMP或HTTP-FLV,其他都用HLS,基本上可以覆盖所有客户端的观看。
在目前常见的直播系统中,大部分选择的HTTP-FLV和HLS两种下行格式,HTTP-FLV满足用户的低时延要求,HLS满足用户的跨平台需求。选择这两种方式的根本原因是这两种协议是基于HTTP,HTTP对比RTMP协议,兼容性非常好,可以穿过一些防火墙,还支持灵活的调度,防盗链等功能。
视频播放器的原理
流媒体播放器实现的功能和流程与之前讲的编码工具刚好相反,历经解协议,解封装,解码视音频,视音频同步几个主干环节。
在播放端中,PC端用Flash就足够了,移动端可以基于ijkplayer这样的开源跨平台播放器去开发,关键点在于对移动端不同型号、网络切换、播放中来电话、应用转入后台运行等等事件下进行针对性处理以及CPU解码和GPU解码之间的平衡。另外,首屏加载时间和延迟优化在播放端也大有文章可做,比如通过缓存最近一个GOP减少播放器数据下载量快速启动解码以提升首屏时间,合理的缓冲策略、追帧播放等来提升延时等。
Flash播放器只有拿到GOP才能开始解码播放,cdn吐给Flash播放器的第一帧数据必须是关键帧,否则就是无用的数据,没有办法播放。为了能够第一时间给播放器吐关键帧数据,cdn必须对直播数据进行缓存,至少需要缓存一个GOP的数据。
常见的播放器主要分以下几类:
Web播放器的视频播放能力本身不是网页代码实现的,而是靠浏览器的支持,所以兼容性并不像我们想象的那么好,您必须要接受一个事实:不是所有的手机浏览器都符合预期的表现,有些手机浏览器甚至根本就不支持视频播放。
ffplay,vlc
flash播放器:
http://www.cutv.com/demo/live_test.swf
用户自己开发的app,快手,斗鱼等客户都会自己开发移动端APP
选好直播协议后,现在简单介绍一下直播流程,主播发起一个简单的直播,主干流程需要经历采集、编码、推流、转码、分发、拉流、解码和播放环节,要求在数秒内完成。
除此之外直播还需要完成录制、截图、防盗链、审查等诸多复杂的功能需求。具体实现的架构图如图5所示。
直播技术架构图
直播总体框架图
上行推流质量是整个直播系统的关键,用户推流的网络错综复杂,很多是在弱网络的移动环境下进行直播推流,如果上行推流就出现了丢帧,卡顿的现象,下行播放100%会卡顿,花屏,绿屏,灰屏等,严重的会导致播放卡死。
为了提高上行接入质量,腾讯在深圳、上海、天津、西安、成都、中国香港等国内核心节点部署IDC机器进行就近接入。其它二级中心节点,如长沙、武汉、济南利用OC节点接入进行补充,然后转推到核心节点。同时为了解决跨网络问题,采用了公司的TGW(Tencent Gateway)系统进行接入。TGW,是一套实现多网统一接入,支持自动负载均衡的系统。TGW具有可靠性高,扩展性强,性能高,抗攻击能力强等特点。外网接入采用的是gslb,GSLB DNS通过GSLB IP地址库来识别来自于不同LocalDNS的请求的递归出口IP的国家+省份+ISP属性,然后给对应的国家+地区+ISP的域名解析请求返回相应的IP,来最终实现负载均衡及就近接入。
为了解决域名解析导致负载不均衡的问题,对oc的接入点进行测速,监控oc点的接入质量,进行oc节点的全局调度(ip直通车,httpdns)。
测速方式: Q调测速
upload接入分布图
上行质量衡量指标:
码率:直播数据占用的带宽
帧率:每秒视频流的帧数
流畅度:本地流逝时间和视频流逝时间的对比,如果不匹配说明上行数据传输存在异常
推流接入目的是怎样最快的和用户建立连接,直接面对的是用户,很多时候不是upload服务器直接和用户对接,在upload和用户之间通常会插入upload_proxy作为接力,将用户的流转推给upload,upload_proxy有可能有多个,具体要看网络架构的实现。
推流接入是直播数据的入口,直播数据的主要来源如下:
1、演唱会,新闻发布会等大型活动直播,这种活动直播一般是临时的,采用专用软件,甚至直接用硬件进行推流,上行带宽和网络质量很好,上行接入网络质量可以得到保证,对直播服务总体的质量要求非常高,在直播过程中,不能出现任何故障。上行可以同时推多路流进行容灾。
2、第三方直播服务平台转推,如虎牙,斗鱼等直播平台,基于降低直播带宽成本和容灾的考虑,不会把所有的量都放给一家直播服务平台。但主播只会选择其中一家直播服务平台推流,这就要求接受直播推流的厂商,将直播流转推给其它CDN服务厂商。这种来源的上行网络质量也比较稳定,不会出现网路带宽不足的情况。
3、拉流转推,去第三方通过ffmpeg进行拉流转推,作为第三方网络出口带宽是有保障,正常的情况下,也不会出现卡顿。拉流转推可以分为三种方式,第一种是收到用户的推流通知,去指定的地址,进行拉流转推;第二种是定时定时检测制定的流地址是否有流,定时执行拉流转推;第三种是拉流出发的拉流转推,由第一个播放用户通过cdn访问,回源失败后,触发拉流转推模块按照制定的规则,去第三方进行拉流,再转推到自己的平台。拉流转推的方式,基本上都是服务器上进行操作,网络质量可以保证,出问题概率比较小。
4、个人直播推流,主播直接推流到直播服务平台,采用的网络多种多样,有线网,wifi,移动网络,小运营商宽带等,网络波动比较大,不能保证网络质量,一般的播放卡顿都是来源于主播。
除了推流外,还有一个视频数据来源是,去第三方源站回源。
可以直接配置推流转推,用户推过来的流,直接转推给第三方服务器。upload服务器只是简单的作为流接入和分发使用。
drop_idle_publisher 终止制定时间内闲置(没有音频/视频数据)的发布连接。默认为off,注意这个仅仅对发布模式的连接起作用。
为了更好的接入,upload之前加了一层upload_proxy,upload_proxy只是做简单的转推工作,upload还需要做逻辑,流分发以及数据上报,添加upload_proxy主要是防止upload发版本时,断掉与用户的连接。
由于推流是整个云端流程的第一个环节,非常重要,需要对推流进行容灾设置,容灾策略可以分为两种,第一种是用户可以给同一个流地址,同时推两路流;另一种是用户推一路流,upload转推成两路,互相备份。当其中一路出现故障时,CDN可以从另外一路流进行播放。两种方式都是可以的,我们采用的第一种方式。
推流断流原因分析:
Upload_proxy | upload | 错误说明 |
---|---|---|
Unknown reason | Unkown reason | Finalize_reason_str初始状态 |
Proxy recv deleteStream | Recv rtmp deleteStream | 推流端主动关闭(主播主动关闭) |
Proxy recv closeStream | Recv rtmp closeStream | 推流端主动关闭(主播主动关闭) |
Proxy recv() return 0 | Recv() return 0 | Proxy和推流端之间tcp链接,recv函数返回0,tcp链接断开(网络断了,收到0,表示收到了fin包) |
Proxy recv() return error | Recv() return error | Proxy和推流端之间tcp链接,recv函数返回-1,tcp链接断开,网络异常 |
Proxy handle read event failed | Server internal error | Proxy注册读事件错误,一般不常见,内部异常 |
Proxy met too big csid | Chunk stream id too big | Csid超过最大值65535,rtmp最多支持65597个流,ID在3~65599 |
Proxy met too big message | Rtmp message large than 1M | Rtmp message large than 1M,输入流有异常 |
Proxy drop idle stream | Drop idle stream | Proxy 70s 没有收到数据,断流 |
Proxy handle msg failed | Message handle failed(maybe server internal error) | Proxy处理接收的音视频数据失败,在处理过程中又没有明显的表示失败的原因,输入流有问题 |
Proxy recv drop cmd | Kickout bad rtmp stream | Proxy收到controller的drop命令断流 |
Proxy alloc recv buf failed | Server internal error | Proxy分配内存失败 |
Proxy send rtmp ack failed | Send rtmp ack failed | Rtmp协议,proxy回复推流端ack失败 |
Proxy send timeout | Send() timeout | Send超时,内部异常 |
Proxy send() return error | Send() return errror | 内部异常 |
Proxy send control msg failed | Send rtmp control msg failed | Send rtmp control msg failed,内部异常 |
Proxy handle write event failed | Server internal error | Proxy注册写事件失败 |
Proxy handle rtmp ping failed | Handle rtmp ping failed | Proxy和推流之间ping信令失败 |
Controller did not accept stream | Push url maybe invalid | Upload向controller发送upload_report信令,controller返回非0表示不接受该流,后台要看具体原因 |
3rdparty did not accept stream | 3rdparty auth failed | 第三方鉴权失败 |
Upload drop idle stream | Drop idle publisher | Upload 70s没有收到数据,断流 |
Upload recv drop command | Kickout bad stream | Upload收到controller的drop命令断流 |
Upload recv restart command | Kickout bad stream | 手动指定流重启 |
从UPLOAD单独拉一路流,如果码率和分辨率保持不变,只需要进行转封装,转封装的消耗的资源比较小。否则需要进行解码,重新进行编码,非常耗费转码资源。
HLS如果保持GOP不变是只需要转封装,如果GOP有变,即使码率不变,也需要进行解码和编码的。
FLV和RTMP如果码率不变,只需要转封装,否则需要进行解码和转码。
原始码率的默认就开始转封装,即推流后,就会触发转封装。
其它需要重新编解码,都需要第一个播放用户触发,才会启动转码任务。
1、多协议
rtmp,hls,flv
2、多码率
任何码率大小都可以
3、多分辨率
画面大小,支持转任何分辨率的
4、水印
添加水印功能,会额外增加播放时延
5、转变编码格式
H265
http://km.oa.com/group/578/articles/show/333881?kmref=search&from_page=1&no=1
截图对每个stream单独从upload拉一路流启动截图任务,然后上传到cos平台进行落地存储,默认每隔10s截一张,截图的下载地址是动态变化。
截图支持覆盖模式,每次上传的地址是固定,覆盖原来的图片。如果截图配置cdn分发,为了保证截图实时更新,cdn的缓存需要设置为0,不进行缓存。
默认无数据断流时长调整为75秒
截图和录制的数据分国内和国外进行存储,国内的存储中心部署在上海和广州,国外的存储中心部署在新加坡。
类似于截图,需要从upload单独拉一路流,对数据进行转封装,然后进行上传,目前也是保存在cos平台。所有的录制都是保持直播推流的码率不变,不需要对视频格式进行转换。录制的成功之后,文件会上传到点播平台。
Hls录制m3u8文件是不分的,不管直播多久,都是一个m3u8文件。
Flv录制默认30分钟一个分片,可以设置分片时长,每个分片生成后,立即进行数据上传。
Mp4录制默认90分钟一个分片。
录制模块图
支持定时录制和自动录制,controller通过发送消息NetStream.Record.Start和NetStream.Record.Stop两个消息来控制录制的启动和暂停。
recorder myrec { record all manual; record_path /var/rec; record_notify on; }
不同模块之前信息共享,数据传输逻辑控制,时序控制等。
OC下行观看用户直接访问的节点,是cdn的一部分。cdn为了减少DC的回源带宽,分成了中间源和OC节点两层,OC节点分成多个set,每个set内部互相做备份。用户访问oc set时,先随机选择一台oc节点进行接入,然后根据流id进行hash,从set内部选择一台oc节点去中间源进行请求,目的是为了减少oc节点到中间源的带宽。中间源内部也是类似的设计方案,具体如下图所示。
CDN内部架构图
进行回源收敛,降低回源带宽。
延迟指稳定网络下,发送和接收时差,即在播放端观看到的内容是几秒钟之前的视频内容,对延迟性要求比较高的应用场景,影响比较明显。
导致延迟的原因如下:
物理延迟:
网络传输是有延迟的,网络延迟RTT,一般在ms级,如果网络情况比较差,影响非常大。
网络抖动
n突发的转发速度变化
n增加后续播放的延迟
n无法预先计算
逻辑延迟:
RTMP和HLS是基于TCP之上的应用层协议,TCP三次握手,四次挥手,慢启动过程中的每次往返来回,都会加上上一次往返时的RTT。
直播流程一般较长,转发的模块较多,每转发一次都会产生网络延迟,转发环节越多,延迟越大。
一般在ms级。
累积延迟:
还有一种情况,就是累积延迟,rtmp是基于TCP的协议,网络传输是不会丢包,当网络状态差时,服务器会将包缓存起来,导致延迟越来越大,待网络状态好了,就一起发给客户端。为了解决此问题,需要开辟一个较大的缓冲区,并适当的调整播放策略,当缓冲区数据较多时,加快播放速度。还有一种方式,如果发现缓冲区的数据太多,就断开重连,获取最新的数据,断开重连是最有效的。
业务体验延迟:
Rtmp协议的播放流延迟在3s,http+flv的播放流延迟在2~3s,http+hls的播放延迟在20~30s。实际的延迟和cdn的缓存策略和推流端设置的GOP大小,为了提高用户的播放体验,cdn会在oc节点缓存直播数据,一般缓冲区的大小为16MB,不同码率的流,缓存数据的播放时长不一样。平均的播放延迟的影响因素如下:
-- 为了实现秒开功能,每次吐给用户的数据,必须从关键帧开始,关键帧间隔越大,平均播放时延也就越大。
-- 为了降低客户的卡顿,用户会设置回退策略,也就是说,用户可以指定从多少s之前下载数据,定位具体的回退时间,也需要参考GOP,需要从合适的关键帧开始吐数据。
-- 播放过程中出现了卡顿,播放器缓冲区的数据会越来越多,也会导致时延会增大。
延迟测量比较困难,需要在修改视频元数据,在扩展字段中,加上绝对时间戳,播放端收到播放数据后,解码获取绝对时间戳后,与本地当前时间进行比较,获得实际延迟时间,目前陌陌和快手都统计该指标。
如果想尽量降低播放时延,需要从下面两个方面考虑:
-- 在不影响用户体验的情况下,尽量降低GOP大小,GOP越小,平均时延越小。但也不能设置太小,设置太小,会导致视频编码的压缩率降低,导致需要传输的数据增多,也会影响到用户体验。建议设置为2s。
-- 播放器增加追延迟功能,播放缓冲区的数据如果比较多,在不影响观看的情况下,加快播放速度。
也不是延迟越低越好,适当的增加延迟可以降低播放的卡顿次数,提高用户的观看直播的体验。
低时延的应用场景如下:
-- 互动式直播:如美女直播,游戏直播等,各种主播,流媒体分发给用户观看,用户可以文字聊天和主播互动。
-- 视频会议:会议1s延迟是可以接受的,讲完话后,其他人需要思考,思考的延迟也会在1s左右。
-- 监控:监控对时延的要求也比较高。
一般的直播应用,只要不是电话类对话的那种要求,rtmp延迟是可以接受的。
直播的可用性包括两个方面,一个是要能播放成功,第二个是播放要连续,不能出现卡顿。用户需要可以正常拉到流,进行播放和观看,画面质量不能有异常,具体要求如下:
1、需要能够获取到视频数据。
2、需要能够及时的获取到数据,获取数据不能有延迟。
3、获取的数据需要是完整,正确的,否则会出现画面异常,如黑屏,花屏,绿屏。
卡顿是指视频播放过程中出现画面滞帧,让人们明显感觉到“卡”,也称为缓冲。单位时间内的播放卡顿次数统计称之为卡顿率。
造成卡顿的因素有可能是推流端发送数据中断,也有可能是公网传输拥塞或网络抖动异常,也有可能是终端设备的解码性能太差。卡顿频次越少或没有,则说明用户体验越好。卡顿引起的原因如下:
-- 帧率太低:如果主播手机性能较差,或者有占CPU的后台程序在运行,可能导致视频的帧率太低。正常情况下,每秒15FPS以上的视频流才能保证观看流畅,如果FPS低于10帧,可以判断为帧率太低,这会导致全部观众的观看体验都很卡顿。正常情况下直播的帧率都会超过15帧。
-- 上传受阻:主播的手机在推流时会源源不断地产生音视频数据,但如果手机的上传网速太小,那么产生的音视频数据都会被堆积在主播的手机里传不出去了,上传阻塞会导致全部观众的观看体验卡顿。国内运营商提供的宽带上网套餐中,下载网速虽然已经达到了10Mbps,20Mbps,甚至是100Mbps,但上传网速却还一直限制的比较小,很多小城市的上行网速最快是512Kbps。Wifi上网遵循IEEE 802.11规定的载波多路侦听和冲突避免标准,简言之就是一个WIFI热点同时只能跟一个手机通讯,其它手机在跟热点通讯前都要先探测或询问自己是否能够通讯,所以一个WiFi热点使用的人越多就越慢。同时,WiFi信号受建筑墙体的屏蔽干扰很厉害,而一般的中国普通家庭很少在装修时考虑好WiFi路由器和各个房间的信号衰减问题,可能主播本人也不清楚自己直播的房间离家里的路由器究竟穿了几堵墙。80%的卡顿问题是因为主播端上传阻塞所致。
-- 下行不佳:就是观众的下载带宽跟不上,或者网络很波动。比如直播流的码率是1Mbps的,也就是每秒有1M比特的数据流要下载下来。但如果观众端的带宽不够,就会导致观众端体验非常卡顿。下行不佳只会影响当前网络环境下的观众。
主要解决方法如下:
推流端:
-- 选用质量好的网络
-- 设置合理的编码设置,如帧率设置为15以上
-- 如果是自己开发的推流软件,可以对上行带宽进行探测,动态调整码率
播放端:
-- oc多吐数据,播放端多缓冲数据,播放端缓冲的数据越多,在播放过程中卡顿越少,但是缓冲数据多了,会引起较大的延迟,因此需要合理设置缓冲区大小。首帧吐流数据过多会导致首屏耗时过长,也会影响到用户的播放体验
具体指标:首帧时长
首屏耗时,指第一次点播播放后,肉眼看到画面所等待的时间。技术上指播放器解码第一帧渲染显示画面所花的耗时。通常所说的“秒开”,指点击播放后,一秒内即可以看到播放画面。首屏打开越快,说明用户体验越好。
首屏耗时主要由以下三个方面组成:
1、DNS解析
解决方法才用ip直通车,在下载视频流之前,先去专门的httpdns服务器上去获取最佳下载ip地址,寻找最佳ip地址的方法是利用QQ海量客户端对oc节点的测速数据,分析出访问那个服务器的视频流是最快的,另外系统内部还有一个实时监控cache服务器负载和状态的模块,确保返回的ip是可用,并且负载是均衡的。通过以上优化,减少了传统的dns请求,并且用户访问的资源更近了。
2、缓存、获取首帧内容
Oc节点缓存数据,每次都从最新关键帧开始吐数据,gop不能设置太大,否则会导致播放延迟过大。建议gop设置为2s左右,首帧播放可以降到500ms以下。
3、网络延迟
由于直播的链路比较长,从终端,到边缘节点,中间源,以及转码,中间还有可能存在大oc节点,往返时延非常大,为了减少网络时延,需要找到离用户最近的节点进行接入,采用预加载的方法,将数据缓存在边缘oc节点上,缩短数据访问的链路。
4、播放器缓存策略
播放器的缓存策略,也会影响到首帧时延的,如果有些播放器首次缓冲至少5s数据后才会进行播放。
在视频编码和解码过程中,不能大幅失真,保持画面质量和清晰度。
帧率:指的的视频每秒钟播放的图片数目,电影基本的帧率为24帧每秒(大于这个数时肉眼就看到的是流畅的视频了),二维动画的帧率为15帧每秒。帧率越小,那么你看到的视频就会越卡。动作就不连贯。
码率:这个跟单帧图片的信息量有关 ,越大图片储存的信息量越大,图片就越清晰。还原的画质就越好。当然不是越大越好。这样只会增加数据量,浪费内存。(码率越高许多的细节就会越完整,但是肉眼的辨别能力有限,许多细节的东西是分辨不出的)。
分辨率:就是视频的尺寸大小,如标准的720P视频就是每一横排有1280个像素,每一列有720个像素,总的像素就是1280x720个,这个乘积即是视频的分辨率。一般情况下,分辨率越大,视频就越清晰。但是关键要看你的视频的来源(码率高不高,拍摄设备的成像质量好不好)。
其他参数保持不变的情况下:
码率越大,画质越好,画面越清晰。
帧率越大,编码器必须加大对单帧画面的压缩比,需要通过降低画质来承载足够多的帧数,因此画面清晰度会下降。
分辨率越大,画面越大,需要传输的数据就越多,画质也会变差。
画面质量清晰度还与GOP大小以及编码格式有关,GOP越小,编码压缩比越低,需要传输的数据也就越多,在其它条件不变的情况下,会降低画质。市面上比较常见的编码器是H264,如果采用较新的H265格式的编码,H265压缩率更高,在码率和帧率保持不变的情况,画面质量约有30%的提升。
从上面介绍来看,搭建一个直播系统很简单的,最主要最核心的技术转码和直播内容分发都是使用开源的软件,CDN也没有什么技术壁垒,也可以自己搭建。如果你只想搭个简单的直播系统玩一玩,做做测试,还是可以的。如果要做上线运营的商业系统,特别是并发量比较大,这些远远不够。由于流媒体直播不是简单的业务,它是一个复杂的系统,涉及到文件存储、文件上传和下载,视频和音频编码,视频采集,视频转码和分发,视频的解码和播放,数据缓存,视频的录制,负载均衡等,虽然每一项市场上,都有成熟的技术,但要把这些技术综合在一起,变成一个完善的系统,还是非常有难度的。
流媒体直播实时性非常高,并发量和带宽都是非常高的,因此需要的机器资源也是非常多的。录制文件的存储,截图文件的存储,cdn都是非常耗资源的,由于这些是旁路的,都可以使用第三方服务。流媒体服务绕不过去的是转码,转码是耗资源是惊人的,转码的核心是编解码,如果转码之后和转码之前的码率保持一直,就不需要编解码,只需要转一下封装就可以,耗的资源比较少。如果需要将流的码率和分辨率进行转换,如转换成普清(550kbps),高清(900kbps),超高清等码率格式的直播流,需要将原始直播流先进行解码,然后在重新编码,解码所耗的资源是固定的,编码的码率越高,耗费的资源越多。一台普通的8核8G内存1000Mbps的网卡的服务器,只能支持6路高清转码。大量的转码机器,带来一个严重的问题—容错和负载均衡,需要对每台机器进行监控,出现故障机器,需要及时用其它机器进行替换,如何把转码任务分配到负载低的机器上等。
流媒体直播的流程非常长,任何一个环节出现问题都会导致直播不成功,中间环节这么长,要保证不出问题,还是非常难的。因此,流程监控是流媒体直播绕不过去的一个问题,需要对直播流的采集,推流,转码、分发、拉流、解码、播放,每个环节都需要进行监控。
网路问题是互联网的永远不可回避的一个问题,用户推流到流媒体的服务器这个环节是要经过外网的,外网的网络是不可控的,怎样解决流媒体服务器的网络接入质量呢?怎样解决跨地域,跨运营商网络问题呢?上行流的质量是非常关键的,如果上行流的质量得不到保证,后面流程做的最好,都无事于补。为了保证上行质量,需要在全国中心节点部署接入服务器,就近接入,主要的运营商都需要部署服务器,这些都需要专业级别的解决方案。提高上行质量的同时,还需要对上行流进行容错处理,时间戳错乱,需要进行恢复,在网络丢包不严重的情况下,需要保证直播的播放质量。
CDN播放负载均衡,目前比较流行的做法都是采用DNS解析的方法,如果采用HLS的,因为hls下载的是ts分片,是短连接,不会存在部分机器过热的现象。如果是HTTP+FLV或者RTMP进行下行播放,由于是长链接,如果落到某台机器上的链接都播放的时间很长,就会造成部分机器过热,搜集不到CDN节点的负载信息,DNS做不到精细化的调度,需要采用IP直通车的方式,需要有服务对每个CDN节点的资源负载信息进行收集,用户播放的时候,先去请求IP直通车服务,根据CDN节点的负载情况,进行全局调度,通过http的302跳转的方式,把CDN节点IP直接返回给播放器。
流媒体直播有一些坑是必须要踩的,如花屏、绿屏、黑屏、卡顿、首次播放慢、音画不同步等,花屏主要原因是用户上行直播流质量不稳定,有丢包或者数据错乱导致,还有一种就是用户在推流过程中,改变了推流配置,cdn对流的配置有缓存,导致cdn下发流配置与实际的流配置存在差异,从而导致花屏。绿屏和黑屏的原因多种多样,一般重推一下,就可以解决。卡顿的原因就多了,如果上行流本来就卡,播放肯定会卡,如果上行有丢帧,如果丢的恰好是关键帧,也会导致卡,用户的网络质量不稳定,也会导致播放的时候卡顿,这些都是已知原因,还有一些未知的原因,播放器下载速度太慢,导致cdn的缓存数据被覆盖,播放器的播放策略等,也会导致播放卡顿。首次播放时长,与播放器的缓存策略有关,有些播放器是获取到第一个关键帧就开始播放,有些播放器会缓存部分数据后,才开始播放,和用户的网络有关,同样的数据,如果用户网络不稳定,会导致传输时延比较长,还和cdn的缓存策略、直播的播放热度也有关系。音画不同步,主要原因是用户上行不稳定,丢包比较严重,采流设备有异常,也会导致音画不同步。
解决上述问题思路很简单,需要收集数据,对直播的各个环节进行监控,如果推流软件和播放器都是私有的,很好很强大,你可以通过推流软件和播放器搜集到第一手的质量数据,在目前互联网直播如此开放的今天,要求推流工具和播放器都用自己,有点不太现实。剩下的方法,就是需要在服务器端,直播环节很多,业务量很大,上报的数据也非常多,对如此多的数据进行统计分析,不是一件简单工作。
说了这么多,总结一下,直播的各项技术都非常成熟,不存在技术门槛,但是直播系统涉及到的环节非常多,系统复杂,涉及到的机器资源很多,运维工作非常大,数据监控和数据分析,对直播质量的提升,以及系统的稳定性,都是非常大的挑战。
虽然CDN的技术和流媒体没有任何关系,但是CDN技术在流媒体的发展过程中,是至关重要的,点播和直播都依赖与CDN,如果没有CDN,流媒体的数据就没有办法高质量的传输给用户。下面就来简单的科普一下CDN相关的知识。
IOS平台上无论硬编还是软编,由于是Apple一家公司出厂,几乎不存在因为芯片平台不同而导致的编码差异。
Android平台,Android Framework SDK提供的MediaCodec编码器,在不同的芯片平台上,差异表现很大,不同的厂家使用不同的芯片,而不同的芯片平台上Android MediaCodec表现略有差异,通常实现全平台兼容的成本不低。另外就是Android MediaCodec硬编层面的H.264编码画质参数是固定的baseline,所以画质通常也一般。因此,在Android平台下,推荐用软编,好处是画质可调控,兼容性也好。
如果编码器出现过载,在不影响画质的前提下,进行选择性丢帧,来降低编码环节的功能开销。
在移动网络下,通常容易遇到网络不稳定,连接被重置,断线重连,一方面频繁重连,建立连接需要开销。另一方面有其是发生GPRS/2G/3G/4G切换时,带宽可能出现瓶颈。当带宽不够,帧率较高/码率较高的内容较难发送出去,这个时候就需要可变码率支持。
即在推流端,可检测网络状态和简单测速,动态来切换码率,以保障网络切换时的推流流畅。
其次编码、封包、推流,这部分的逻辑也可以微调,可以尝试选择性丢帧,比如优先丢视频参考帧(不丢|帧和音频帧),这样也可以减少要传输的数据内容,但同时又打到了不影响画质和版视听流畅的目的。
直播是媒体流、APP的交互是API信令流,两者的状态不能混为一谈。尤其是不能基于APP的交互的API状态来判断直播流的状态。
n对网络很差的主播给予界面提示
n业务判断主动断掉网络很差的主播
n避免一个流做抢麦逻辑
n直播的流(socket)与业务的流(直播间)不可混为一谈
大家可能会看到,市面上某些手机直播APP的打开速度非常快,一点就开。而某些手机直播APP,点击播放后要等好几秒以后才能播放。是什么原因导致如此的天壤之别呢?
大部分播放器都是拿到一个完整的GOP后才能解码播放,基于FFmpeg移植的播放器甚至需要等待音画时间戳同步后才能播放(如果一个直播里边没有音频只有视频相当于要等待音频超时后才能播放画面)。
“秒开”可以从以下几个方面考虑:
n改写播放器逻辑让播放器拿到第一个关键帧后就给予显示。GOP的第一帧通常都是关键帧,由于加载的数据少,可以达到“首帧秒开”。如果直播服务器支持GOP缓存,意味着播放器和服务器建立连接后立即可以拿到数据,从而省却跨地域和跨运营商的回源传输时间。GOP体现了关键帧周期,也就是两个关键帧之间的距离,即同一个帧组的最大帧数。假设一个视频的恒定帧率是24fps(即1秒24帧图像),关键帧周期为2s,那么一个GOP就是48张图像。一般而言,每一秒视频至少需要使用一个关键帧。
n增加关键帧个数可以改善画质(GOP通常为FPS的倍数),但是同时增加了带宽和网络负载。这意味着,客户端播放器下载一个GOP,毕竟该GOP存在一定的数据体积,如果播放网络不佳,有可能不是能够快速在秒级以内下载完该GOP,进而影响观感体验。
n如果不能更改播放器行为逻辑为首帧秒开,直播服务器也可以做一些取巧处理,比如从缓存GOP改成缓存双关键帧(减少图像数量),这样可以极大程度地减少播放器加载GOP要传输的内容体积。
n在APP业务逻辑层面优化。比如提前做好DNS解析(省却几十毫秒),和提前做好测速选线(择取最优线路)。经过这样的预测处理后,在点击播放按钮时,将极大提高下载性能。
n主动推送GOP至边缘节点,边缘节点缓存GOP,播放端则可以快速加载,减少回源延迟。首屏也可以快速打开。
n贴近终端就近处理和分发,可以减少延迟,减少抖动,提高速度
这其实是一个直播过程中传输网络不可靠时的容错问题。例如,播放端临时断网了,但又快速恢复了,针对这种场景,播放端如果不做容错处理,很难不出现黑屏或是重新加载播放的现象。
为了容忍这种网络错误,并达到让终端用户无感知,客户端播放器可以考虑建立一个FIFO的缓冲队列,解码器从播放缓存队列读取数据,缓存队列从直播服务器源源不断的下载数据。通常,缓存队列的容量是以时间为单位(比如3s),在播放端网路不可靠时,客户端缓存可以起到“断网无感”的过渡作用。
显然,这只是一个“缓兵之计”,如果直播服务器边缘节点出现故障,而此时客户端又是长连接,在无法收到对端的连接断开信号,客户端的缓冲区容量再大也不管用了,这个时候就需要结合客户端业务逻辑来做调度。
重要的是客户端结合服务端,可以做精准调度。在初始化直播推流之前,例如基于IP地理位置和运营商的精确调度,分配线路质量最优的边缘接入节点。在直播推流的过程中,可以实时监测帧率反馈等质量数据,基于直播流的质量动态调整线路。
码率:
10秒的平均码率,码率过低的,播放质量比计较差
码率曲线
帧率:
10秒的平均帧率,理论上帧率是恒定的,如果出现了频繁的波动,表明推流丢帧比较严重,必然会出现卡顿。
帧率曲线
流畅度:
本地时间流逝和视频时间流逝对比,如果两天曲线偏离太大,就会出现卡顿
流畅度曲线
推流时间列表:
从下面表中可以获取都推流时间和结束时间,还有推流时长,客户端ip,tgw接入ip等重要信息,方便定位问题。
推流事件列表
通过upload监控,可以清晰的了解到upload接受到流的质量,对排查问题非常有效。
上行推流房间数
通过监控用户整体的推流房间数,能够监控到系统故障
在线直播流数
播放带宽:
下行播放带宽
同时在线播放人数:
下行同时在线人数
在线房间播放信息排行榜:
按照带宽和在线人数进行排行
在线房间列表
同屏对比
左边是从upload播放的结果,中间是从DC拉流播放的结果,右边的是从cdn,即从oc节点播放的结果
Upload能够正常播放,表明用户推流正常
Dc能够正常播放,表明转码和转封装正常
如果oc节点能够正常播放,表明整个链路都是没有问题
同频对比,能够很清晰的定位到问题出在哪里。
如果流媒体不采用CDN进行流分发,存在以下问题:
1、源站服务器的出口带宽有限。
2、源站服务器所处在地域和运营商是固定,需要解决跨运营商和跨地域问题,需要保证用户接入的网络质量。
3、负载均衡,在大并发的情况下,怎么保证服务器负载均衡分布。
4、数据缓存,源站服务器的内存或者磁盘有限,需要大容量的磁盘或大容量的内存进行数据缓存。
5、负载监控、数据统计、业务数据监控。
接入CDN帮流媒体很好的解决以上问题,CDN主要提供以下功能:
1、通过分布在全球各地的机房为用户提供就近接入,选择优质的节点进行接入。
2、通过CDN节点缓存数据,减轻源站的访问压力,分担源站服务器的出口带宽。
3、CDN可以提供安全防护,防止DDOS等攻击。
4、可以降低整体的访问时延
5、可以提高服务整体访问的成功率
6、负载均衡,容灾
CDN涉及主要模块如下
CDN技术架构
CDN实现细节
CDN系统需要解决以下问题:
1、网络接入成功率
CDN网络的目的是怎样高质量将视频数据传送到观众的播放端,让观众能够实时流畅的观看视频画面。
2、调度和扩容,容灾
直播是实时的,需要支持客户高并发的观看视频,当有突发时,需要能够实时的调用带宽和机器资源,满足客户观看需求。
3、机器监控和配置管理
直播需要支持海量客户的访问,需要大量的机器和带宽资源,通常是几千台服务器和超过百Tbps的带宽,机器故障和负载过载经常出现,如果不及时发现和处理,就会影响到客户观看质量。直播客户域名成千上万,每个客户的需求不尽相同,需要满足客户不同的需求,需要各种各样的配置,配置如何管理和快速发布 ,会影响到客户需求的响应速度。
4、回源和成本优化
直播最大的成本是带宽,如何节约带宽,降低回源,是直播系统的需要解决的重要问题之一。
智能路由
通过腾讯DNS服务(GSLB)对域名进行DNS解析,根据用户的出口ip所属的地域和运营商,实现就近接入。还有一种优化方案,IP直通车,通过立体化监控,用户测速,进行全局负载调度,返回接入质量最优的节点给用户。同时还支持HTTPDNS接入,防止域名劫持。
IP直通车调度是采用302跳转的方式实现的,调度策略主要参考以下几个参数:
l文件分布策略
l防盗链策略
l服务器负载
l机房负载
TCP优化
音视频技术
智能加速(就近接入):
我们使用了基础IP库,小运营商出口IP白名单机制,通过网络探测确保最优C段等方式,确保了用户网络最短的传输距离,达到较好的播放质量。
流量调度
立体化监控
Q调测速
服务器拨测
应用层数据监控
TCP测速
硬件基础数据监控
直播带宽计费策略,主要分为以下几种:
1、中小客户,尽量推峰值计费,网宿、阿里官网挂的也是峰值。 2、大一些的客户,不接受峰值,一般会用峰值平均。 网宿在几家客户也主推峰值平均。 3、商务单独谈,客户主导性强。可能只能是月95计费。 4、极少用的,但偶尔有客户强势要求的。 日平均后再月95。
正常情况: 峰值>第四峰值>峰值平均>月95>日平均月95, 每个档位计费差别基本在10%-20%,要看客户具体业务模型。
回源带宽只计算外网带宽,计费带宽也只计算外网带宽
1、DNS劫持
如果用户的发生了dns劫持,域名解析的ip地址是假的,当然就不能获取到正常的直播数据。
解决方法:通过ping域名,提供一个oc地址给用户,配置host进行播放
2、浏览器缓存
用户播放的老的数据,如果是hls,可以正常下载m3u8,但是不能获取到ts分片,m3u8文件是浏览器缓存的。
解决方法:清空浏览器缓存
3、推流不成功
推流不成功的原因分成以下三种:
-- 推流url不正确,鉴权不通过,签名不对或者已过期;
-- URL被占用,推流推到同一台服务器;
-- 连不上服务器,网络不通或者网络质量非常差,DNS劫持也会导致连接不上服务器。
4、播放不了
-- 播放url不对
-- 直播流已经结束
-- 播放鉴权不通过
-- 多码率的直播流采用延迟转码,默认是不启动转码,第一个用户发送播放请求后,才会触发转码,因此第一个用户获取直播流延迟会比较长,如果超时时间设置的比较短,就会出现播放失败的现象,遇到这种现象,多试几次就可以了。
-- 播放器缓存,导致播放很老的数据,特别是HLS,如果获取的是缓存中的m3u8,导致获取旧的ts,导致下载不成功。
-- 防火墙拦截,如果上述都排除了,还播放不了,就切换到4G网络试一下。
5、其它
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。