写点什么

优酷移动端弹幕穿人架构设计与工程实战总结

  • 2022 年 6 月 06 日
  • 本文字数:3751 字

    阅读完需:约 12 分钟

弹幕穿人方案主要分为两类:“云端离线人体分割+端侧渲染”和“移动端端侧实时人体分割+端侧渲染”。在这里我们分别简称为云端方案和端侧方案。本系列文章主要聚焦在优酷端侧弹幕穿人的技术实战上,主要包括优酷跨平台多媒体渲染引擎 OPR 简介、优酷端侧弹幕穿人架构设计与工程实战、淘系端智能 PixelAI 移动端实时人像分割技术、以及优酷弹幕渲染及弹幕穿人渲染技术的方方面面。

一、背景

1、弹幕穿人的价值弹幕是目前用户观影的一个标配,弹幕能使用户在观影过程中与其他用户实时互动,提升了观影体验。但弹幕也会遮挡视频画面,也会给用户带来一些困扰。弹幕穿人是视频内容与弹幕内容争夺用户视觉焦点的一种平衡,能够让用户在消费弹幕的同时,依然可以观看到视频中涉及人物等的关键画面区域。在有弹幕穿人效果的时候,用户有更强的意愿打开更多行弹幕,弹幕穿人对用户弹幕开启行数有一定促进作用,从而证明弹幕穿人能产生正向的价值。2、端侧弹幕穿人的优势相较于云端方案需要提前针对某个剧生产、部署、下发,在介质有变化时需要重新生产等等不利因素,以及动则上百万的生产、储存及带宽成本,不适用于直播等实时场景。端侧弹幕穿人则完全依赖于移动端自身的算力,最大优势是实时、低成本,并且利于大规模铺量。3、端侧弹幕穿人的技术要求及难点 3.1)穿人效果要准确无论是云端还是端侧,穿人效果都要求准确。否则如果不达标,mask 与人物有错位、弹幕渲染频繁抖动等等现象,这些都是不可接受的。3.2)性能要达标我们要在端侧保证弹幕穿人效果和性能,不能因为端侧弹幕穿人而导致 CPU/GPU/内存等资源占用的飙升,或者导致弹幕本身渲染卡顿,更不能影响到视频或音频渲染的效果和性能。否则就是本末倒置了。相较于云端方案,端侧方案的挑战更大,主要表现在如下几个方面:(1)算力有限端侧方案只能利用移动端自身的 CPU 或 GPU 来完成链路上所有操作。相较于云端方案,端侧的算力非常有限。移动端、边缘端和云端的 GPU 算力的介绍可以参考这篇文章《GPU 深度报告,三大巨头,十四个国内玩家一文看懂》。(2)模型小由于端侧的限制,我们不可能用大模型,这给检测的准确性也带来更大的挑战。(3)实时性弹幕穿人需要跟视频画面实时匹配。由于视频帧率一般在 25~60 之间,为了达到好的穿人效果,我们对整个端侧弹幕穿人链路的实时性要求是非常高的。端侧穿人链路上所有操作,包括视频画面获取、人像分割检测、弹幕穿人效果的实现及渲染上屏,所有这些操作加起来要求在 20ms 以内时间完成(超过 20ms 就基本能感知到弹幕的卡顿了),这样才能达到一个好的效果。否则穿人效果就会有滞后感、穿人效果与画面不匹配,甚至会对弹幕本身渲染的流畅度和视频渲染的流畅度都产生严重影响。以上这些因素都会给端侧弹幕穿人项目带来巨大的挑战。


在淘系算法同学的大力支持下,PixelAI 很好地完成了移动端实时人像分割的任务,给优酷端侧弹幕穿人功能的上线铺量打下了坚实的基础。另外,我们在工程侧也做了大量的优化(优化手段后面会有介绍),使市面上机型的大规模覆盖成为了现实。

二、整体架构设计

1、架构图 OPR(OPen Render 的缩写)作为优酷主客全端的渲染引擎,主要负责 audio、video 和弹幕的渲染。另外,我们也在 OPR 中引入了端智能引擎。由于 OPR 天生离 audio、video 和弹幕的 raw 数据最近,我们可以直接在 OPR 里就去消费这些数据,产生我们所需的端智能结果,给业务带来更大的价值。我们不需要把数据再一层层地回传给更高的层次去做处理去做消费处理。所以我们在 OPR 里融入一层端智能层,直接拿数据就可以处理端侧智能相关操作,然后把结果在 OPR 层展示、上报或者传给上层去消费,这样做的效率是最高的!


我们首先看一下整个 OPR 的架构图:



OPR 从上到下分为 4 个层次:(1)接入层 OPR 是跨平台的,我们支持 Android(Android 手机和 OTT 设备)、iOS(iPhone、iPad、Mac)和 Windows(DX9、DX11、DX12)平台。我们抽象出对应平台的接口,供业务层调用,来完成相应数据元素的渲染。(2)引擎层引擎层,按功能分为 Video Engine,Audio Engine 和 Danmaku Engine,分别对应 video、audio 和弹幕的引擎。(3.1)渲染层除了基本的 Video、Audio 和弹幕渲染功能之外,OPR 也包括相应的后处理能力,比如视频的帧享相关后处理、特效广告、色盲、zoom 等等能力,音频的倍速、均衡器等能力,弹幕的节奏弹幕、流光弹幕、心动弹幕等特效能力。(3.2)端智能层主要包括人脸相关能力、语音能力、超分能力等,下层是其对应的支撑库。(4)平台层对各平台渲染接口的封装,包括 2d/3d 的 opengl es、metal、directx 和 audio 的 opensl、audioqueue、directsound 等。2、流程图


端侧弹幕穿人流程如下:



(1)video 正常解码、渲染流程中,我们去实时截取当前视频画面帧;(2)送给端智能模块,去做人像分割,得到人体分割 mask 数据;(3)mask 作为单通道纹理上传至 GPU;(4)mask 数据上传至 GPU 之后,我们做一次 5x5 的 gaussian blur,这样边缘处边缘处更加平滑;(5)把 blur 处理之后的纹理作为 alpha 去跟弹幕纹理做 blend;(6)有穿透效果的弹幕 surface 叠加在视频 surface 之后,就能得到如上丝滑的弹幕穿人效果了。

三、工程实战

1、技术选型及实践人像分割能力,外部开源的 opencv 和集团内的 mnn 都有这个能力。但是我们在移动端实测之后得的结论是,性能和效果都达不到我们端侧弹幕穿人的要求。后来我们了解到,集团内部已经有一个强大的端上引擎 PixelAI,有强大的人脸等处理能力,已经在淘宝直播等场景上线。我们快速实测了一下,的确在效果和性能都能满足我们的需求。所以我们最终定型 PixelAI 来作为我们端智能的主引擎来针对端侧弹幕穿人来实时做人体分割。2、性能优化 1.1)帧画面高效获取(1)正常 video 渲染流程如下:



video 正常上屏流程是这样的,video 解码后的数据(硬解或软解),通过 aliplayer 调到 opr 的接口。video_player->video_engine->video_layer->video_pipeline,后面对接一个个后处理 filters 去完成各个后处理功能,最后上屏。(2)用户截图场景下,帧画面的获取流程如下:



针对用户截图场景,由于截图场景不需要上屏,所以我们自然而然想到如下流程,在所有的 filter 之后加一个 snapshot 的 filter,这个 filter 完成数据渲染到一个纹理,然后拷贝出来即可。针对用户截图这种场景,上述流程没问题任何问题。我们在加上 snapshot filter 之后重新走一遍渲染流程,截图完成后卸载 snapshot filter,整个流程耗时若干毫秒。针对用户主动截图这个场景,我们不会因为这若干毫秒感知到性能存在问题问题。但是,当我们把整个链路应用到端侧弹幕穿人这个场景下,我们发现每一帧截图的这个若干毫秒的时间,就是一个致命的性能问题了。如果不压缩时间的话,留给算法的处理时间就太少了,无法达到上线的标准。


(3)端侧弹幕穿人场景,帧画面获取流程如下



针对这种需要频繁实时截帧的场景,我们设计了如上链路。我们在所有 filter 的末端增加一路 quick_snapshot filter,这个 filter 有两路渲染 command。一路 command 按正常流程去渲染、正常上屏,不做任何额外处理。同时,另一路 command 把数据渲染到纹理,然后再拷贝出来。这样,两路相当于并行起来。在每一帧渲染过程中,不会有任何多余的创建和销毁 snapshot filter 的过程,完全不会对正常渲染链路造成任何影响。同时,新加的一路 command 使截帧的效率最大化,很好地实时完成了频繁截帧的任务。经过实测,我们的截帧性能提升若干倍,为算法去做实时人体分割节省了大量的时间。1.2)避免在 cpu 中完成耗时操作 PixelAI 有大模型和小模型,为了使底层的 MNN 不做频繁的初始化操作,大小模型要求的帧数据尺寸是固定的。如果大于或小于算法要求的尺寸,PixelAI 会先使用 OpenCV 去做 scale。了解到这些 scale 操作全部在 CPU 中完成,会造成大量的耗时,所以我们针对大小模型,直接在前面的截帧操作中,通过纹理大小的变化,我们就可以在 GPU 里完成了帧画面的 scale,使截帧输出的尺寸就是 PixelAI 大小模型所要求的尺寸。这样就避免了使用 OpenCV 在 CPU 中做 scale 锁消耗的大量时间了。1.3)异步调用模型从算法同学了解到,PixelAI 人像分割过程是一个原子操作,对应的底层 MNN tensor 等运算不可中端。一般来说,在 GPU 和高端手机的移动端运算比较快,但也有那种耗时比较久的场景。算法侧我们保证在一个固定的时间内返回结果。如果算法耗时较久不返回数据,我们在这里死等的话,就会导致弹幕渲染卡顿、穿人效果的错位等异常 case,这是不可接受的。为了达到最好的性能和效果,我们必须要实现一个异步调用模型。在正常时间内返回结果的,直接使用 mask 数据上屏。在正常时间没有返回的,我们丢弃掉当前帧的 mask 数据。如果是若干帧以内没有返回,我们都使用上一次检测的数据;为了避免这种场景下穿人效果的错位,超过若干帧就直接上屏,没有穿人效果了。这也是在工程上对弹幕穿人渲染效果做出的一个均衡处理了。3、效果优化要做到好的穿人效果,我们在渲染层面也做了大量的优化,参见文章《优酷弹幕穿人渲染技术揭秘》。4、测试结论(1)算法测试结果,参见文章《PixelAI 移动端实时人像分割》(2)优酷整体测试结果测试结论:我们并没有因为引入端侧弹幕穿人带来大量的性能损耗。

四、展望

移动端端智能是未来一个趋势,移动端弹幕穿人是端智能一个很好的应用场景。后续我们会在 OPR 里衍生出更多的端智能应用场景,给优酷用户的观影带来更好的用户体验。


更多文娱相关技术解读,移步➡️【阿里巴巴文娱技术 公众号】

用户头像

还未添加个人签名 2021.06.09 加入

还未添加个人简介

评论

发布
暂无评论
优酷移动端弹幕穿人架构设计与工程实战总结_技术_阿里巴巴文娱技术_InfoQ写作社区