在视频直播中,有几个关键的体验指标,如卡顿率,清晰度,延迟时间,秒开速度等,本文介绍的就是得物直播在秒开体验上做的一些优化措施。
直播和视频秒开有很大不同,难度也更高。比如视频可以预下载对应的视频列表,而直播是动态、实时的流,不是静态的,所以就没办法去 prepare 以及预下载去做缓存。缓存这一大利器是用不了了,那么我们是如何提高其秒开速度的呢?
要做指标优化,首先确定通过数据作为支撑来优化指标,那么就需要客户端埋点,明确统计口径是什么,只有这样埋点数据才是有参考价值的。对于时长的统计那么我们需要明确的就是开始时间,结束时间,其差值就是我们需要上报的秒开时间了。
开始时间: 页面被选中时(在android 中对应 ViewPager 的 onPageSelected)
结束时间:播放器首帧回调;
秒开时间: 结束时间 - 开始时间
提升秒开体验,首先要梳理下直播链路:
简单来看,首先是生产端,即主播推流到流媒体服务器,然后流媒体服务器分发到各地的 CDN ,用户通过播放器拉流消费,主播端推流 -> 流媒体服务器 -> CDN边缘节点 -> 终端设备。
我们可以根据不同的端大致分为三个部分,推流部分,流服务部分,拉流部分。
这里注意一下,我们实际上统计的秒开数据只是拉流部分的,推流并不直接影响拉流端的优化策略,但是会间接影响秒开数据,比如同等条件下,推 H264 还是 H265 肯定 H265 的秒开更好一些,所以为了说清楚一整个直播的链路,这里将推流端做的一些影响秒开优化和设置也一并提了一下。
播放器拉流可以大致分为如下流程:
DNS 解析 -> CDN 节点建立连接 -> 收到GOP包 -> 解码第一帧 -> 渲染第一帧
其中耗时最长的就是 DNS 解析的缓解,因此要降低首屏时间,必须先降低 DNS 解析时间。
传统的DNS解析的过程很简单,业界统称localDNS方案,APP向所在网络运营商的DNS Server发起域名解析的请求,而运营商DNS Server会向CDN的GSLB系统发起递归查询,GSLB通过运营DNS Server所属IP地址判断查询来自于哪个运营商和地理位置,然后返回若干合适的CDN边缘节点IP给它。
HttpDNS使用HTTP协议进行域名解析,代替现有基于UDP的DNS协议,域名解析请求直接发送到阿里云的HttpDNS服务器,从而绕过运营商的Local DNS,能够避免Local DNS造成的域名劫持问题和调度不精准问题。
其原理其实比 localDNS 还要简单,就是APP通过HTTP协议直接调用CDN提供的httpsDNS API,获取一组合适的边缘节点IP。因为中间少了一条链路,所以这部分的耗时大致可以省却几十毫秒。通过节点优选后的 IP 我们要注意防止大量用户都聚集在少量节点,导致节点负载不均衡
上下滑是我们直播间切换的一个比较重要的方式,我们可以通过一些处理,让上下滑的秒开更快一些。
仔细看下这个视频会发现,当我们滑动直播间的时候下一个直播间的视频画面已经显示出来了,并且松手后判断如果没有离开当前直播间,也不会重新加载当前直播间的数据。
从用户的视觉来看,在滑动到下个直播间的瞬间就看到下个直播间的画面了,这实际上是充分利用了用户从开始滑动到手指离开屏幕的这段时间去拉流。
核心逻辑就是多个播放器,当前直播间一个,上下各保留一个,当用户滑动直播间卡片时,就可以根据 position 和当前直播的position去判断我们是上滑还是下滑,让对应的直播间 Fragment 去执行播放器的 start 即可。
从数据上可以看出,经过这一层优化之后,上下滑秒开率已经非常高了,并且 65%+ 的数据做到了 0 s 开。
直播间的 UI 布局比较复杂,那我们可不可以让布局不一次性全部加载进来,渐进式的去加载呢?
简单来说,渐进式加载就是一部分一部分加载,当前帧加载完成之后,再去加载下一帧。
这样设计的好处是可以减缓同一时刻,加载 View 带来的压力。这样我们就可以先加载核心部分的 View,再逐步去加载其他 View。比如在我们直播间就可以先加载我们的视频控件,然后再依次加载其他的布局控件。观察抖音直播的实现也是这样渐进式加载的,视频先出来,然后才是交互的 UI 。
目前我们直播间的 Fragment 除了核心的父布局以及播放器控件直接通过 xml 加载,其余的都通过 ViewStub 机制进行渐进式加载。
因为秒开的时间是从页面 UI 加载完成之后开始算的,所以这个优化的数据没有反映到秒开数据上,但从观感上确实优化了秒开时间。
收益:UI 布局首帧加载时间提升 90+%
直播对播放器体验要求比较高,直播播放的整体框架是,cdn建连、媒体文件下载、文件解析、音视频解码、音视频渲染,然后从整体播放链路上去优化首帧的秒开,整个链路上可以优化比较多的是,文件解析之前的这3个环节。秒开从实现策略上来讲,可以从两个维度考虑,可以称为缓冲配置和缓冲管理。
缓冲配置,尽量保证直播在正常播放的时候,尽可能去优化链路上的起播。
缓冲管理,尽量保证直播在播放的时候,可以跟进到当前直播点。
在cdn建连的过程中,自研播放器添加了支持IP直连的逻辑,可以通过给播放器设置已知服务器域名的形式,在内部直接通过IP直连CDN服务器;
在媒体文件下载的过程中,自研播放器调整了起播的buffer,不会额外设置起播的条件,只保证有足够时长的视频被解析。
在文件解析层面,当播放器大概有少量的数据下下来的时候,才开始去起播。
通过版本迭代测试,修改了播放器各个环节的内部buffer、缓冲量的大小、追帧策略,得到较为理想的秒开效果。目前和三方播放器保持持平状态。
目前我们使用的 RTMP推流,HTTP-FLV 拉流。
RTMP 协议为流媒体而设计,在推流中用的比较多,同时大多 CDN 厂商支持RTMP 协议。
HTTP-FLV 使用类似 RTMP流式的 HTTP 长连接,由特定流媒体服务器分发,兼顾两者的优点。以及可以复用现有 HTTP 分发资源的流式协议。 它的实时性和 RTMP 相等,与 RTMP 相比又省去了部分协议交互时间,首屏时间更短,可拓展的功能也更多。HLS 作为苹果提出的直播协议,在 iOS 端占据了不可撼动的地位,Android 端也同时提供相应的支持,但是我们作为实时互动直播,这个延时是不可接受的,所以不考虑。
推流端可以自己选择不同的画质进行推流,同时会根据网络状况动态设置码率和分辨率,所以秒开数据就要上报码率、分辨率的参数去对比分析,比如去看 720P 的秒开率,1080P 的秒开率。
画质 |
视频分辨率 |
H.264转码码率 |
H.265转码码率(比H.264下降30%) |
流畅(360P) |
640*360 |
400Kbps |
280Kbps |
标清(480P) |
854*480 |
600Kbps |
420Kbps |
高清(720P) |
1280*720 |
1000Kbps |
700Kbps |
超清(1080P) |
1920*1080 |
2000Kbps |
1400Kbps |
2K |
2560*1440 |
7000Kbps |
4900Kbps |
4K |
3840*2160 |
8000Kbps |
5600Kbps |
H.265旨在在有限带宽下传输更高质量的网络视频,仅需H.264的一半带宽即可播放相同质量的视频。比起H.264/AVC,H.265/HEVC提供了更多不同的工具来降低码率,以编码单位来说,H.264中每个宏块(macroblock/MB)大小都是固定的16x16像素,而H.265的编码单位可以选择从
最小的8x8到最大的64x64。同时,H.265的帧内预测模式支持33种方向(H.264只支持8种),并且提供了更好的运动补偿处理和矢量预测方法。
质量比较测试表明,在相同的图象质量下,相比于H.264,通过H.265编码的视频大小将减少大约39-44%。在码率减少51-74%的情况下,H.265编码视频的质量还能与H.264编码视频近似甚至更好,其本质上说是比预期的信噪比(PSNR)要好。
和动态码率一样,我们将拉流是 H264 还是 H265 作为埋点参数上报,然后对比同码率分辨率下 H264 H265 的秒开比。
除了客户端业务侧的优化外,我们还可以从流媒体服务器侧进行优化。
直播流中的图像帧分为:I 帧、P 帧、B 帧,其中只有 I 帧是能不依赖其他帧独立完成解码的,这就意味着当播放器接收到 I 帧它能马上渲染出来,而接收到 P 帧、B 帧则需要等待依赖的帧而不能立即完成解码和渲染,这个期间就是「黑屏」了。
所以,在服务器端可以通过缓存 GOP(在 H.264 中,GOP 是封闭的,是以 I 帧开头的一组图像帧序列),保证播放端在接入直播时能先获取到 I 帧马上渲染出画面来,从而优化首屏加载的体验。
这是流媒体服务器的基础功能,所以实际并不需要我们做什么。
混合云介绍:混合云融合了公有云和私有云,是近年来云计算的主要模式和发展方向。我们已经知道私有云主要是面向企业用户,出于安全考虑,企业更愿意将数据存放在私有云中,但是同时又希望可以获得公有云的计算资源,在这种情况下混合云被越来越多的采用,它将公有云和私有云进行混合和匹配,以获得最佳的效果,这种个性化的解决方案,达到了既省钱又安全的目的。
因为不同的云服务平台 CDN 分布不一,比如阿里云可能杭州的 CDN 节点比较多,速度较快,七牛可能上海的 CDN 节点比较多(只是比如哈),速度较快,我们便可以整合多家云服务平台,评测出用户当前最快的通道,从而提高用户连接的速度。同时不光是速度的提升,也是多云多活架构、容灾备份业务的落地。目前我们在对接的平台有阿里云,网宿,金山,七牛,华为等。
得物直播在历经一个 Q 的治理后,整体秒开率由 60% 左右到达 85%+:
在相同质量下,场景运动缓慢的视频比场景运动剧烈的视频,所需码率少很多,另外在高码率的时候,码率增加对视频质量的提升比较少,因此只要找到合适码率,那么视频低码率下的质量和高码率下的质量是相差无几的,因此我们需要对视频进行内容复杂度分析,获取场景信息,取得视频空间域的复杂度和时间域的复杂度,然后获得视频序列最终的复杂度,最终确定视频编码场景,这就是场景划分的意义所在。
参考资料:
http://www.52im.net/thread-1033-1-1.html
http://www.52im.net/thread-2087-1-1.html
文/子辰
关注得物技术,做最潮技术人!