本文字数:2259字
预计阅读时间:10分钟
视频起播时间,即首帧时间,是视频类应用的一个重要核心指标,也是影响用户观看体验的核心因素之一。如果视频要加载很久才能开始播放,用户放弃播放甚至离开 App 的概率都会增加。
视频秒播是指用户在起播时平滑播放,没有首屏的顿感,用户几乎感知不到有首帧时间的存在。
我们把从开始播放到视频首帧画面展现出来这个链路的耗时称为首帧耗时,想要优化首帧耗时,达到秒播效果,我们需要知道这个链路上,都进行了哪些步骤,然后找到其耗时点,进行针对性优化。不同的业务场景下,播放行为和播控策略不尽相同,最常见的就是冷启动场景、短视频场景、页面切换场景以及长视频场景。本文主要讨论具体业务场景下的优化实践,我们可以根据场景的特性,采取不同的优化策略。
01
通用首帧优化方法
1.1提前获取播放地址
视频播放的第一步就是获取视频资源的播放链接,通常而言,视频资源会有唯一标识video id,在点播的服务端会有一个根据video id获取播放链接的服务,如果将播放地址随feed流一起下发,或者播放前提前请求,则省去了客户端的一次网络请求耗时。
1.2预加载
预加载是一种常见的首帧优化措施,我们可以提前下载部分视频数据以达到快速起播的目的。但是什么时候去预加载、预加载多少、并行预加载数量等都是实际需要考虑的问题。
首先是预加载时机的问题,预加载时机如果太晚,几乎没有效果;如果太早,可能会跟当前正在播放的视频抢夺宝贵的带宽资源,甚至造成播放卡顿。我们必须要遵守一个原则:视频预加载绝对不能影响到当前视频的播放。一个简单的方案就是,当前视频缓冲到一定比例,再进行下个视频的预加载。当然还有更加细致的方案,根据当前播放视频的可用缓存、当前网络的下载速度、当前视频的码率以及即将预加载视频的码率、并行预加载数量,通过这些数据我们能够构建一个模型去预测接下来视频播放的卡顿状况,如果大概率是不会发生卡顿,则可以开启预加载,反之则不启用或者暂停预加载。
另外一个问题,预加载多少,直观认识,至少得保证首帧能加载出来。一个粗略的估算方法是moov大小加上视频的平均码率 * 预加载时长,这样就可以通过服务端下发moov头大小及视频的平均码率,然后在App端上通过实验去调整预加载时长参数,进而调整预加载大小。
1.3预渲染
通过预加载只能够将网络请求的耗时消除掉,但播放器还是需要经历解复用、解码、渲染的步骤,在中低端机器有200毫秒以上的耗时。如果能够将视频的首帧提前渲染好而不播放,将会缩减掉这部分的耗时。而预渲染就是提前将视频的首帧渲染出来的技术。
具体来说,预渲染会提前解码出视频首帧,并且将首帧渲染出来,但是这个过程中音频不会播放出来。在滑动播放场景,当滑动视频卡片时,就已经开始启动预渲染,在卡片滑动过程中,视频的首帧很可能就已经通过预渲染加载出来,这样当卡片滑到中央时,则直接启动播放,这时候用户基本上感受不到视频的加载。
02
分场景优化实践
2.1冷启动场景
冷启动场景下能做的优化空间较小,主要两个思路:
一、在App启动最早的时候(Application创建时),开始异步初始化播放器组件,让播放器尽早Ready;
二、在不影响体验的情况下,选择码率低的档位起播。
2.2短视频滑动场景
短视频沉浸式滑动播放场景,可以采取双播放器实例加载复用的策略,播放当前视频的同时,第二个播放器加载即将播放的视频,渲染首帧后暂停,列表其他视频进行预加载(预加载是纯下载的过程,无渲染逻辑)。
另外,还有滑动过程中调播的优化,在滑动松手 scrollViewWillEndDragging时就可以计算出待播放的视频,无需等到滑动停止scrollViewDidEndDragging,手指抬起就开启播放,可节省300毫秒左右的耗时。
在增加了下一个视频的 "预播" 机制后,用户滑到下个视频时,可以立即从首帧的暂停状态恢复为播放,不再需要预先显示封面图,也提高了播放体感上的速度。除视频以外的业务数据的渲染,可以放在用户滑动翻页的过程中进行。
基本流程如下图:
preload
2.3页面跳转场景
进入新页面时,总需要先请求播放数据及业务数据,然后再加载播放视频,这个过程会让用户感知到等待时长。播放页面之间的跳转,有两种情况:
一、播放中视频的跳转;
二、未起播视频的跳转。
针对情况一的优化策略为:无缝切换,不打断当前视频的播放,实现播放器在两个页面间的转移,真正做到"零耗时"体验。
针对情况二的优化策略为:在跳到新页面时需要前页面传入 videoUrl,提前进行播放,同时进行业务数据的请求和渲染。这样保证了视频与业务数据的加载可以异步执行,由于用户主要目光是集中在视频上的,所以从用户的视角直观的来看,页面加载速度变快了。
2.4长视频场景
长视频场景下可做的优化,一个是关键帧起播。长视频一般是从播放进度处起播,通常的实现方式是seek到历史进度前面最近的一个关键帧,然后把视频帧塞给解码器,在解码器中做丢帧处理,直到 pts 到了指定的历史进度。假设这个视频的码率是 2.5Mbps,视频的 GOP 大小为 5s,那么精准 seek 的起播,最坏情况需要额外下载 2.5 * 5=12.5Mb 的数据。如果我们只在关键帧位置起播(非精准 seek),则可以避免这些额外数据的下载,从而缩短首帧的耗时。
另一个是连播预加载,连播场景下是可以定位用户接下来要播放的视频的,可以采取提前获取播放地址,并进行预加载的策略,提高连播视频的起播速度。
03
总结与展望
本文介绍了通用的几种首帧优化方法,以及各实际业务场景中的不同优化策略,我们在项目开发中也在持续优化实践。客户端受网络环境、高中低各种机型、用户使用习惯等影响,无论是预加载、预渲染策略,还是网络请求策略等各种策略,仍有非常多需要精细化的去优化的点,才能让尽量多的用户都能获得更好的播放体验。