作者:喜马拉雅直播技能客户端 杜若尘
导读:随着互联网的展开,越来越多人喜欢直播,喜马拉雅直播也在快速展开中,现如今已有秀场直播、课程直播、语音聊天室等类型。为了进步用户的运用体会,本文针对喜马拉雅直播的杂乱流程进行了全体整理,并详细说明了展开的一系列直播启播优化作业。
背景
在直播场景中,QoE(Quality of Experience) 很重要,也便是用户体会,而 QoE 和 QoS 又是严密相关的,作为技能开发,需求从技能的视点去考虑怎么进步用户体会。直播场景中,用户的体会目标有很多种:首帧、卡顿、延迟、清晰度等等。站在用户的视点出发,在进入直播间后,必定希望能够立刻看到画面,也便是启播速度要快。所以首帧优化成为首要任务。
计算口径
在做直播启播优化前,首要要考虑怎么去衡量启播体会,也便是说要将启播体会转化为可量化的目标,并拟定体会标准以便衡量体会的好坏。启播体会问题能够转化为首帧耗时问题,首帧耗时越短,启播体会也就越好,比如以下标准:
拟定标准后,体会优化问题也就转化成了目标优化问题。要做目标优化,需求获取精确可靠的计算数据作为展开作业的支撑,明确计算口径是什么,只要这样客户端上报的埋点数据才是有参考价值的。关于时长的计算,需求明确开端和完毕时刻的界说,其差值便是需求上报的首帧时刻了。
关于开端时刻,选择不同的进口,计算方法也不相同。直播发动进口能够分为两个类:
1. 一类是从其他页面跳转进入直播间页面的,这类方法能够将页面的创立时刻作为开端时刻,在 Android 中对应 Fragment 的 onCreate 回调。
2. 另一类是在直播间页面内上下滑进入其他直播间,这类方法能够将下个页面被选中时作为开端时刻,在 Android 中对应 ViewPager 的 onPageSelected 回调。
关于完毕时刻,能够将播映器的首帧回调作为完毕时刻。
首帧耗时即为完毕时刻减去开端时刻。
直播全链路剖析
直播全体流程环节较多,主播推流到流媒体服务器,然后流媒体服务器分发到各地的 CDN ,用户经过播映器再从CDN 进行拉流播映,即主播端推流 -> 流媒体服务器 -> CDN 边际节点 -> 终端设备。其间终端拉流又能够细化成许多环节,像网络恳求、读取数据、解封装、解码、烘托。
能够依据不同的端大致分为三个部分:推流部分、流服务部分和拉流部分。客户端所做的首要优化作业集中在拉流部分,但推流部分、流服务部分同样也会间接对启播速度产生影响,这里也一并提一下。
现状
直播协议选择
RTMP 协议为流媒体而规划,在推流中用得比较多,一起大多 CDN 厂商支撑 RTMP 协议。
HTTP-FLV 运用类似 RTMP 流式的 HTTP 长连接,由特定流媒体服务器分发,兼顾两者的长处,还能够复用现有HTTP 分发资源的流式协议。它的实时性和 RTMP 适当,与 RTMP 相比又省去了部分协议交互时刻,首帧时刻更短、可拓宽的功用也更多。
HLS 由苹果公司提出依据 HTTP 的流媒体网络传输协议,可用于直播场景,Android 端也一起供给相应的支撑。
喜马直播移动端运用的 RTMP 推流、HTTP-FLV 拉流。
推流端—动态码率
流量操控功用能够让主播依据自己当时网络环境状况来动态调整视频推流的码率、帧率、分辨率,以及音频码率,自动适应当时网络环境及网络动摇,然后确保视频能流畅发布。
流量操控的原理是依据当时网络状况,对用户的网络环境建模并预算它的上行带宽。假如当时上行带宽小于设置的推流码率,则会经过装备的选项分别从视频码率、分辨率、帧率、音频码率几处按部就班地下降,以削减终究推流的上行码率,确保直播的流畅性。在网络环境康复正常以后,上行码率也会重新康复到初始设置值。
流媒体服务器优化—缓存GOP
视频是由一帧帧的图画组成的,GOP(Group of Pictures)是一组能够被独立解码的图画序列,它由一组不同类型的帧组成,包括关键帧(I 帧)、猜测帧(P 帧)和双向猜测帧(B 帧)。关键帧是视频序列中的完好帧,没有依靠其他帧进行解码。猜测帧和双向猜测帧则依据前面的关键帧或其他猜测帧进行编码和解码。假如拉流时返回的榜首个视频帧是 B 帧或 P 帧,那是无法被成功解码的,直到收到下一个 I 帧才干被解码展现画面,然后导致首帧时刻变长。因而,一般 CDN 都会缓存一到两组最近的 GOP,在收到客户端的资源访问恳求时返回最近的 GOP,这样能确保客户端收到的榜首个视频帧便是 I 帧,能够立马进行解码和烘托。
启播优化计划
拉流各阶段耗时拆分
关于拉流进程,能够细化成许多环节,如获取拉流地址、网络恳求、读取数据、解封装、解码、烘托。因而,需求把直播启播耗时进行阶段拆解、细化各个流程,并进行数据上报。在实际数据计算中,咱们会对各个环节(如网络恳求部分、解封装部分)进行更精密的计算。
下方表格列出了喜马直播业务的启播耗时各阶段的数据计算:
上表中进程 4-7 需求读取解析 flv 头部信息,其详细结构组成如下所示
从用户点击跳转到直播间或许在直播间内上下滑动切换直播间,到终究的直播播映成功,估计会有十多个的点位进行一系列的追寻剖析。详细的数据表格呈现启播进程中每一进程的耗时,然后针关于耗时多的地方进行优化。
预获取拉流地址
一般而言,用户进入直播间的业务场景,是从一个直播列表页面点击某一个直播卡片进入直播间。这个进程中,数据流是怎么走的呢?
在启播优化改造之前,观众从直播列表页点击某个直播卡片到直播间后,需求先向服务端恳求一个直播间概况接口,概况接口发现直播间当时是处于开播中状况的话,再去恳求该直播间拉流地址接口,交给播映器播映。
在这个进程中,播映器必须比及进入直播间,串行恳求完两个接口拿到直播流地址后才干开端播映,这个时刻点是能够提前的:在直播列表页及其他直播进口拿到直播间对应的流地址,在进入直播间时直接传过去,这样一进入直播间播映器就能够拿着直播流地址开端播映了,省去了从服务器恳求直播流地址的时刻。关于在直播间内上下滑切换房间的状况,就需求改造上下滑接口、增加拉流地址信息。
组件渐进式加载
直播间功用组件数量多达 34 个(如视频播映组件、红包功用组件、礼物动画功用组件等),页面层级杂乱,在一些中低端机型上加载较慢,能够选用渐进式的加载计划,让优先级高的组件先进行展现。组件加载方法遵从以下三条准则:
1. 组件按需加载,用到的时分再进行加载;
2. 组件视图假如杂乱,耗时问题不好解决,能够运用异步加载;
3. 组件能够按优先级串行加载,先展现首要视图,然后加载次要视图,最终加载特定条件才触发动态增加的视图。
规划优点是能够减缓同一时刻加载 View 带来的压力,实现先加载中心部分的 View,再逐步去加载其他 View。比如在喜马直播间就能够先加载视频播映组件,然后再依次加载其他的功用组件。
预烘托
1. 从外部页面进入直播间场景
直播间页面是在一个上下滑容器中进行加载的,从其他页面进入直播间遵从这样的时刻线:直播间容器页面创立 -> 直播间容器页面烘托 -> 直播间页面创立 -> 直播间页面烘托。当点击进口跳转的时分调用播映器进行播映,假如在直播间页面烘托出来之前榜首帧画面现已解码好了,这时因为直播间页面的 TextureView 的 Surface 仍然是不可用的状况,会导致解码的视频帧无法去送显。
因而,能够在直播间容器页面创立一个 SurfaceView ,将解码的视频帧先烘托至容器页面的 SurfaceView 上(之所以用 SurfaceView ,因为它 Surface 的烘托能够放到独自线程去做,防止主线程卡顿形成画面无法烘托的问题),比及直播间 TextureView 的 Surface 可用后,再将视频帧烘托到 TextureView 上,实现无缝切换。
2. 直播间上下滑场景
针对直播间上下滑场景,因前史原因,播映器是单例,所以在直播间上下滑场景中无法进行下一个直播间的预加载,只能比及下个直播间被选中时才干进行播映,也便是上下滑进程中手指抬起后开端播映下一个视频。一起,因为直播间 view 是复用的,要比及屏幕中止滑动后,才干够去复用上个直播间的 view 。
因而,假如屏幕在翻滚进程中,首帧已解码成功后,可先烘托至容器页面的 SurfaceView 上,待屏幕中止翻滚直播间 TextureView 的 Surface 可用后,再将视频帧烘托到 TextureView 上。
运用HttpDNS
网络恳求中,DNS 解析是一个相对耗时的进程。在传统的 localDNS 计划中,APP 向地点网络运营商的 DNS Server 建议域名解析的恳求,而运营商 DNS Server 会向 CDN 的 GSLB (Global Server Load Balancing)全局负载均衡体系建议递归查询,GSLB 经过运营 DNS Server 所属 IP 地址判断查询来自于哪个运营商和地理位置,然后返回若干合适的 CDN 边际节点 IP 给它。
HttpDNS 运用 HTTP 协议进行域名解析,把域名解析恳求直接发送到 HttpDNS 服务器,然后绕过运营商的 Local DNS ,能够防止 Local DNS 形成的域名绑架问题和调度不精准问题。因为中心少了一条链路,所以这部分的耗时大致能够省却几十毫秒。一起将节点 ip 进行缓存,下次有相同域名的恳求时直接返回该 ip,省去 DNS 解析耗时。
优化播映器缓存水位办理
播映器缓冲区首要有两个水位办理概念,一个是启播水位,另一个是卡顿后启播水位。顾名思义,启播水位表示首次拉流播映时,缓冲区到达多长时刻的数据能够开端播映。卡顿后启播水位表示假如缓冲区没有数据产生卡顿了,需求再下载到达多长时刻的数据才干够持续播映。关于启播优化来讲,为了让用户能够更快地启播,能够将启播水位调的尽可能小。因而在直播场景下,咱们将播映器的启播水位设置为了100ms,以到达更快的启播速度。
成果与考虑
经过一个季度的优化,现在喜马音频直播的秒开率到达了 90% 以上:
视频直播的秒开率到达了 85% 以上:
体会导向的使用理念
经过优化直播启播速度,不同渠道直播进口的播映转化率都得到了不同程度的进步,因而能够得出一个体会导向的使用理念:在引进任何优化时,首要需求评价计划的全体收益;之后需求规划全体优化计划进行开发调优;经过 AB 试验评价每项技能的业务目标影响,刻画性能目标与业务目标的相关;反复以上迭代进程。
未来展望
H.265
H.265 旨在在有限带宽下传输更高质量的网络视频,仅需 H.264 的一半带宽即可播映相同质量的视频。因而,关于相同质量的视频,H.265 只需下载 H.264 约一半的数据量即可进行解码烘托,有利于进步启播速度。
上下滑多播映器实例
上下滑是喜马切换直播间的一个重要的方法,后续能够运用多个播映器实例,在手指按下开端滑动的时分就去静音播映下一个直播间的资源,待手指抬起确定滑入下个直播间后再取消静音播映,一起中止上个直播间的播映。相比于单播映器实例,这样能够省去拖动屏幕这段时刻的耗时。
解码器复用
通常状况下,视频正常播映时解码器都需求进行 create()、configure()、start() 等初始化操作,而播映其他视频时,每次播映都必须重新进行这一初始化流程。依据上面的解码器状况流通图,假如播映完一个视频后不去 release 、stop解码器资源,而是直接用于解码下一个视频,实现解码器的复用,就能够省去创立及初始化解码器的耗时。
解码器复用的中心条件是支撑自适应播映属性,此属性是指 Android 供给的一种无缝切换不同分辨率视频的能力,能够由体系接口 (android.media.MediaCodecInfo.CodecCapabilities.isFeatureSupported(String)) 查询是否支撑。一起还要求当时视频编码格局要坚持相同,分辨率不能超过上个视频的分辨率。