light-rtc: 理念与实践 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
VideoCloudTech
V2EX    WebRTC

light-rtc: 理念与实践

  •  
  •   VideoCloudTech 2021-03-01 11:23:02 +08:00 1847 次点击
    是一个创建于 1684 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在与同行交流过程中,发现很多同行对 WebRTC 改动太多,导致无法升级 WebRTC 版本。而 WebRTC 开源社区的快速迭代,让他们感到欣喜又焦虑:开源社区的迭代效果,是不是超过了他们对 WebRTC 的优化效果?我们针对特定场景优化 WebRTC 时,怎么紧跟 WebRTC 开源社区通用的优化?

    理念

    简言之,把 WebRTC 作为 Framework 使用,而不是 Library,即:WebRTC 仓库轻量化,核心模块插件化。

    详细的,WebRTC 作为 Framework 串联核心模块;核心模块既可以以插件形式使用我们的实现,也可以 Fallback 到 WebRTC 的默认实现。目的是减少 WebRTC 冲突的可能性,提高升级 WebRTC 的敏捷性。

    目标:一年升级一次 WebRTC,一次花费一个人月。

    架构

    模块拆解

    file WebRTC 的核心模块,包括:

    音频

    • ADM 采集、APM 、ACM 编码;
    • NetEQ 与解码、AM 、ADM 渲染;

    视频

    • 采集、编码;
    • JB 、解码、渲染;

    通用

    • RTP 打包与解包、FEC 生成与恢复、CC 与 Pacer 、ICE 、SDP 信令等。

    WebRTC 在长期的演进中,API 已经具备了作为 Framework 的大部分能力。红色的核心模块,已经基本可以插件化,如下面的 API: file

    仓库管理

    file light-rtc 作为 WebRTC 仓库,我们需要保留两个 Remote,一个是 Alibaba,一个是 Google 。升级 WebRTC 时,我们从 Google 上 Pull 最新代码, 解决冲突,然后 Push 到 Alibaba 。

    对插件化的模块,我们需要放到单独的仓库 lrtc-plugin 里,这样有两个好处:

    1. 对 light-rtc 仓库改动少,减少与 Google 冲突的可能性;
    2. 更重要的,让每个开发同学,在每次改动前,更主动、更有意识的思考,放到哪个仓库更合适,否则容易惯性思维,直接改动 light-rtc 。

    对 lrtc-plugin 依赖的第三方库,也应该以单独的仓库存在,并保留两个 Remote,比如 Opus,这样,即使修改了 Opus 源码,仍然可以像升级 light-rtc 一样,方便的单独升级 Opus 版本。

    模块

    Codec

    音频编解码器、视频编解码器,是我们最常优化的部分之一:

    • 新的编码工( AV1/SCC/ROI 等)优化视频质量和带宽;
    • 分辨率自适应,使不同能力(编码能力、发送带宽等)的发送端,发送不同分辨率的码流;
    • Simulcast,为不同能力(解码能力、显示能力、接收带宽等)的接收端,提供不同分辨率码流;
    • SVC,提供时域 /空域分层;
    • 新的视频解码实现,规避 Mac 硬解卡死等问题;
    • 新的音频编码器,适配商用接收端; …… file

    这部分插件化是相对简单的,只需要实现自己的 [Video|Audio][Encoder|Decoder]Factory 即可。以 Simulcast 为例,在自己实现的 VideoEncoderFactory 里,先用 WebRTC 原始的 VideoEncoderFactory,创建多个 Encoder 对象,然后封装到一个 Simulcast Encoder 里。

    ADM

    很可惜,ADM(Audio Device Module)没有提供检测设备插拔的功能,需要增加 Callback 接口。

    另外,虽然 WebRTC 支持样本数量的监控,但是当前只用于打印日志,如果想在此基础上做更多事情(如:发现采集样本为 0 时,重启采集),则单独做一个 AudioSampleMoniter 的类,比较有利于扩展。 file ADM 是一个适配难点,相信是困扰 RTC 同行的共同难题。不同操作系统、不同机型,都可能有不一样的问题。例如:

    • Mac 3.5mm 耳机插拔时,偶尔崩溃;
    • Mac 获取的设备 ID 在插拔后发生变化,不能做持久化;
    • 联想 X1 电脑,多次插拔后,整个 Audio 后台服务失效;
    • 某些 Windows 机型采集不到声音;
    • 某些手机采音权限问题; ……

    这些修改大部分属于 Bugfix,参考“Bugfix”章节。

    APM

    APM(Audio Processing Module)可能是 light-rtc 相对难处理的部分。

    APM 与 NetEQ 一起,可能是 WebRTC 核心模块中,开源价值最大的部分。在我对 APM 有限的认知里,对 APM 常见的优化可能有:

    • 混音后的远端信号,做滤波 /均衡处理。这是业界不少音频算法的必要条件;
    • 利用 Android 手机特性,优化 AECM,尤其是 Double Talk 时的效果;
    • 啸叫检测与抑制;
    • 利用机型特性,优化 AGC,提高语音音量; ……

    下图是 WebRTC APM 内部模块的数据流程图: file 从图中可以看出,APM 其实也为插件化做了准备,但是只在近端信号的尾部、远端信号的头部。从 APM 构造函数上也可以看出来: file 滤波 /均衡,可以方便的实现一个 CustomProcessing 的 render_pre_processor 。

    其他的优化,遵循轻量化 /插件化的理念,没有现成的插件接口,我们可以创造新的插件接口,如啸叫抑制,以及 AECM 优化的部分算法。

    但 APM 仍然会有很多没办法插件化的,只能修改 light-rtc 仓库,如 AECM Double Talk 优化等。

    AM

    AM(Audio Mixer)的插件化,可以在不修改 light-rtc 的基础上,玩出很多花样:

    • 播放本地文件;
    • 借助语音检测算法,优化语音排序,从而选出更准确的语音做混音;
    • Mono 变成 Stereo,借助 HRTF,可以在多方同时说话时提高说话人辨识度和可懂度;
    • 对 RTP 方案的回放,倍速回放时变速不变调; …… file

    FEC

    FEC(Forward Error Correction),常见的修改:

    • 调参,如冗余度、MaxFrames 、Table 类型,包括固定参数和动态自适应调参两类,已有的插件接口 WebRTC::FecControllerFactoryInterface 即可满足;
    • RSFEC,需要创造新的插件接口;
    • Opus Inband FEC 。WebRTC 动态配置的 Opus FEC 参数,不能很好的解决弱网时声音卡顿问题。这时,一个办法是把 Opus 独立成仓库,直接修改 Opus 编码器。 file

    CC

    CC(Congestion Control),包含两个方面,一个是 CC 算法本身,一个是 CC 关联模块。

    算法本身,可以用不同的算法实现,如 WebRTC 默认的 goog_cc,也可以是 BBR,甚至是满足 WebRTC::NetworkControllerFactoryInterface 接口的外部插件。

    关联模块:

    • 带宽分配:不同场景可能不一样,如视频会议里,需要“保音频、保屏幕”。可以通过 rtc::BitrateAllocationStrategy 实现插件化。

    file

    • Pacer 调优:对于屏幕内容,I 帧往往非常大,WebRTC 的 2.5 倍的发送带宽,会导致巨大的首帧时间。具体解法见仁见智。 ……

    VideoRender

    Android 、iOS 、Mac,WebRTC 都提供了默认的实现,虽然有少量 Bug,但是基本满足需求。

    Windows 平台,早期 WebRTC 提供了 D3D 的实现,最新版已经剔除,我们可以在 lrtc-plugin 仓库实现自己的 D3D,或者其他的渲染,如 QT OpenGL 。

    VideoProcess

    WebRTC 并没有提供视频前处理(如:美颜)、后处理(如:超分辨率)的接口,但是我们完全可以像 rtc::BitrateAllocationStrategy 一样,创造 VideoProcessInterface 接口, 并在 lrtc-plugin 仓库里实现。 file 让 VideoProcessInterface 同时继承 Sink 和 Source 接口,可以方便的把多个对象串联起来。

    其他 & Bugfix

    其他核心模块,如 JitterBuffer 、ICE 等,目前接触的主要是 Bugfix,还没有发现自己定制重写的必要。

    Bugfix,往往只能修改 light-rtc 仓库。一方面,是尽量把 Bugfix 内聚成函数,减少对已有代码的修改;另一方面,尽量把 Bugfix 贡献到开源社区(Issue Tracker),既为开源社区做了贡献,也彻底避免了升级的冲突。

    贡献到开源社区,往往比想象的要复杂,但也更能锻炼人。在特定场景,往往只用了 WebRTC 一部分能力,如视频 JitterBuffer,一个 Bugfix 可能只考虑到了 H264,贡献到开源社区时,则需要同时兼顾 VP8/VP9,甚至是将来的 AV1 。在这个过程中,Google 工程师会在 Code Review 中与你亲密切磋,其实是非常好的锻炼机会,进一步提高对 WebRTC 的认识。

    参考

    WebRTC m74 源码

    RSFEC:

    • WebRTC RSFEC 详解和剖析;
    • ARTP 技术探秘之:WebRTC 中支持 RS FEC 。 (以上两篇文章之后将会在本号推送)

    CC

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2434 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 15:33 PVG 23:33 LAX 08:33 JFK 11:33
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86