视频业务中如何对下载任务进行限速

众所周知,视频业务是一个非常烧钱的业务,除了现在水涨船高的版权费用,CDN 厂商的带宽费用也是一笔昂贵的开支。

视频业务中,视频内容是非常重要的,可能是第一位的影响因素,从视频点播厂商的版权大战,到直播厂商的千播大战,我们可以发现,IP 影响力、PGC、UGC 上传的内容质量,对视频业务的成败有着举足轻重的影响。不过作为一个技术人员,这种资源毕竟不在我们掌控范围内,我们能做的就是在当前的业务场景下,在保证视频生产消费质量的前提下,尽可能为公司节省带宽、存储相关的开支。

视频点播中的限速

这里以视频点播业务为例,简单介绍一下,如何对一个视频进行下载限速。

业务初期的选择

算起来,我们公司视频业务的起步不算早,主打 PGC、UGC 内容,业务的主要形态就是视频列表。

视频体验的第一观感就是首屏时间(或首帧时间),即用户开始播放视频到视频画面出现的耗时,毕竟短视频时代,用户的耐性是有限的。为了提高视频播放的体验,预加载是必不可少的。从技术层面上来说,视频列表做预加载是最简单的,这很容易理解:只要在用户观看当前视频的时候,把下面一个或几个视频开头的一部分数据提前下载好就可以了(当然这一部分数据怎么确定的,不同产品有不同的策略,这里不展开)。除了预加载,视频播放过程中基本也是火力全开,全力保障视频下载速度,这种处理方式在业务初期是没有问题的,毕竟多花一点钱把体验提升上去,用户量就可能提升上去。

视频限速基本原理

随着业务的发展,问题逐渐显现出来:因为没有限速,CDN 带宽成倍增长,根本停不下来。这个时候有人可能会想:这是没办法的事,用户体验是第一位的,我们不能限速。但是基于以下几个原因,视频限速是可以做的,并且并不会影响用户的使用体验:

  • 视频并不需要全速下载才能保证流畅观看
  • 通过一定的策略调整,我们可以自由控制视频下载速度
  • 视频需要全速下载的时机是可以预测的

这里做一下简单的解释:
根据视频压缩的原理,我们知道视频是分 I/B/P 帧的,帧内也存在压缩,所以视频流不是均匀的,即便如此,视频码率仍可以大体描述每秒钟的视频流量,如果我们以视频码率 2~3 倍的速度下载这个视频,视频播放卡顿的可能性很小,根据我们对视频业务的观察,用户的下载速度可能不只 4~5 倍码率,这是没有必要的;

自由控制视频的下载速度,需要一定的设计,这在业务初期就是需要考虑到的;

如果能做到对下载过程的较准确控制,那么我们可以粗略计算出当前视频多缓冲了多少数据,这个数据量可以视为视频能否流畅播放的重要指标,根据这个指标,我们可以决定视频是走全速下载策略,还是限速下载策略;

此外,由于 CDN 厂商带宽收费的策略一般是根据一个月带宽峰值的 P95 之类的进行计算,通过合理的限速,可以把一些流量峰值有效的降低,带宽费用自然就下降了。从这些角度来说,视频下载限速不仅是可以做的,而且可以做到有百利而无一害。

视频限速如何操作

视频下载限速有两个角度可以切入:数据接收端、数据发送端

数据接收端:

  • 从接收过程进行限速,一般可以通过控制丢包或者控制数据接收处理速度来进行;
  • 控制丢包无法降低服务端的带宽消耗,仅仅降低了接收端的接收效率,处理复杂,实际意义不大;
  • 控制数据接收处理速度,可以通过控制接收缓冲区读取数据的速度来进行,涉及到底层操作,处理较为复杂,实际上降低了系统运行效率。

数据发送端:

  • 从发送过程进行限速,主要是控制数据请求的发送频率

总体来说,从数据接收端控制速度难度较高,并且意义不大。从数据发送端进行控制,容易操作。

很多公司的视频使用 MP4 格式,传统的 MP4 格式就是一个单独的视频文件,从发送端进行控制,要求视频文件不能只通过一个请求发送出去,需要将视频文件的下载通过多个 range 请求分段下载,通过控制 range 请求的发送频率来达到限速的目的。有了分段请求,就能计算出分段下载速度,通过视频码率和视频当前多缓冲的数据量,我们就可以进行下载策略的切换。

进一步的完善

之前提到的方法能解决一般情况下的视频限速,但是还是存在一些问题:

下载过程中发生 seek 操作怎么办?

视频点播和直播有一点不同,那就是视频点播存在 seek 操作,对于一个完整的 MP4 文件,频繁的 seek 会增大文件的存储难度,所以,range 请求就需要按照一定的规则来;此外,我们的 MP4 文件并不需要存储为一个单独的文件。

下载速度还是太快

根据我个人的测试,将速度限制为 2 倍或 3 倍码率,视频的播放仍然很流畅,但是想象一下:3 倍码率下载一个视频,视频在用户看到 1/3 左右的时候就下载完了,速度还是太快。可以考虑的做法是,对视频多缓冲的那部分数据做一点文章。