Revvel如何将视频转码速度提升几十倍?

2021-09-02 12:08:41 浏览数 (1)

来自Revvel的团队的Greg Femec在re:Invent 2017大会上分享了他在构建视频转码服务中遇到的挑战,以及构建基于Serverless架构的视频转码平台的经验。Revvel团队将视频转码服务从AWS EC2迁移到AWS Lambda和S3上,实现了整个转码的Serverless化,节省了大量费用和运维成本,并且将时长2小时的视频转码从4-6小时缩短到不到10分钟,从而将更多的时间投入到核心服务的开发和优化当中。LiveVideoStack对其进行了摘译整理,点击『阅读原文』观看Greg的分享视频。

作者:Greg Femec,Revvel资深软件开发主管(Principle Development Lead)

听译:王鸿蒙

责编:Ant

Serverless系统架构具有自动扩容、按需付费、无需服务器部署和运维以及高可用性和容错性的特点。AWS Lambda是著名的Serverless云服务提供商,在AWS Lambda上的一个典型Serverless应用往往通过事件驱动的方式去触发对预定义函数的调用。事件源可以有很多种,主要分为3类:

  • 数据状态变化,例如S3对象的新增、删除。
  • API请求,即通过特定的HTTP请求来触发函数的执行。
  • 资源状态变化,如AWS云组件的相关配置发生变化。

AWS Lambda典型的应用包括:

  • 网站: 静态网站,复杂网站应用,Flask和Express网站架构
  • 后台:应用和服务,移动App,物联网(IoT)
  • 数据处理:实时数据处理,MapReduce,批处理
  • 聊天机器人:聊天逻辑
  • Amazon Alexa: 语音驱动的应用, Alexa 技能工具包
  • IT自动化: 策略引擎, 扩展服务, 架构管理

在视频编码处理中,并行编码算法有多种,根据并行级别可以分为GoP 级、帧级、Slice 级和宏块行级。视频编码的这种特点使得它可以很好的利用AWS Lamda的并行处理的特性。Revvel团队在之前构建视频转码服务平台过程中遇到过许多挑战,主要体现在以下几个方面:

  • 大量的待转码视频
  • 无法提前预测转码业务所需的时间及工作量
  • 视频源来自于不同的合作伙伴,不同的拍摄设备,导致其长短,分辨率、码率多种多样
  • 不同的输入格式
  • 输出格式多样, 多种封装格式
  • 典型的无交错(逐行扫描)MP4
  • HLS(TS块)
  • DASH(片段化MP4)
  • 各种DRM协议

在早期Revvel团队使用了SaaS方案。但是由于视频的来源不同,我们很难在这个方案中获得对于视频转码更高的控制权。同时成本效益并不高,尤其是新增转码格式的边际成本并未随着用量增大而显著降低。

我们也在AWS EC2上尝试建立自己的视频转码服务,成本得到了一定的控制,视频的控制权也增大,但随之而来的是运维方面的挑战。这些挑战表现在:

  1. 可扩展性。用户希望能够快速上传并分享视频,因此我们希望避免任何任务排队,以快速响应用户请求。但是这里涉及到冷启动问题。从购买计算资源直至计算资源可用,要花费大量的时间启动实例,下载软件,安装更新,下载所需文件。
  2. 资源浪费。假设我们有一个可以同时运行多个任务的高性能实例,但目前却只有一个比较耗时的任务在运行,比如高清(HD)视频转码,这在我们当前的配置下通常会花费好几个小时。我们无法利用该实例上多余的计算能力,也无法中止转码,把任务移交到另外一台机器来回收多余的计算资源。另外,在我们构建转码服务的时候,EC2按小时计费,如果我们启动多个实例处理视频,每个实例运行了20分钟,每个实例仍然需要支付一小时的费用。(从2017年9月份开始,EC2可以按秒计费。)

我们为什么使用Serverless?

Serverless的好处明显:没有冷启动问题,可以快速扩容缩容,没有资源浪费,运维问题更少,并发量更大(AWS Lambda默认并发执行上限为1000,我们调整为2000,但这并不是硬性限制),以及灵活的资源配置(可以快速重新对资源进行分配)。

Serverless下转码的挑战

输入的视频文件往往较大(有些有数百GB),我们不希望等文件下载完成才开始处理,并且我们在Lambda中的容器也没有这么大的存储空间。另外,视频转码工具一般假定输入输出为完整的视频文件,无法进行块级的处理。同时,如我们之前提到的,HD视频转码往往耗时好几个小时,而且转码一旦开始,很难暂停和重启。

我们的解决方案

我们的高效视频转码解决方案使用类似于MapReduce的分治法,把视频切成5秒(时间可以调整)的小块,在map中进行转码,在reduce中进行合并,输出我们需要的格式, 比如无交错视频(Progressive MP4)和MPEG-DASH。对于HLS,某些情况下我们可以直接使用map的结果作为TS块,有时也做一些后期处理,尤其是需要加入DRM时。同时需要避免在本地磁盘上缓存完整的视频大文件。

我们使用的工具包括AWS Lambda(实时缩放、并行处理的能力)、S3(支持分段上传,按范围请求数据)、FFmpeg(转码领域的瑞士军刀)以及Python(AWS Lambda对Python有很好的支持,Revvel团队熟悉并大量使用该语言,并可以对C代码进行很好的整合)。下面对Serverless转码的架构图进行简要说明:

图:转码架构图

我们的输入和输出处理基于S3存储。首先,我们从不同的存储位置获取视频源文件,统一存储在S3上,执行map(图中所示Chunk Lambda Function)开始进行处理。严格来讲,在这里我们可以并行运行任意数量的map,视频文件中的每组5秒数据块可以被分别获取,这些5秒数据块的计算相互独立,每一个的处理都不依赖于其他的5秒数据块,数据块的分发和执行只取决于我们现有的CPU总核数,以及并发的Lambda function执行数量。所以,这就允许我们一次运行多组程序来处理ts块,而这步处理的结果将被存储于另外的S3存储桶中。下一步,我们继续在这些文件块上进行reduce。通过对文件块进行相对简单的reduce操作,并将他们合并,可以生成MP4文件;如果要生成DRM文件则要更加复杂的过程,图中所示即是生成DRM后的HLS文件的例子,而DASH文件的生成过程与之类似。

下面我们讲解块函数(Chunk Function)操作中的细节。

块函数(Chunk Function)工作说明

之所以叫块函数,是因为我们要通过这个函数生成ts文件块。如果我们想生成一个文件块,首先就需要解码输入视频中的一小部分,然后将其转码到想要得到的分辨率/码率,最后,将生成的TS文件块上传到S3中。这里面临如下两个主要的挑战。

图:块函数(Chunk Funtion)工作流程图

  • 解码的挑战与解决方案

从上面可以看到,我们不再需要下载整个文件,而只是对其中一小部分进行操作即可。因此,我们的挑战主要来自于如何在这种情况下实现解码。通常,我们使用FFmpeg帮助我们完成大部分解码操作。FFmpeg支持有大小范围请求的HTTP请求,FFmpeg常常读若干字节后前后跳转,产生大量的HTTP请求来对相同文件块反复读取,造成巨大的性能消耗。为此,我们在Lambda function中对S3进行了缓存,做法是在Lambda里启动一个HTTP服务,代理所有FFmpeg对S3的读取请求。我们要做的是从S3中得到比FFmpeg请求更大的文件块,并将其缓存到内存中,避免反复对相同文件块的反复造成的开销。另外,由于视频处理整体是从前往后的,所以在FFmpeg处理一个块时,我们也会主动预取下一个数据块,以免出现CPU等待IO造成的性能损失。

  • FFmpeg的挑战

首先, 动态链接的FFmepg在lambda中运行不是很稳定,所以我们目前基本都是使用的静态链接。虽然文件尺寸更大,但仍在Lambda的限制之内。

另外,创建进程也可能出现问题。在Lambda里使用fork创建进程时,子进程会继承父进程的所有属性,这里面也包括了运行着我们代码的lambda沙箱,因此在子进程里常常会意外发现一些自己并未创建过的东西。在我们的实践中,在Python代码里fork的FFmpeg进程继承了沙箱中的某些文件描述符,特别是标准输入,这偶尔会造成一些bug,我们可以将文件描述符关闭来解决这些问题。另外,如果前后执行多个Lambda function,容器可能会被重用,这意味着之前创建的进程会一直保持到后续的执行过程。因此,lambda function即使在执行错误的情况下也要正确清理现场。

合并函数(Merge Function)

图:精简合并函数(Merge Function)工作流程图

当我们的文件经过map步骤处理后,形成小的ts文件块进入到精简合并操作步骤。其中,比较常用的就是生成MP4文件。在这个过程中,合并函数读入.ts的文件块,合并为MP4文件,然后上传到S3中。这里遇到的问题主要集中在文件输出上。

输出文件的挑战

相对于输入文件,输出的视频文件往往很大,lambda没有足够的临时空间存储。FFmpeg虽然支持FTP输出,但在输出MP4时,它输出大部分数据之后,还会跳转到文件头插入一些信息。这个时候我们就要引入S3的文件分段上传功能。我们在Lambda function中启动一个定制的FTP服务,类似适配器,将FTP输入适配到S3的文件分段上传功能中。由于S3不需要按顺序上传,每段大小也不需要相同,因此我们可以从第二段开始上传,最后再上传包含文件头的第一段。

连接函数(Concat Function)

图:连接函数(Concat Function)工作流程图

如上图所示,我们看一个输出DRM后的HLS格式文件的例子。图中,我们读入.ts的文件块,在reduce过程中进行加密,并将加密文件上传到S3中。我们将其合并以提高缓存效率,因为CDN中为列表中每个HLS只创建1个对象。这里的问题主要集中在执行方面。

执行的挑战

我们面临处理时间方面的挑战。举例说明,当我们的AES加密样本需要重新打包ts流,由于视频较长,无法在lambda限制的5分钟内完成。我们的解决方案是将lambda function进行菊链连接,这样如果前一个lambda function没有处理完,就把当前上传状态序列化给下一个lambda function继续处理。这里要注意的是,上传和下载速度不一定是对称的,当上传速度成为瓶颈时,需要限制下载速度。我们曾经遇到过下载数据过多而来不及上传导致的内存不足,所以当你进行类似的流式数据处理时,要加上一些背压(backpressure)。

下面我们讲一下部署的问题。

部署和CI/CD流水线

图:部署和CI/CD流水线

考虑到可重现性,我们通常选择在Docker容器中创建我们的lambda function。创建lambda function所用的git sha和脚本哈希值会成为zip文件名的一部分,这是我们对于不可变基础架构理念的一种探索。但我们生成的新zip文件实际上不会立即替代现有的lambda function,而会生成一个新版本。我们可以对新版本进行测试,确保它可正常工作。当我们足够自信代码没有问题的时候,我们会更新产品环境中的lambda function的别名,使它指向新版本,这是新代码才开始在产品环境中运行。虽然是老生常谈,我们感觉,Serverless中很棒的一点就是,它强制你把代码分拆成API定义良好的小片段,这也基本保证了你的代码一开始就是可测试的。

下面,我们对Lambda在使用中给一些建议:

  • 注意容器复用的问题。除了注意清理多余的进程以外,一般还要及时清理磁盘的临时空间或内存空间。我们还用到了S3高速缓存和FTP适配器,这些最终会绑定到一个端口上,如果你使用的静态端口,程序结束时要及时释放,或者像我们一样使用随机端口。
  • 日志问题。如果多进程出现问题,lambda沙盒提供了很多linux的实用工具可用来调试,比如spawn、ps、top,在你的函数里调用他们,日志会出现在CloudWatch里,就像一个虚拟机一样。
  • 运行时间可能变化。准备好重试超时的函数,尤其是网络受限的函数,这些函数可能只是恰巧超时而已。

成果展示

  • 使用情况统计数据。我们现在已处理15万小时的已转码视频,并拥有4亿次Lambda Function调用。
  • 成本显著降低。过去6个月,我们每个月平均支付6000美元的Lambda使用费,而在按需分配的EC2上拥有类似能力(2000计算核心、C4系列等)需要每月花费6万美元。
  • 速度大幅度提升。此前2小时的视频在EC2上转码需要4-6个小时,而在Lambda上则不超过10分钟。

几点思考

  • 局限性。一是lambda function有5分钟的运行时间限制,想生成比如4k 60fps的视频就很难完成。二是在解码视频文件中部的5秒文件块时,由于我们没有读取之前的帧,所以我们需要视频源格式支持高效的跳转,我们有大量的视频提供方以及工作室,还没有遇到过不能高效跳转的情况,但从理论上说,有可能存在这样的视频格式。三是Lambda上的CPU每小时的价格要高于EC2。四是解码开销。其实解码工作中很多步骤是重复的。比如,很多步骤都要解码2个音频流、1个视频流,读取文件头里的元数据等。
  • 未来计划。一是支持更多种输出格式。我们也很期待iOS和Android早日统一标准,这样我们提供一个视频源即可。二是提升对较小视频文件处理的效率。

Revvel团队简介

Revvel团队的前身是前Hulu CEO Jason Kilar和CTO Richard Tom创立的短视频创业团队Vessel。Verizon在2016年11月收购了Vessel团队来服务与它在数字媒体业务方面的战略。Revvel团队主要专注在下一代互联网电视产品和服务。它和雅虎和收购的AOL一起隶属于Verizon旗下新成立的名为“Oath”的新公司。Revvel总部位于旧金山,其在北京的研发团队位于清华科技园附近,专注在大数据平台,搜索和个性化推荐技术,移动和网页开发,以及多媒体编码技术等领域。

LiveVideoStack招募全职技术编辑和社区编辑

LiveVideoStack是专注在音视频、多媒体开发的技术社区,通过传播最新技术探索与应用实践,帮助技术人员成长,解决企业应用场景中的技术难题。如果你有意为音视频、多媒体开发领域发展做出贡献,欢迎成为LiveVideoStack社区编辑的一员。你可以翻译、投稿、采访、提供内容线索等。

0 人点赞