本文来自新浪微博视频转码平台技术负责人李成亚在LiveVideoStackCon 2017上的分享,由LiveVideoStack整理成文。李成亚分享了微博短视频如何提升用户体验、降低成本的思路与实践,包括提升短视频发布速度,降低长视频转码时间,通过新的Codec减少带宽成本等。
文 / 李成亚
整理 / LiveVideoStack
概览:
我所在的团队主要负责微博短视频从客户端的转码上传到服务端的转码存储的整条服务链路。今天主要向大家分享我们团队在短视频方面有关视频编解码的实践与探索。
这是一个简单的交互图,表示典型的生产者、消费者和服务方之间的关系,其在平台中关心的重点也会有所不同,在这里需要强调的是,我们今天主要讨论通过技术手段改进优化服务并为消费者带来更加完善的产品体验,关于用户内容的部分并不在此次讨论的范畴。
简单总结了一下平台中每方关切的重点:生产者关心视频的发布速度,也就是用户通过微博客户端发布一段视频,从点击发布按钮开始到其他人能在微博上看到此视频所需要时间的长短;消费者关心视频的观看体验,例如是否卡顿,流量消耗等;服务方关心平台的服务质量。
1. 发布速度
1.1 发送流程与关键性问题
先来看发布速度。首先向大家简单介绍一下用户通过微博客户端发送视频的流程。
客户端是一个iOS或Android平台应用。首先,在客户端我们会对视频做一次压缩,其目的是缩小视频体积;接下来视频经过转码后会被作为一个整体文件单独上传至Web Server, Web Server接收后会将视频上传到存储服务,同时在服务端触发转码操作。
此服务端转码的目的是:
(1)视频规范化,统一输出格式,排查视频错误;
(2)视频标记处理,为视频添加水印或标识;
(3)自动截图。接下来服务端转码后也会把此视频文件上传至存储服务,最后提示用户视频发送成功。
我想大家可以很明显地看出来这里有三个关键性问题:
(1)整个视频发布是一个串行的过程。意味着一旦其中任何一个环节出现问题都会导致整个操作的失败;
(2)服务端转码慢。因为曾经的服务端转码是一次性转码,我们为了减小视频压缩的体积使用了一个比较复杂的算法。
(3)长视频发布的速度非常慢。曾经在微博上发布一段最长一小时的视频,其延时可达到好几个小时。
后来我们重写或者重构了每条链路上一些关键节点的服务代码。
1.2 关键技术优化
下面我来介绍一下几个关键的技术优化点。
(1)在客户端我们会将编码与上传合并到同一个流程里,我们在客户端中集成了一个监控编码器的线程以监测编码器完成Gop数据编码的数量;一旦此数量累计到一定阀值后会触发客户端的上传操作,客户端将这部分数据进行单独分片并上传至Web Server,在Web Server收到所有分片之后会进行Merge操作,最后上传至存储服务。
(2)我们在转码端集成了一个调度模块,此模块会在发布阶段为视频做一次低复杂度的编码以缩短视频的发布延迟;当完成这次低复杂度转码后调度器会进行一次更高复杂度的转码,此转码完成之后会原播放链接会被替换,整个操作流程对用户而言是无感知的。
(3)对长视频采取分片并进行转码。其大概过程是:首先一个输入的视频会被分离成音频轨和视频轨。
其次依据其GOP,视频轨会被切割成不同的分片,一个分片中可能包含多个GOP。但一个GOP不会被分在不同的分片中,以避免最终视频合并时出现丢帧而导致视频观看卡顿的问题。
最终分片完成后,每一片会被调度器分发到不同的转码器同时进行转码。
此时调度器会开启一个监听线程去监听此视频所有分片的转码任务,一旦调度器监测到最后一个分片已经处理完成便触发一次Merge操作,把视频流的所有分片合并成一个视频,最后再和音频轨合并为一个完整的输出视频。
1.3 总结与成果
上述流程中我们主要做了以下三点优化:
(1)客户端:将编码与上传合并为一个操作。
(2)服务端:分等级转码。在发布阶段只进行简单复杂度的快速编码。
(3)对长视频进行分片并行转码。这里的两个关键点:A:分离音视频。B:按GOP分割视频流。
通过上述这些优化,我们可以提升视频平均发布速度至原来的3倍,提升长视频发布速度至原来的10倍以上,以上就是我们在视频发布阶段主要进行的一些优化。
2. 观看体验
下面我想与大家分享一些关于观看体验的优化,分享之前先为大家介绍一下产品形态与观看场景:
(1)产品形态
这是目前微博上主流的两个视频类产品,左边是一个信息流中的视频,其默认播放尺寸比较小而且基本上都以横屏呈现;右边是微博于2017年初上线的一个新服务“微博故事”,这是一个全屏播放并可添加AR特效的视频产品,以上是微博视频业务的两种产品形态。
(2)观看场景
观看场景是指用户会在什么样的场景下观看微博视频。首先,在网络环境上可能是Wi-Fi或移动网络;在终端设备上可能是手机、Pad或PC;手机又可依据不同的操作系统、屏幕大小、硬件配置等等进行细分。如果我们只做一些发布阶段的工作,用户在不同场景下选择不同产品形态看到的都是同一份文件。这种方案可能在某些特定的场景下能够带来比较好的体验,但是我相信对于大多数场景这种方案的体验应该都不是最好的,甚至很糟糕。
2.1 服务端转码细化
第一项优化是在服务端进行转码的细化,简单地说就是从原来的一个输出变为多个输出,这些输出之间主要的差别大概是以下三个维度:
(1)分辨率从低到高。微博视频服务的分辨率最低是240P,最高目前是720P,在未来还可以更高一些。
(2)编码复杂度从简单编码到复杂编码。
(3)视频格式,例如MP4、HLS等等。
2.2 下发策略优化
我们会在客户端构建一个定制化的下发策略,根据产品形态与用户的网络环境、设备类型、屏幕的尺寸等硬件配置来选择一个符合此场景需求的编码复杂度、分辨率、格式等输出参数。通常情况下我们选择的输出都是此用户在此场景下能够以足够清晰度播放的较低码率视频。
2.3 A/B Test
接下来要讲的是一种常见方法叫做A/B Test,大概分为四个步骤:定义指标、选择对照组、变更设置、对比结果。
(1)定义指标
详细说一下定义指标。第一个是首帧播放延迟,简单说就是从用户点击播放按纽到视频的第一帧画面播放出来所需要的时间,包括下载时间、解码时间、渲染时间等等;第二个是播放失败率;第三个是有效播放率,这里我们有两个和播放数相关的统计指标:总播放量就是只要此视频有一帧被成功播放就算一次,有效播放量是指此视频连续成功播放多长时间,例如三秒钟、五秒钟连续的播放。有效播放率就是这两者的比值。
(2)选择对照组
关于选择对照组我们大概有两种方式:第一种是随机选择,就是从所有的微博用户中随机抽取20%分成两个对照组。第二种是按特征选择,可以确定用户具体的某一个特征,例如是不是大V用户或粉丝数量处于何种量级,甚至可以按照用户登陆终端设备不同来进行选择。
(3)变更设置
这里我们主要在两方面进行一些区分与调整:第一是编解码参数,以 X264具体来说就是X264的那些编解码参数;第二是下发策略,有时候尽管两个用户可能处于同一个场景,但我们依然会下发一个不同的视频并最终看哪个视频的数据表现更好。这里其实还有一些其他的调整,例如是否启用客户端的软编、硬编、或软解、硬解等等。
(4)对比结果
最后就是对比结果,这里主要有两点,第一是前文定义的核心指标变化情况是趋于优还是差,第二是客观的视频质量对比;我们也会借助一些开源的工具来客观对比视频本身的指标,例如PSNR或者SSIM,这也是A/B Test的主要内容。需要说明的是,选择对照组、变更设置、对比结果是不断迭代的过程,通过不断的去调整各种设置最终达到优化指标的目的。
上图是指在 Wi-Fi 环境下微博自动播放的一种策略。既然是自动播放就涉及到一个问题:播放之前需要先下载视频,那么需要下载多少比较合适呢?
2.4 Wi-Fi 环境下自动播放
方案一:固定长度下载
一开始我们采取的是一种叫做“固定长度下载”的方案。简而言之就是每个视频都提前下载一部分固定长度的数据例如265K,当时此功能上线之后我们就发现了两个比较明显的问题:第一是视频下载服务器占用带宽有很大的上升。因为自动播放的功能,当天的播放量已经上升到之前的两倍多,其中一部分播放量最终回到视频的下载原站;第二是有部分的视频依然会出现轻微的卡顿感。
简单解释一下这两个问题的原因,其实这两个原因都和下载方式不正确有关系。带宽占用飙升是因为自动下载导致用户下载得太多,卡顿感是因为自动下载下的内容还不足以支撑流畅的播放体验。关于第二点需要进行解释的是:我们知道对于一个视频文件,比如说MP4,它的一些Meta信息或Moov信息是在头部的,并且此信息的长度与视频本身的长度相关,也就是说视频越长这部分的信息提取量越大,所以对于一些短视频自动下载256K可能太多,但对于长视频下载256K又太少。
方案二:固定时间下载
我们想到了一种固定时间下载的方案,简而言之就是对每个视频都先计算好一部分例如前三秒钟的数据大小,我们在服务端转码的同时会计算出此视频包含的Meta信息、Moov信息、前三帧的MBAT等加起来有多大;在用户浏览信息流的同时和这些信息将与播放链接一起下发至客户端。需要进行解释的是这个3秒是基于我们反复调整测试最终得出的一个最佳值,可以在明显消除自动播放卡顿感的同时控制带宽的占用。
2.5 提高视频源的质量
之前微博对发布视频的压缩门槛有了一个质的提升,从480P提高到了720P,并且对全部的微博用户都开放了此权限。我们未来还可能实现1080P的上传,可以看到随着分辨率的提升对比左右两个视频画面差距十分明显。
2.6 总结
简单总结一下对于观看体验方面的几项重要优化,第一是我们依据定制化的下发策略根据用户场景自动下发最符合此场景的视频;第二是我们使用A/B Test来帮助不断完善几项核心指标,从而优化观看体验;第三是我们实现了Wi-Fi下的自动播放;第四是提升上传视频的质量。
3. 服务质量
作为服务提供方的我们比较关心的问题可以概括成一句话:怎么既稳定又省钱地提供高质量的短视频服务?这句话有两个关键点:稳定、省钱。为了保证稳定我们做得更多的其实是一些类似于多机房部署等架构方面的工作,在此不用赘述。
3.1 降低成本
省钱,是指成本优化方面。在这里主要有两个降低成本的思路:
思路一:保持画质,提高编码复杂度,降低码率。
思路一可以简单理解为一个用时间换空间的方案。我们知道随着编解码器的发展,在其编码的复杂度越来越高的同时带宽与码率是越来越低,同等码率下视频质量越来越高。以H.265为例,官方给出的比较有代表性的数据是H.265相对于H.264而言其编码复杂度大概提升至后者的10倍,而码率能够达到H.264的50%。如此高的一个编码成本提升,如果是在客户端或是服务端进行都是不现实的。于是我们构想了一种新的思路:热门视频的极限转码。
思路一优化:热门视频极限转码
(1)业务特点
简单介绍一下,微博具有一个很明显的热点 长尾的业务特点,可能每天TOP2000或TOP1000部分的视频会占到当天视频播放量的50%以上,而绝大部分视频的播放量很低,只能占10%~20%。根据此种业务特点,我们提出了这种只对一部分热门视频进行极限转码的方案,从而最大程度地节省计算成本,降低带宽消耗。
(2)热点判断
如何判断某个视频是否为热门视频?我们主要从以下两个方面:第一是预判。在其发布阶段,我们根据发布方的影响力预判其是否为热门视频,在这里我们并没有什么非常复杂的机器学习算法,而是可以简单理解为根据用户的粉丝数作出判断。第二是跟踪。可能有些视频在发布阶段并没有被判定为一个热门视频,但是可能因为某位微博大V转发了他的视频或者因为这个视频本身很有意思从而带来播放量的爆发性增长。在这里我们会有一个程序去统计某个时间段t内全站播放量Top x的一部分视频;随后这部分中还未进行极限转码的视频,会被调度器投放至一个工作队列中进行极限转码。这里的一个小细节是我们的统计时间段t与统计视频数量x都可根据机群的工作负载进行动态调整。如果机群整体负载较高,我们会把这两个数值调低以避免热门视频的转码对正常发布视频的转码任务造成过多影响;如果机群整体负载较低,我们就可把这两个数适当调大以转码处理更多低码率视频从而降低带宽成本。
(3)方案选择
关于方案选择,在这里我只是提供一些可供选择的思路,大概是有三种:第一是更换编解码器例如H.265或AV1;第二是使用一些机器学习的技术进行场景识别,判断此视频的类型,从而优化编码过程。第三是使用云服务,业内的一些云服务提供商都能提供这种高复杂度转码能力的服务。
(4)意义与影响
通过采用对热门视频进行极限转码的方案,我们可以实现20%~40%的码率下降;而在目前所有微博视频播放量中通过这种高复杂度转码处理的视频的占比可达到一半以上,与此同时日带宽节省在一百TB以上。
思路二:保持画质,保持编码复杂程度,降低成本。
思路二是保持画质、保持编码复杂度的同时降低成本。上图是一个比较简单的视频转码流程,从视频输入到解封装,再到视频的解码与处理,经过视频的编码最后封装与合并到输出。此流程可以说本身已经没有什么优化的余地。
思路二优化:多输出转码
但这里有一个前提就是其输出并不是只有一个而是多个。这些输出之间的差别可能就是分辨率或格式,其他的大部分的参数是一样的。所以我们可以复用解码的一个环节:可以看到上图的后半段,在视频流解码完成之后视频会被复制出多份,每份会进行单独的视频转码,紧接着复制出的每一个流会与音频流合并成一个单独的输出,最终通过此方式我们可以同时转出多个输出。
意义与影响
通过这种方式我们可实现整体转码耗时节省15%左右。
3.2 降低集群冗余度
我们都知道现在很多的互联网业务都会面临一个流量明显变化的过程,例如一天中某个时间段会出现流量的高峰或低谷,如果希望集群能够经受住流量高峰的考验就需要保持一个比较高的冗余度,可能需要保持1.5甚至2倍的冗余,才能在流量高峰时段保证互联网服务的稳定进行。
以下是关于此方面我们进行的一些工作
3.2.1 消除差异
首先,在整个短视频服务的环节中,整条链路由以下四个服务构成:上传服务、转码服务、存储服务、业务服务。这些服务所需要的配置、运行环境,甚至实现语言都是不一样的,而每个服务都有自己的流量高峰与低谷。这便导致了这样一个问题:如果按传统方式,需要每个服务始终保持一个比较高的冗余度,那么所有服务加起来整个集群的冗余度就会显得非常高,从而造成一些浪费。所以我们需要做的是抹除这些服务之间的差异。具体来说是通过最近几年在后端领域很火的Docker技术将包括配置代码在内的整个运行环境打包成一个镜像,可以简单理解为一个压缩包;我们所有的服务依赖的都是这种Docker服务,只要在机器上安装Docker软件就可以随时启用所需服务。通过这种方式可以将之前处于高冗余度下的四个集群转变为一个集群,此机群只要保持一定的冗余度就可完成服务的承载。
3.2.2 定时扩容
上图是微博大致的每天流量变化趋势,最右边那部分是晚8点到次日凌晨0点的晚高峰,可以说几乎每天流量都是以这种趋势变化,晚高峰时段流量会比白天大部分时间段高出20%~30%的样子,面对这种情况我们会在高峰时段通过一些公有云服务扩充出的一些计算资源承担这部分高峰流量;当高峰期结束便撤下这些公有云服务以尽可能降低服务的整体成本。
3.3.3 弹性扩容
上图是之前鹿晗发微博公开恋情的半个小时内,微博一些核心服务的流量变化。可以看到从12点的值到最高峰,不到半个小时流量基本翻了4倍。这种量级的上涨是无法通过诸如降级或流量调配等人工干预手段有效应对,这便要求我们的服务器必须具备快速且大批量的弹性扩容能力。当天我们也是从阿里云上紧急扩容了超过一千台的服务器,最终将此热点事件造成的流量爆炸性增长化险为夷。
3.3.4 成本优化总结
简单总结一下我们在成本优化方面做的一些工作:首先是对热门视频进行极限转码,通过以最小的计算资源去获取最大带宽节省来降低成本;其次是我们多输出转码,整体上降低一些编码的成本,随着发布的视频的质量越来越高,多输出转码降低成本所带来的收益应该会继续提高;第三是根据业务的流量变化通过一些弹性扩容的手段来动态调整集群的规模。