视频传输延迟,尤其是在某些互动社交环境中,会严重影响用户的体验。Instagram多年来以降低视频上传延迟为重要指标,实现了多种优化策略。本文来自Instagram媒体基础设施团队软件工程师Ryan Peterman。
文 / Ryan Peterman
译 / 蒋默邱泽
原文
https://instagram-engineering.com/video-upload-latency-improvements-at-instagram-bcf4b4c5520a
2013年6月,Instagram推出视频上传功能。当时系统功能很简单,为了摄取视频并用于播放。我们让Instagram app在客户端完成录制后将整段视频文件传至服务器,然后我们将视频转码为一组质量可控的视频版本,以确保视频文件可以在尽可能多的设备上播出。一旦所有视频都可用我们就“发布”供用户观看。
Instagram在社交环境中对上传时间反应尤为敏感,用户希望其他人可以尽快看到他们的视频故事和实时消息留言。出于这个原因上传延迟是Instagram一个非常重要的指标。多年来,我们开发出了多种减少延迟的策略。
让我们首先定义本文中的上传延迟,即服务器从客户端接收到所有视频码率信息,直至视频"可发布"或可供查看为止。
发布内容
减少视频上传延迟最简单的优化是在视频被发布前尽可能减少步骤。我们的想法是在所有视频版本都可用之前,先将可用的最高质量视频版本发布出去。其余视频可用于回放并非强制性,可以为带宽弱的用户提供较少卡顿的回放体验。这样可以有效降低处理低质量视频比高质量版本花费更多时间而造成的延迟,极大程度上提高了视频上传的成功率。因为我们只依赖一个版本而不是所有质量版本。
我们使用基于图形的存储系统来表示视频数据模型,所有视频版本"视频资源附加到父节点,这允许上传的视频被判断为媒体级别而不是视频版本级别。这种抽象实现了简单统一的发布逻辑。为了实现上述改进,我们将视频资源标记为“可发布的”,当我们通过视频处理服务收到回调信息时在视频资源中进行翻转布尔值。
通过让发布信号只依赖于一个版本,使得我们的视频处理模型更具弹性和灵活机制。如果通道在一段时间内无法生成可选编码,我们仍然可以准许发布视频,因为我们拥有最高质量版本。之后我们可以按需补充其余版本。
为了使发布信号只依赖于最高质量的版本,带宽受限的用户可能会体验次优的回放体验,直到其余版本完成为止。例如,只要最高质量的版本准备好了,视频就会发布,但是可能还有一些低质量的版本正在处理中,这些版本要到稍后才能发布。当带宽受限的用户最初观看视频时,如果只有最高质量的视频可用,他们可能会体验到相对较高的卡顿率与失帧率。而实际上在绝大多数情况下,编码的其余部分在强制的版本完成后也会迅速可用。
视频切片上传处理
另一种加快视频上传速度的方法是让客户端在视频录制完成后对其进行切片。一旦视频被切片,客户端就会把它们上传到服务器上,并给每个切片加上索引,以便后续可以按顺序重新组合。当服务器接收到视频切片时,并行地进行代码转换,从而节省时间。一旦所有切片都被转码,将其组合在一起,就可以进行播放。
在服务端,我们将每个视频处理流水线构建为有向非循环图。每个节点都是执行单元,每个边则代表两个节点间的依赖关系。每个节点在所有依赖项完成后执行运行。这里的示例是基本非分段通道简化处理视频过程:
在示例中大部分工作都发生在转码节点中。如果能并行化这部分,我们就可以显著减少上传延时。切片通道旨在通过为每个片段添加转码任务来并行化该部分。然后,添加一个拼接任务,将每个片段的视频帧连接起来,放在一个新的容器中。此拼接任务取决于通道每个片段任务,如下图:
在多数情况下切片上传只会减少上传延时,但质量权衡还有其他复杂性。例如:切片上传会增加通道复杂性。有一些质量指标会在转码时用于每个案例如SSIM。这些指标对我们每个细分受众群没有帮助。但是我们需要对所有片段的SSIM进行持续时间平均加权,以得出整个视频的SSIM。同样处理异常更加复杂,因为要处理非常多数量的计算单元。
此外通过切片视频,我们在通道引入另一个步骤将所有转码片段拼接在一起。这需要更多CPU处理,若是非切片则不必。重要问题是拼接步骤在最终系统中明显增加了I/O要求,每个片段在单个机器进行转码拼接时我们希望执行拼接处理。因此其他节点必须从网络下载所有片段这会大大增加I/O利用率。
在切片长度上我们会处理的非常小,这样可以并行完成更多任务。然而,由于设置节点对切片进行转码时存在一些必须开销,因此我们将切片长度保持在某个阈值以上。如果切片长度细分的太小,那么必然浪费资源。实际上将长度设置为大约几秒的时间对我们来说足以。
此外就上传延时而言,这并不总是全胜法子。随着初始视频缩短切片上传的好处也相应减少了。例如:下面描述了短视频和长视频的非分段视频处理和分段视频处理相对于时间的比较。对于这两者,我假设视频处理时间与视频长度成正比图。Δt 是切片和非切片通道执行之间的上传延时。与长视频相比,短视频的获胜几率要小得多:
总的来说,我们决定在上传过程的开始阶段根据产品和视频的长度对视频进行切片。某些视频产品(例如故事情节)已经强制规定了长度的最大值,这些最大值足够短,切片不需要特别复杂。对于像IGTV这样的视频产品,规定了最小长度,这样有足够的长度使得分片上传是有价值的。
透传
我们用来改进上传延迟和节省CPU利用率的另一种性能优化称为“透传”上传。在某些情况下,上传的媒体已经可以在大多数设备上播放了。如果是这样,我们可以完全跳过视频处理并将视频直接存储到数据模型中。这样不仅减少了延迟而且在这种情况下我们不需要对视频进行转码。
这是一个非常重要的检查步骤,以便进入Instagram的视频符合我们的播放标准。除了视频转码通道外,我们还添加了另一种通道用于检测传入视频的特定属性。例如:编解码器和码率,以确认是否视频符合透传的条件。如果视频的解码器支持较少,那么能够播放视频的Instagram用户就会更少。类似地,如果比特率过高,则通过网络加载用于回放的视频将花费太长时间。
一旦解码器和码率通过我们的筛选标准,我们就会使用内部工具检查视频文件;该工具报告拓扑、一致性和存储流一致性。如果视频文件不一致,尝试修复原视频文件会被启用。这个内部工具可以可靠的识别缓冲区溢出场景,使得我们不会向用户提供任何恶略质量文件。最后我们将修复后的视频与原始视音频一起转码并存储在我们的数据模型中:
由此产生的透传通道比转码通道完成得更迅速。我们检查确保视频版本的可播放性,因此系统允许将资源池视频回调并标记发布状态。这极大地改善了视频处理延时并提高了视频质量,因为转码是一个有损的过程。
这里的权衡也取决于我们设定的码率上限,其原因有几种:如果原始视频的码率太高并且执行透传上传,那么我们将存储比转码视频时更大的文件。此外,随着码率的增加视觉质量反而在减少,当这些内容在屏幕尺寸有限的移动设备上播放时则更加明显。而高码率的原始视频在透传版本与高质量转码版本比较时,获得的视觉质量优势较小。实际上,我们的比特率上限允许我们控制这些权衡。
总而言之,透传对于依赖延迟的视频产品尤其有用。
下一步呢?
多年来,Instagram的视频处理能力有了显著提高。这种基础设施以高效、可靠和高质量方式为全球用户提供了丰富的价值。我们也在致力于使上述程序更加高效简单。
随着视频的老化和与外界的互动,一个最有希望的领域是根据需要生成和清除编码。
例如,我们可能希望根据流行程度或视频的年龄等数据更改某个视频的表示形式。由于旧的内容没有那么多的观看,我们不可能存储所有的视频版本。取而代之的是,我们可以只为那些看起来很久以前的小流量设置一个视频版本的子集。如果一个旧视频突然流行起来,那么我们可能会根据需要重新生成这些版本。
设计一个系统来管理我们在每个视频生命周期中所拥有的视频表示形式涉及到许多有趣的挑战。我们应该选择使用什么信号?如何快速有效地管理和迭代现有的视频?