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