写点什么

音视频终端引擎优化实践

发布于: 45 分钟前
音视频终端引擎优化实践

本文由百度智能云-视频云终端技术架构师 ——李明路,在百度开发者沙龙线上分享的演讲内容整理而成。内容从音视频终端引擎的概念出发,梳理了音视频终端引擎的发展和技术演进,重点介绍了音视频终端引擎的关键技术组件,分享了开发过程中的经验与实践。

文/ 李明路

整理/ 百度开发者中心

视频回放:https://developer.baidu.com/live.html?id=8


本次分享的主题是:音视频终端引擎优化实践。内容主要分为以下五个部分介绍:

1. 音视频终端引擎介绍

2. 视频云音视频终端引擎发展

3. 视频云音视频终端引擎面向企业级架构思考

4. 视频云音视频终端引擎关键技术组件

5. 视频云音视频终端引擎面向开发者提供服务


01 音视频终端引擎


什么是音视频终端引擎

定义:音视频终端引擎,是一款集成在移动或嵌入式设备中,使用软件定义的方法,扩展终端原有音视频处理能力,以高效地方式解决异构音视频场景下的归一化、抽象化、层次化的客户端问题。


注释:

  1. 归一化:指提炼不同音视频场景背后的主线逻辑。

  2. 抽象化:采用虚拟映射的方式,定义不同音视频实体与组件外部联系。

  3. 层次化:通过顶层架构的设计,实现不同音视频业务与接口内生关系。


音视频引擎终端引擎基本架构


首先看图片的顶端,这一条链路很好的解释了在上一章提到的归一化:音视频终端是从业务中迭代出来的,通过一些方法论,还要能够回归到业务当中。


在这条链路上,列举了几个常见的业务场景:点播、直播、短视频、实时音视频等。随着这些音视频场景的不断丰富,业务也会越来越复杂,能够提炼不同音视频场景背后的主线逻辑就显得十分重要。


接下来,我们重点分析音视频终端引擎架构。


音视频框架首先要立足移动端提供的系统能力,包括系统框架和硬件能力


如图,系统框架层有 iOS/Android 的一些多媒体框架、硬件的编解码、硬件的处理能力如 CPU、GPU、NPU 的处理模块,以及一些开源图像库。


系统框架层之上是第三方框架,如 FFmpeg、OpenSSL(加解密);在点播场景用的比较多的 Ijkplayer/Exoplayer;用于底层通讯的技术:双向、低延时的 WebRTC 技术,用于单向点播的 RTMP,目前比较火的 SRT 低延时方案;除此之外,还会有一些图像处理方面的框架如 GPUImage 等。


在此之上,就是一些跟场景相结合比较多的模块,这里大致列出了部分核心模块。


数据从多媒体采集模块出来,会经过一路或多路的混音混流(与实际场景相结合),然后过渡到多媒体编辑模块:当下短视频的一些能力(比如:转场、字幕效果添加等)都是通过多媒体编辑这个处理单元实现,再到后面的多媒体后处理模块:例如 AR 特效,以及一些比较好玩的互动能力等;内容生产完成后,我们会根据点播、直播或者短视频等场景的不同,采用不同协议进行分发。


再下面就是消费侧,这里可以直接读取数据,也可以间接读取数据作为缓存加快二次读取数据的载入。获取数据后会根据不同的封装格式,如 FLV、TS 或者是 MP4 等对数据进行解封装,再进行解码和渲染操作。


相比于其它移动端框架,音视频框架最特别的地方就是管线部分,因为音视频 SDK 的产品与其它产品不太一样,首先需要的是实时处理,数据流是不断在各个模块之间穿梭的,如何保证各个模块间的高效传输,这里提出了一个管线的概念。


那么,是不是有这样的基本架构后,就能解决现在音视频场景的能力呢?答案当然是否定的。事实上,这套架构中,在软件层面、硬件层面都或多或少面临着挑战。具体来说,大致可以分为以下几种:


1.平台能力不对齐

虽然现在很多的平台都提供了大量的音视频处理能力,但是这些平台的能力并不对齐。下面以苹果 iOS 系统的多媒体框架和 Android 多媒体框架处理 1080p 的高清视频举例说明。

  • iOS 系统多媒体框架:

拥有 AVAsset, AVCapture 接口,通过这些接口能够很快速获取到高分辨率视频的裸数据。

  • Android 系统多媒体架构:

缺乏像苹果这样的简单高效接口。通常需要两步解码,并且针对高分辨率的视频可能会解码失败。

2.编解码芯片适配难

编解码芯片复杂且多变,很多厂商会根据自己的平台/产品进行二次定制,导致音视频编解码芯片的标准是对齐的。这对于开发者和云厂商来说,适配的技术成本非常高。

3.CPU 到 GPU 性能开销处理难

虽然说现在很多的高端手机都能提供非常多的协处理器,能力也非常强。但是针对音视频场景,性能开销的处理却有一定挑战。比如视频的采集,通常是在 CPU 处理,但是若想做一些加速处理,需要在 GPU 进行。从 CPU 到 GPU 这种数据的转化协同,如果处理的方案不是特别好,会导致性能的开销非常大。

4. OpenGL 图像处理框架挑战频频

OpenGL 是比较老旧图像系统框架,目前遇到了非常大的挑战。苹果在 ARM11 处理器上已提出自研的 Metal 处理框架,并把 OpenGL 图像处理框架标记为未来可废弃。若 OpenGL 在未来废弃,势必会影响目前大多数主流产品的稳定性。

音视频终端引擎新挑战

简单介绍了音视频 SDK 的框架,接下来介绍目前框架遇到一些问题和挑战。

1. 更高的音画标准

目前很多业务场景,其实都在追求更多的新玩法。会追求更大的分辨率,还有一些更高的刷新率,甚至是更极致的体验。比如:有些场景像点播或短视频,720p 的分辨率已经不能满足场景的使用,甚至在一些运动场景,30fps 的刷新率也已经没办法满足场景的开发。


但音视频 SDK 很大程度上会受制于平台的能力,由于平台具有很多差异性,以及相关硬件没有完全普及,所以导致音视频 SDK 在发展过程当中,其遇到很多的问题。


另外多模块间的数据交互到模块间的数据交互也是一个巨大挑战,如何保证数据无损处理和高效传递?

2. 跨屏的音画场景


除了刚才说音视频自身的高清技术标准的升级外,音视频终端也在慢慢的摸索一些沉浸式场景体验,这也催生了一些新的平台和新的交互方式。


比如说一些带屏幕的智能音箱,用户可以在这种类型的设备上就会有一些新的需求:更好的场景渲染、更好的通话质量、更低的播放时延。


还有目前比较流行的数字人:如何在户外大屏幕,甚至在一些专有设备上以更高精度的方式呈现出来?


这些音视频终端数据跨屏,迫使音视频终端引擎支持更多的硬件平台、更多的特性适配、更好的人机交互。但受限于设备兼容性,如何保证数据的高效计算和稳定传输?这些都是音视频终端引擎需要面对的问题。


02 视频云音视频终端引擎发展


经过上一章的介绍,相信大家对音视频终端引擎有一定的了解。在本章将梳理百度视频云做音视频引擎的发展过程,并挑选几个重要节点介绍具体的应用方案。

视频云音视频终端引擎发展路线图

百度智能云在较早的时候就提出过音视频解决方案,下图描述了主要的发展历程。

阶段 1OneSDK 音视频解决方案  

提供推拉流能力,在千播大战和直播答题等场景有广泛的应用。

阶段 2:一站式解决方案

随着现在短视频、互动直播、以及其他实时音视频场景的不断的丰富。百度提供了更全面的一站式的解决方案,其中包括了特效、编辑和连麦的能力。

阶段 3:Pipeline 设计

随着开发者对音视频场景的不断了解和深入,也提出了一些更高的要求标准。如:低时延、高清化。百度视频云通过重构的 Pipeline 方案,将底层能力通过管线进一步开放出来。

阶段 4:研发范式

如何让开发者更高效的利用这些管线?百度视频云也提供了一些研发范式。通过研发范式,使得管线可编程。除此之外,也提供一些简单应用的组件,能够让开发者更快速、更高效的将开放能力与业务相结合。

阶段 5:SDKEngine

目前,SDKEngine 也还在持续技术演进,主要是研究通用引擎技术的落地,以更好满足跨平台、跨终端的音视频需求。

一站式解决方案介绍

一站式的解决方案,是以自身业务发展为出发点,将业务按照一定模块进行划分,并以模块化方式进行对外输出。


从上图可以看到,在最早的一站式解决方案中,会提供非常多的组件与模块。比如:录制模块、直播模块、互动模块、特效模块等,并且这些模块之间存在一定的依赖关系。


这种方案对于想快速接入音视频场景的开发者来说是十分的高效,能够帮助开发者从 0 到 1 快速建设音视频场景,并提供轻量级、一站式的接口解决方案。


但事实上,客户侧的需求也在不断地发生变化。如:业务需要做推流或者一些更底层地调试以及获得底层能力的开放服务,这需要客户通过提工单的方式告知解决方案厂商,而厂商又需要评估、迭代,将这些能力逐步的开放,这对开发者的体验并不是很友好。因此,接口与业务解耦是引擎的下一步发展方向。

Pipeline 设计方案介绍

Pipeline 设计,站在融合的视角,以流水线的方式融合异构业务架构,整合音视频底层能力,复用音视频模块,以实时音视频引擎为基座,插件化对外输出。


从上图可以看到,Pipeline 设计将之前比较高级的业务接口剔除,并开放更底层的接口。以录制模块为例:将录制模块中,与业务相关的逻辑进行抽离,而提供像 Capture 这样的采集组件。通过 Pipeline 的设计,逐步的把底层能力逐渐开放出来。


但是在开放过程当中,如能能够让开发者更好的使用底层技术?以及如何在 Pipeline 上做一些更加灵活的定制?这催生了我们新的终端引擎。

研发范式方案介绍

针对开发者在 Pipeline 设计方案上的一些使用问题, 我们期待终端引擎具备可编程、可自制的能力。

所以,百度视频云以企业级架构为出发点,结合平台中间件和业务低代码为设计思想,对外输出能力。

在之前的设计中,终端引擎都是对接 APP,而研发范式方案里,对接的是开发者。这其实是一个设计理念的升级:将 SDKEngine 泛化为研发范式,开发者可以根据自身情况,按需使用或进行二次开发。


应用层面 ,将常见的组件进行封装,如:相机组件、连麦组件、推流组件等,开发者能够快速、插拔式地使用这些组件。

平台中间层面,实现了架构层面的治理。针对不同的音视频场景,可以通过构建方案、灵活自动化地打包相应的产品能力。

与此同时,底层的引擎能力也在逐渐地开放出来,如:针对弱网的优化、传输能力等。


03 视频云音视频终端引擎面向企业级架构思考


在上一章介绍了视频云音视频终端引擎的发展历程,在整个过程中也得出了一些经验。以下是针对实践得出的一些经验:

去中心化的设计理念


背景:音视频场景越来越复杂,专业程度也越来越高,随着音视频开发者逐渐发展,以业务为驱动的传统设计理念无法满足发者对新场景的一些场景的定义。


去中心化的含义:

>> 以业务为中心转变为以服务为前提

这就意味着,云厂商要站在开发者的角度,去审视终端引擎的发展。该如何提供哪些能力?每个能力又该如何进行自我演进?这是一个特别好的反馈机制。

>> 封闭架构设计转变为协同共赢

如前面章节提到的研发范式这种解决方案,它实际上是将更多的接口与底层能力开放给开发者。这也是希望能够和开发者们更好的协同,并更好的服务一些新的场景。


去中心化的设计理念:

1. 单一责任法则:将业务场景模块化。

2. 开闭法则:即高度自治,不影响其他模块。

模块质量经过厂商严格的内部测试,解决开发者的后顾之忧,并且每个模块是可插拔的 ,一旦出现问题,可以快速剔除。

3. 接口可替换:接口设计兼容并蓄。

目前音视频识别场景的复杂程度远超云厂商的想象,开发者对模块或者说接口的需求是个性化的。这就需要音视频终端引擎的模块、接口是可以独立输出的,并且设计兼容并蓄,以减少开发者在使用过程中的一些负担。

4. 接口隔离:接口易于理解。

5. 依赖反转:面向接口编程,易用。即:要求接口是好上手,能够快速使用的,甚至在二次开发和进一步封装的时候都是没有任何负担的。

被集成到可编程


历经音视频终端引擎的发展,我们认为,SDK 可集成是基本能力,具备可编程的能力才能够更好服务于开发者。这样能够将客户侧业务与终端引擎解耦,提供标准组件,支持可编程的范式开发。


如上图示例:原有的直播 Demo,在设计层面会提供很多复杂的 UI 与业务逻辑,而在代码层面,会包含很多业务的 SDK,这种设计接入简单,但是能力不足,无法拆分细化场景,影响开发者对 SDK 产品的辨识度。


经过 B 端设计与业务重构,将原有的直播 Demo 拆分为几个业务场景:标准直播场景、互动直播场景、低延时直播场景等,通过研发范式,将终端引擎能力释放出来。并且每个模块之间的内聚性强,节省开发者的使用成本。


03 关键技术组件介绍


数据管线组件介绍

数据传递由数据管线负责,它能够让各个组件之间的数据传递实现高完全解耦。以上图的直播推流场景为例,介绍数据管线是如何实现数据传递的高完全解耦。


直播推流场景按照较粗的分类维度,可大致分为以下几类:相机类、美颜类、推流类。


相机类会使用到一些底层组件,比如:采集组件(开启摄像头、麦克风等),采集组件会将数据通过接口回调的形式传送给相机类,那么相机类的数据又如何传输给美颜类或者其他类呢?


首先是制定数据协议,主要解决的是最基本的模块间数据的高效、稳定的传递。我们提供了 AVOutput 模块和 AVInput 的数据传输接收的协议,单纯的去记录和管理这条链条上的各个的组件,我们称之为 target。


然后通过 Dispatcher 的机制,分发从生产端上报的视频帧,通过视频帧不断的传递到各个链路的 target 当中,而每个 target 实现 AVInput 其中的协议方法。例如 frame 跟 type 两个函数,frame 就是从 raiseFrame Output 传递下来的数据;type 主要是做一些音视频的音频跟视频的区分。


除此之外我们还支持一些二进制场景的分发,主要是为了配合像直播这种对数据有分发要求的场景做了一些协议的升级。在链条的最末端,可以看到我们也实现 AVControl,跟之前不太一样是我们制定了一个控制协议,这个控制协议主要是为了控制数据的流入和流出。


为什么要做这个事情呢?我们知道音视频 SDK 最核心的就是数据在不断的传递,如果说某个模块出现异常,数据没有一种机制能保护它,可能会导致整个 SDK 的运行出现不稳定的情况。比如在直播场景分发的时候,我们发现网络有抖动,此时我们可以调整发送的速率、速度等。


这里简单的画了一下我们的数据流向。


一个是推的方式,就是直接从相机这种模块采集数据,直接着向后面的某个模块去传递。


一个是拉的方式,主要是指读取本地文件或者说是间接的获取数据,比如从网络读取数据首先需要将数据读下来,然后再传递到各个模块。


这里其实相对于之前说了 GPU 在异步线程的一些处理,我们也做了一些兼容和保护,就是防止异步处理时对象被释放的情况发生。所以说我们基本上也是沿用了 GPUImage 协议简单的这种思想,然后在此基础上又增加了一些像控制协议的实现机制,让整个链路变得可控。


在这一步中,控制协议的加入是十分必要的。我们知道,终端音视频的场景,大多时候都是实时处理的,而预处理的功能模块不断叠加,给终端性能带来了很大的挑战,加入控制协议,可以将这些控制交给开发者管理,通过及时调整参数,保证数据的高效传输。

特效组件介绍

特效组件会有提供很多接口,特效模块通常是典型的 PaaS 结构,它上面存在多种模型,而且模型之间是可以进行插拔;它还有另外一个特点就是耗资源。那么如何在音视频 SDK 中将这个模块更好的运用起来,去对外提供能力呢?


我们这里以人脸特效的高级美颜接口为例,高级美颜中涉及到的特征点非常多,像大眼、瘦脸、下巴等,而且这些特征点并不是通过一次迭代或是一个模型就能解决的,它可能会涉及到多次的迭代和多种模型的组合叠加。这样就会带来一个问题,在集成特效模块的时候,如果这些能力都是不断变化的,对于模块的使用来说,就存在一个不安全不稳定的因素。那么我们该如何把这个问题解决,或者说屏蔽掉呢?


这里提供了一个概念:代理层。


首先在调用能力的时候,不直接去调用,而是把这些能力做进行抽象、封装,然后这些封装的模型,用来关联后面的一些不同的算法。因为开发者在使用 SDK 的时候,不一定按照厂商提供的所有东西来集成,可能只使用其中部分能力,这样就有可能会导致一些特效的 SDK 存在版本不一致。


如果没有这个代理层,当出现版本不一致的情况,对于上层来说可能就会出现大量接口的调整和修改,会比较耗时耗力。不过我们做代理的话,可能就给屏蔽上层接口的稳定性,然后通过我们的模型跟一些抽象对象,可以去驱动不同的 AR 模块的版本。


通过上图,我们可以更加直观的了解:


相机模块和特效模块之间的数据通过数据管线的方式进行连接,当数据进入特效模块后,根据开发者传入的不同参数,组件会通过该特征去关联相关的人像算法,以能够更快和更有保障的隔离一些问题的发生。


同时这些数据还会传输给端侧进行端侧推理,目前百度视频云音视频终端引擎是利用百度的 Paddle lite 进行的端侧推理。通过核心性能和指标的检测,实现图的优化,最终通过渲染、数据转换,形成最终的特效效果。

渲染组件介绍

渲染组件其实非常好理解:给定点线面信息及纹理信息,将这些信息生成一张或者多张位图的过程。它也是音视频终端引擎的关键技术之一,是用户感知的最后一公里,随着场景化丰富,(比如:HDR 视频的合成与播放、VR 虚拟现实等)渲染模块成为数据交互和处理的汇聚点。


百度视频云目前主要还是使用 OpenGL 这个组件,也对这个组件做了一些优化与实践,通过这些优化以提升渲染组件的跨平台易用性。


实际上,iOS 的离屏渲染和 Android 的离屏渲染在底层上有很大的差异,并且这些差异导致在封装和适配上有很多技术细节的不同。下面简单介绍一下这些技术细节实现的不同。

1. ES 3.0

OpenGL 的 3.0 给开发者提供了很多的特性。如他新增了 VAO 的概念,而 VAO 在处理多 Buffer 的情况下,效率是更高的。

而针对不支持 VAO 的平台,我们也模拟了 VAO 的概念,这使得跨平台的渲染组件可以更加高效的支持在各个终端上。

2. 基于 OpenGL ES3.0 渲染组件局部框架:

首先将传统 VBO 的概念通过 ES3.0 封装到 VAO 的数据格式里,接下来在 ES2.0 的基础上,通过模拟实现能力对齐。

Shader 拆分:OpenGL 是可通过 Shader 语言编程的,所以将 Shader 进行拆分。如:将位置信息、顶点信息进一步拆分出来,并提供更简单、抽象的接口,减少大家的使用成本。在未来,也会逐步释放 Shader 的一些底层开发方式,让开发者更好的适配一些高级方法。


基于此,基本可解决跨平台上对于渲染组件的一些基本诉求。

RTC 组件介绍

RTC,对于实时类的业务提出了更高的技术标准,更低的端到端时延以模拟更自然的交互。它的使用场景也十分广,比如:互动连麦、直播带货、超低延时播放等。


百度视频云团队目前是提供了两个 RTC 的组件能力。一个是连麦组件 RTCRoom,另一个是针对超低时延场景的 RTCPlayer 播放器。并针对这两个组件,也做了技术的优化。


1. 传输质量的优化

信令 Over UDP  更快的通道,时序处理。

RTC 的信号传输是双向的,而传统的信令传输方案是基于 TCP 开展,为了达到更低时延的效果,采用更快的通道:UDP。并且 UDP 在传输过程中是会出现丢包的,并不是按照顺序传输,所以还需要在时序上做一些处理和控制,防止出现不合预期的内容。

2. 传输链路分析与优化

  • 传输链路调优,识别不同网络下,上行拥塞控制策略。

在用户使用 RCT 组件时,网络环境可能会实时变化,针对这种实时变化的场景,RTC 组件需要快速识别出来,并需要经过一些策略使得对下行接收侧的影响降到最低。具体流程可参照上图。


概括来说就包括:

基于发送侧拥塞控制,部分码率预估处理流程;上行分级传输,下行平滑渲染。

这其中,码率预估是整个 RTC 传输链路中的十分重要环节,如果上行传输质量无法保证,下行的再多优化都是徒劳。


因此,在整个方案中,也会基于不同的场景,如:丢包场景,延时场景做出大量优化。


针对丢包场景,采用不同分级策略。出现常见的丢包情况(带宽无限制,只是丢包情况出现),需要调整策略使用更高的码率去传输,并配合服务端的重传机制,让抖动的数据传输尽快恢复。


出现高级丢包的情况(如:4G 切 3g, 进地铁等场景),是会出现长时间的带宽延时,这个时候需要在在码率预估环节做出精准预估,不让它变化起伏明显,保证上行的传输。


下行平滑渲染也很关键。针对下行丢包的场景,如何在能够快速渲染,使得延时变低?这需要制定一系列的传输质量标准,精简非必要的 RTC, 以适应不同的网络。


05 视频云音视频终端引擎——面向开发者提供服务


  • 面向行业用户

目前百度视频云音视频终端引擎服务广大行业用户。包括金融行业、教育行业、传媒行业等,针对不同场景,准入机制及要求都是不一样的。这也保证了不同的开发者在使用我们产品中能够各取所需。

  • 面向普通开发者

https://cloud.baidu.com/doc/Developer/index.html

普通开发者可以通过 SDK 中心了解视频云终端引擎的能力,也可以接入自己的产品中去体验。


以上是老师的全部分享内容。有疑问欢迎在评论区提出。



发布于: 45 分钟前阅读数: 3
用户头像

关注百度开发者中心,收获一手技术干货。 2018.11.12 加入

汇聚百度所有对外开放技术、平台和服务资源,提供全方位支持,助力开发者加速成功,实现开发者、消费者和百度三方共赢。https://developer.baidu.com/

评论

发布
暂无评论
音视频终端引擎优化实践