音视频生产关键指标:视频发布优化丨音视频工业实战

2022-11-29 18:08:11 浏览数 (1)

这个公众号会路线图式的遍历分享音视频技术音视频基础(完成)音视频工具(完成)音视频工程示例(完成)音视频工业实战(进行中)关注一下成本不高,错过干货损失不小 ↓↓↓


这篇文章是音视频工业实战主题专栏中关于视频发布流程的优化。视频发布流程是指视频录制和编辑完成后,对视频进行转码、上传的过程。在这个过程中,我们关注的指标包括发布成功率、发布耗时等。

  • 发布成功相关:
    • 发布成功率,用户在完成视频编辑后成功发布视频的比例。如果在发布的时候会做转码,则发布成功率就受到转码成功率和上传成功率的影响。
    • 转码成功率,客户端对视频进行转码的成功率。
    • 上传成功率,客户端上传视频的成功率。
  • 发布耗时相关:
    • 平均发布时长,视频发布成功平均耗时。如果在发布的时候会做转码,这个发布时长就包括转码时长和上传时长。
    • 平均转码时长,视频转码平均耗时。
    • 平均上传时长,视频上传平均耗时。

1、发布成功优化

发布的过程可能包括转码过程和上传过程,这两个阶段的成功率都会影响整体的发布成功率。

1.1、转码成功率优化

1.1.1、多种编解码方案兜底

在 iOS/Android 设备上进行编解码,有多种方案可以选择:

  • iOS 硬编解码
  • iOS 软编解码
  • Android Surface 硬编解码
  • Android ByteBuffer 硬编解码
  • Android 软编解码

根据机型的情况,我们通常会优先选择一种作为对应机型的首选编码方式,如果我们选择的某一种编码方式在编码的过程中遇到一些不可恢复的错误时,可以切到另外一种编码方式作为兜底来尝试提升转码成功率。比如,硬编码失败切软编码。

同理,如果在解码过程中遇到了错误,也可以使用相同的策略作为兜底。

1.1.2、GOP 粒度的解码重试

在解码过程中,可以将最近一个 GOP 暂存下来,在下一个 I 帧数据到来时清理。存储这个 GOP 序列主要是为了在解码器遇到解码错误的时候可以尝试先将解码器刷新(flush),然后将当前缓存的 GOP 序列塞给解码器做再次解码。这样可以把解码出错的重试控制在 GOP 的粒度。

如果重塞 GOP 后解码器还是失败,那就可以尝试上文中讲到的切到另外一种兜底解码方式上去做重试。

1.1.3、转码错误重试与监测

当然,对于转码报错,可以重试转码流程。

另外,需要上报转码错误的细分错误码,这样就能更好的定位转码失败的原因进行针对性的优化。

1.2、上传成功率优化

1.2.1、视频大文件分片上传

视频文件较大时,通常对应的上传耗时就较长,在上传的过程中如果出现网络抖动造成连接出现问题,就会直接导致此次上传失败,即使之前已经上传了很多数据也只能前功尽弃了。

将视频大文件进行分片上传,每个分片由于体积较小上传成功的概率会更高,即使出现某一个分片因为网络抖动而上传失败,也可以对该分片进行重试,不影响已经成功上传的分片,因此可以提高整体的上传成功率。

1.2.2、就近上传

就近上传是指能够根据上传者所处的地理位置,分配离上传者最近的存储中心进行上传,这样的上传链路会更优。

就近上传的能力带来最大的收益是减少了上传者到服务器的传输距离,这样一方面可以减少传输距离,提升上传速度;一方面可以提高稳定性,保证成功率。

1.2.3、预探测上传

预探测上传主要是一种针对各类网络错误场景进行优化的手段,例如网络连接失败、超时、DNS 劫持等。预探测上传的措施包括:

  • 使用 HTTPDNS 解析域名获取后端地址,防止 DNS 劫持问题;
  • 探测多个地域的连通性及上传速度,获取最优上传地域;
  • 接入云厂商的加速网络,提供可靠稳定的传输通道。
1.2.4、上传网络错误重试与监测

同样的,对于上传报错,可以重试上传流程。

另外,需要上报上传错误的细分错误码,这样就能更好的定位上传失败的原因进行针对性的优化。

2、发布耗时优化

如果在发布视频的时候会做转码,这个发布时长就包括转码时长和上传时长。

2.1、转码时长优化

转码可能会包括解封装、解码、特效模块渲染、编码、封装等流程。

2.1.1、减少不必要的转码

在下列场景中,可以减少不必要的转码:

  • 只更改音频,则视频不必转码。在转码之前的编辑流程如果用户的操作没有改变到视频,则我们在后续的转码过程,只需要重新编码音频,然后再做一次 mux 即可,不需要重新编码视频。
  • 只更改视频,则音频不必转码。如果用户的操作没有改变到音频,也同理。
  • 只裁剪尾部不必转码。如果用户在编辑的过程中只对视频的末尾部分进行了裁剪,也是可以不进行转码的,只需要在封装的过程中,把裁剪掉的数据去掉,重新 mux 一下就可以了。
  • 裁剪了开头部分,但第一帧为 GOP 开始的 IDR 帧,也不必转码。如果用户在编辑过程中对视频开头部分也进行了裁剪,但是裁剪后的第一帧是一个 GOP 开始的 IDR 帧,这时候也不必做转码,去掉裁去的数据,重新 mux 一下就好了。如果第一帧不是一个 GOP 开始的 IDR 帧,这时候就需要重新编码第一个 GOP,再做后续的 mux 工作。

减少了不必要的转码,可以大大降低转码耗时,同时也可以降低因转码引发的错误,从而提高转码成功率。

2.1.2、多线程优化

转码过程中解码、编码、解封装、封装环节都可以拆分出来支持异步多线程处理。

如果更进一步,可以在 GOP 的粒度支持多线程并发转码。这样可以提升转码速度,但是这种方案会容易出现多线程问题,需要仔细衡量。

2.1.3、转码方式适配

我们一般会同时提供硬件编码和软件编码的能力,我们可以根据设备类型以及在设备上提前做 Benchmark 的数据情况来决策在不同的机器上使用软编还是硬编,以及设置何种编码参数。这样我们可以根据当前的机型智能适配更优的转码方式来提升转码速度。

2.1.4 解码器复用池

在整个视频编辑的工作流中,抽帧模块、预览播放和转码模块都有可能需要使用解码器,由于操作对象大多情况下是同一个视频,所以解码器的参数几乎都是一致的。为了能够更快的获取解码器,可以实现一个解码器复用池来优化解码器的使用性能。

当外界请求解码器池的时候,解码器池会在池中寻找属性匹配(宽、高、H.264/H.265、硬解/软解等)并且处于空闲状态的解码器。如果当前没有符合条件的解码器实例,解码器池会创建解码器并设置解码器为非空闲状态。解码器池也会定时清理空闲的解码器实例,优化内存。

2.1.5 图像数据处理速度优化

libyuv 是 Google 开源的 YUV 图像处理库,实现对各种 YUV 和 RGB 数据之间的转换,包括数据转换、裁剪、缩放、旋转。它是跨平台的,支持在多种操作系统和 CPU 架构上进行编译运行,支持 SSE、AVX、NEON 等 SIMD 指令加速。

在视频发布过程中,某些模块中会需要用到各种 YUV 和 RGB 格式之间的转换,使用指令加速的 libyuv 替换手写的内存拷贝移动方法能缩短转换时间。

2.1.6 解码数据和纹理数据转换优化

在预览播放和导出模块中,用户应用了特效,因为特效渲染模块一般只接受纹理数据,所以我们需要将解码后数据(PixelBuffer)转换成纹理数据,传给特效模块进行渲染,在渲染流程后拿到的纹理数据又需要转回 PixelBuffer。

一开始我们使用的是 OpenGL 中的 glReadPixels,在研究过方案后在 Android 上我们选择了使用转换速度更快的 ImageReader 进行加速。

根据渲染后续流程中的需要的解码格式选择 RGBA 或者 YUV,可以在 ImageReader 构造时就指定渲染返回的 Image 对象的数据格式(ImageFormat 或是 PixelFormat 的一种),避免在 ImageReader 返回数据后再进行一次多余的转换。

ImageReader 创建后返回 Surface 对象,我们将经过特效模块后的纹理数据传给 Surface 进行渲染。ImageReader 就会通过同步(acquireLatestImage)和异步方式(监听 onImageAvailable 回调)获取 Image 对象。

2.2、上传时长优化

在客户端优化视频上传等待时长,一方面可以将传统的视频文件整体上传的方式优化为视频分段并发上传或者流水线上传的方式,一方面可以优化上传的传输协议。

在服务端也可以相应的做一些视频状态的优化来降低用户上传视频的等待时长。

2.2.1、转码状态依赖优化

当原始视频上传成功后即标记视频为可用,不必等其他版本转码完成,从而降低上传等待时长。观看端拉取视频时若对应码率视频转码完成就拉对应码率视频,未完成转码就拉原始视频。

下图是最简单的视频上传处理流程:

上传并转码后再分发的流程

下图是优化为只依赖一个版本的视频而非全部视频版本转码完成后的处理流程:

上传不依赖转码就分发的流程

这样的优化可以降低上传等待时长,但是也会造成一些弱网用户由于拉取高码率的视频导致更多的卡顿。在实际中绝大多数情况下,其余视频版本是能够迅速完成转码并达到可用来满足不同的用户。

2.2.2、视频分段并发上传和转码

在客户端录制完视频后,对视频进行分段然后并行上传到服务端可以提升上传速度。当然,这里的分段需要是可独立转码的切片,可以选择使用 FMP4、TS 等切片格式。

客户端将视频分段上传时,需要对分段标记好 index;服务端收到分段后并行的对各个分段进行转码来降低整体转码时长;当所有分段都转码完成后,服务端再按照 index 顺序将其组装起来,即可下发给消费端播放。

客户端分段并发上传流程

在服务端,将每个视频处理流水线构建为一个有向无循环图。每个节点都是执行单元,每个边则代表两个节点间的依赖关系。每个节点在所有依赖项完成后执行运行。下图表示以非分段的方式处理视频的大致流程:

非分段方式处理视频流程

上图中大部分工作都发生在转码节点中。如果能并行化这部分,我们就可以显著减少上传延时。分段通道旨在通过为每个片段添加转码任务来并行化该部分。然后,添加一个拼接任务,将每个片段的视频帧连接起来,放在一个新的容器中。此拼接任务取决于通道每个片段任务是否完成。如下图所示:

转码节点并行化流程

将视频分段上传和转码可以降低上传等待时长,但是也会带来一些其他消耗。比如:

  • 整个链路的处理复杂度会显著增加;
  • 转码质量的监控(PSNR、SSIM)处理流程会变得更复杂,需要对所有分段的质量分数进行加权平均来计算整个视频的质量分数;
  • 异常处理逻辑会更加复杂;
  • 各分段转码完成后需要进行合成,负责合成的节点就需要从其他分段转码的节点下载各分段,这样会明显增加系统 IO 请求。

对于分段长度,如果我们设置分段长度越小,则并发度就可以越高,但是随之而来的上述消耗也就更高,会带来资源的浪费。所以可以将分段长度保持在某个阈值以上,一般设置为几秒即可。

对视频进行分段上传并不适用于所有的场景。当原始视频时长越小,分段上传的收益也就越小;反之原始视频时长越大,分段上传的收益才会越大。下图展示了短视频和长视频的非分段视频处理和分段视频处理的耗时比较:

非分段与分段视频处理耗时对比

总的来讲,决定要不要做分段上传要取决于产品对视频时长的限制,以及在处理具体视频时的策略选择。

2.2.3、达标视频尽快分发

在某些情况下,上传的媒体已经可以在大多数设备上播放了。如果是这样,我们可以完全跳过视频转码并将视频直接标记为可分发。这样不仅减少了延迟,而且在这种情况下我们不需要对视频进行转码。

达标视频尽早分发流程

要实现尽快分发,最重要的是要对视频进行检测。可以根据码率、编码格式、封装格式等参数对视频进行筛选,因为码率过高会造成播放端卡顿过多,编码格式、封装格式不兼容会造成播放端无法播放。

当码率、编码格式、封装格式通过了筛选,可以进一步对视频质量进行检测,防止较差质量的视频被发放给用户。

视频质量检测流程

由此产生的透传通道比转码通道完成得更迅速,这极大地改善了视频处理时长并提高了视频质量,因为转码是一个有损的过程。

透传的优化也需要在其他方面做一些权衡,这里的权衡取决于我们设定的码率上限,其原因有几种:

  • 如果原始视频的码率太高并且执行不转码透传上传,那么我们将存储比转码视频时更大的文件;
  • 随着码率的增加视觉质量反而在降低,当这些内容在屏幕尺寸有限的移动设备上播放时则更加明显;
  • 高码率的原始视频在透传版本与高质量转码版本比较时,获得的视觉质量优势较小。

所以我们需要通过控制码率的上限来控制这些因素。

2.2.4、就近上传

在上文提到的 1.2.2、就近上传,除了能提升上传成功率,也能提升上传速度。

2.2.5、预探测上传

在上文提到的 1.2.3、预探测上传,除了能提升上传成功率,也能提升上传速度。

2.2.6、传输协议优化

我们还可以使用 QUIC、KCP 等传输协议进行定制开发和优化,对传统的传输协议进行替换来优化上传速度。

当然这要涉及到整个传输链路的协议改造,是个较大的工程。

2.2.7、视频秒传

对于较大的视频平台,通常会遇到一些视频发布者搬运他人视频的问题,这时候就会出现同一个视频在平台上被重复上传的问题。对于这种情况,我们可以实现视频秒传来避免平台已有的视频被重复上传。

视频秒传的大致逻辑是在客户端上传视频前使用 MD5、CRC 等算法计算视频数据的校验值,然后发送到服务端来检查服务端是否已经存在该视频,如果已经存在,则服务端只用拷贝一份视频即可,客户端也不用上传该视频,从而大大降低视频上传耗时。

2.2.8、视频预上传

视频预上传是指在用户选择视频后,但还未点击『发布/上传』按钮前,就预先在后台将视频上传,当用户后面确实点击『发布/上传』按钮时,视频上传任务已经部分或者全部完成了,从而降低用户感知的上传耗时。

当然,这种做法有一些投机因素,因为如果用户选择了视频后还对视频进行了编辑,或者用户最终没有点击『发布/上传』按钮,之前提早在后台上传视频就白做了。这时候如果视频还未上传完成,则需要取消上传任务;如果视频已经上传完成,则需要再通知服务端删除视频。

小结

上面我们从视频发布成功率和发布耗时两方面介绍了一些优化思路,视频发布是一个细致而漫长的过程,我们将在后续继续补充和完善相关的优化方案,大家可以关注我们的公众号,以便及时收到更新。

- 完 -

0 人点赞