前面几篇文章介绍了视频技术中最基础的概念以及Android中关于视频处理的一些知识,这些都是Android视频功能开发必须掌握的基础。这一篇文章作为这个系列的第四篇,主要来介绍直播相关的概念。
在这篇文章中,你可以学习到以下内容:
1.当前直播产品的现状和面临的挑战
2.直播系统的整体架构是怎样的
3.直播客户端的结构如何
4.常用的直播协议有哪些,他们有什么不同
5.直播卡顿和延时的原因和优化方式
带着这些问题,我们来开始今天的这篇文章~
任何事物的兴起和发展都是有其客观原因的,随着网络越来越发达,流量成本越来越低,移动设备性能和体验的不断提升,给直播提供了成长的土壤。正是基础设施的发展使得移动直播的门槛变的很低。对于那些有才艺、有特长、有颜值的内容生产者,他们迫不及待的需要一个平台去展示自己,吸引更多人的关注,并以此获得极高的人气和丰厚的收入,并有可能一举成名。游戏直播、体育直播、音乐直播、才艺直播等等,直播也在垂直领域自然而然的进行了细分。看惯了PGC的常规内容,甚至有些厌倦,现在的人们对于UGC内容越来越有兴趣,这给了他们极强的参与感和和带入感,可以进行实时互动,使得人的某些欲望得到了满足。UGC时代的到来,让直播成为内容领域不可或缺的一部分。
那么,在使用直播App时,对用户来说什么最重要呢?答案就是流畅性。现在直播软件众多,要在其中脱颖而出不只内容要有吸引力,软件的体验也是决定成功与否的关键。一个频繁卡顿又延迟很大的软件必然得不到用户的青睐。虽然说当前网络发达,设备配置越来越高,但是弱网环境是我们绕不过去的问题,低端设备也还大量存在,这些都是挡在用户体验面前的大山。作为一个开发者,我们需要给用户提供丰富的功能,但同时也不能忽视了App的体验也是决定其成败的关键因素。
直播中涉及到众多技术和方案,直播数据的采集、前处理(美颜和滤镜)、音视频编解码、流媒体协议、系统架构、CDN、播放器优化、用户互动等。其中的任何一项单独拿出来,都可以作为一个主题来展开讲解,并不是一篇文章就能完全讲清楚的。因此,我们在这篇文章中也只是先从宏观上对直播技术进行介绍,并不会对某一项进行深入分析。
我们先对直播系统做一个全局的介绍。从上图来看,直播系统主要由推流端、拉流端、业务服务器、IM、视频处理系统、CDN、视频管理系统等几部分组成。下面分别讲一下这几个组成部分的作用。
直播客户端结构分为推流端和拉流端。推流端就是主播端,视频的生产者;拉流端即观众端,视频的消费者。它们的职责不同,也就决定了结构有所差异。
首先来看推流端。
直播数据由视频和音频数据合成而成,数据的采集和处理需要分成视频和音频两部分来看。先来看视频部分,Camera负责采集原始视频数据,原始数据为YUV格式,然后经过编码器进行编码,生成编码后的数据,现在用的比较多的是H264格式。视频数据的编码可以通过软编码或者硬编码两种方式实现,Android上的硬编码使用MediaCodec,而软编码通常需要使用第三方库x264或者openh264。虽然硬件编码的效率要高一些,但是由于硬件的一致性比较差,很难实现统一的高质量的编码,所以通常都是使用软件方式来编码的。对于音频部分,通过麦克风获取音频并生成PCM格式的原始音频数据,然后通过某种音频编码器(如FAAC)编码成AAC格式的音频数据。最后,通过合成器将视频和音频数据合成为FLV格式的视频,通过RTMP协议发送出去。这样,整个推流端的处理就全部完成了。
我们了解了推流端的结构和原理,再来看一下拉流端的情况。其实我们可以合理的猜测,拉流端就是推流端的一个逆向的过程,实际也差不多就是这样。 拉流端播放器通过http-flv协议拉取数据,拿到flv格式的视频流数据。然后对音视频数据进行分离,分离出视频流和音频流,分别为H264和AAC格式,然后通过解码器对数据进行解码。像编码一样,解码也会有两种方式:硬解和软解,硬解码使用MediaCodec,而软解码使用ffmpeg。视频数据被解码成YUV原始数据并最终渲染到屏幕上,音频数据解码成PCM数据通过扬声器播放出来。这里有个音频和视频的同步过程,在播放音视频的时候,播放器会根据数据帧里的时间戳来保证音视频能够同步播放,否则会出现音画不同步的现象。
直播技术中有很多种协议,分别适用于不同的场景。今天我们来介绍三种常用的协议:rtmp、http-flv、hls。下面分别简单讲一下这几种协议的特点。
实时消息传输协议,Real Time Messaging Protocol,是 Adobe公司为 Flash 播放器和服务器之间音视频和数据传输开发的开放协议。协议基于tcp协议进行传输,实质上也是传输的flv格式的数据,不仅可以拉流,也可以推流。正常情况下拉流延迟在3s左右。
它直接基于http协议, 实际上就是将音视频数据封装成flv格式通过http协议进行传输。http-flv协议传送的数据可以看做一个无限大的flv文件,原理是服务器回复客户端请求的时候不加content-length字段。http-flv的延迟也比较小,一般在3s以内。
相比rtmp拉流,由于是直接基于http协议,http-flv有更多的优点,它可以很好的穿越防火墙,可以支持302跳转,可以使用https的加密,移动端支持的也比较好。
全称为Http Living Stream,是Apple开发的协议,也是基于http协议的。它的最大特点就是直播播放器获取到的并不是一个完整的视频流。hls协议在服务端将直播数据切片封装成ts段,形成无数小的ts文件。播放器在请求播放数据的时候,首先得到一个m3u8文件,该文件内部会有一个playlist,客户端按照顺序依次请求并播放ts文件数据。它的特点导致了实时性比较差,播放延迟很大,这个延迟是由切片长度决定的,一般大于10s。另外,hls也是基于http协议的,所以穿透性比较好,不容易被墙。
从上面的介绍看来,三种协议各有优缺点,我们通过一个表格来对三种协议做一个更为清晰的对比。
协议 |
http-flv |
rtmp |
hls |
传输 |
http |
tcp |
http |
视频格式 |
flv |
flv |
ts |
延时 |
低 |
低 |
高 |
数据分段 |
连续 |
连续 |
切片文件 |
H5播放 |
不支持 |
不支持 |
支持 |
通常,推流端会选用rtmp协议,客户端会选择http-flv来拉流,而h5则会选择hls协议进行拉流。
我们要清楚的是,卡顿和延时是有相关性的,卡顿可能会导致延时越来越大,而延时也会导致观众端的卡顿。
首先我们来看一下卡顿的原因。卡顿的主要来源有两个:设备性能和带宽限制。设备性能又分主播和观众端。由于Android本身的碎片化问题,Android设备性能良莠不齐,所以在编解码性能上很难保证所有机器都能满足要求。尤其为了保证一致性和兼容性,编解码通常会使用软解,更加重了机器的负担。既然观众端很难控制,为了尽量减少卡顿,只能是主播端尽量去使用更好的机器了。另外一个卡顿的原因就是网络状况的复杂性。不像设备问题只限于端,网络问题更是受运营商、CDN提供方的影响,可能某个CDN节点抽风一下,就会影响到一拨观众。因此,除了主播要保证良好的网络连通性,最重要的就是CDN网络的稳定,能够在大部分情况下给观众提供流畅稳定的服务。
对于卡顿,有一些优化策略,比如可以通过使用硬编解码充分利用GPU资源,或者通过增加播放器的缓冲区来降低网络不稳定带来的影响,或者降低编码质量来降低编码时间和传输时间等等。
下面再来看延时的问题,延时的来源也有很多。像上面提到的,网络状况比较差的时候,网络延迟增大,自然观众端的延时就会变大。其实有延迟是正常的,从推流端的数据采集,美颜和滤镜的处理,视频数据的编码,以及最终的数据发送,到服务端的网络延时,CDN的分发,数据的回源,再到观众端对数据的接收、解码和渲染,都是需要时间的。所以我们只要把延时控制在一个合理的区间内就是可以接受的。
对于延时的优化,可以优化推拉流端编解码的速度,可以通过优化首帧的展示时间来减少延时。另外,在播放器的策略上也可以做一些优化,比如可以适当的丢帧来进行追帧,或者在发现延迟很大的时候断掉连接重新进行连接等策略。
本文只是对直播的整体框架和技术的一个介绍,并没有对细节进行展开,比如对于卡顿和延时的优化的细节,后面有机会可以再单独来讲一讲。大家看完文章之后如果能够对直播技术有一个整体全面的认识,也就达到目的了。
欢迎关注我的微信公众号,收到最新的推送文章