用于高带宽应用的 WebRTC 数据通道

jen*_*nsk 1 webrtc rtcdatachannel webrtc-android

我想通过 WebRTC 数据通道发送单向流数据,并且正在寻找最佳配置选项(高带宽、低延迟/抖动)和其他人在此类应用程序中使用预期比特率的经验。

我的测试程序发送 2k 块,bufferedAmountLowThreshold 事件回调为 2k,并再次调用 send,直到 bufferedAmount 超过 16k。在 Chrome 中使用它,我在 LAN 上实现了 ~135Mbit/s,从/到远程连接实现了 ~20Mbit/s,两端都有 100Mbit/s WAN 连接。

这里的限制因素是什么?

如何查看数据是否真正直接点对点传输,或者是否使用了 TURN 服务器?

我的最终应用程序将使用 Android 上的 google-webrtc 库 - 我只使用 JS 进行原型设计。我可以在库中设置选项以加快比特率,而在官方 JS API 中无法做到吗?

Len*_*ahl 9

影响吞吐量的变量有很多,而且很大程度上取决于您如何衡量它。但我将列出一些我为增加 WebRTC 数据通道的吞吐量而调整的内容。

免责声明:我没有为 libwebrtc 做这些调整,而是为我自己的 WebRTC 数据通道库RAWRTC做这些调整,顺便说一句,它也为 Android 编译。但是,两者都在下面使用相同的 SCTP 库,都使用一些 OpenSSL-ish 库和 UDP 套接字,因此所有这些都应该适用于 libwebrtc。

请注意,使用usrsctp 的WebRTC 数据通道实现在同一台机器上执行时通常受 CPU 限制,因此在测试时请记住这一点。使用 RAWRTC 的默认设置,我可以在 i7 5820k 上达到 ~520 Mbit/s。根据我自己的测试,Chrom(e|ium) 和 Firefox 在默认设置下都能够达到 ~350 Mbit/s。

好的,让我们深入调整......

UDP 发送/接收缓冲区大小

默认情况下,Linux 中 UDP 套接字的默认发送/接收缓冲区非常小。如果可以,您可能需要调整它。

DTLS 密码套件

大多数 Android 设备都有 ARM 处理器,没有硬件 AES 支持。ChaCha20 通常在软件方面表现更好,因此您可能更喜欢它。

(这是RAWRTC默认协商的,所以我没有将其包含在最终结果中。)

SCTP 发送/接收缓冲区大小

libwebrtc 使用的 SCTP 堆栈 usrsctp 的默认发送/接收窗口大小为 256 KiB,这对于以中等延迟实现高吞吐量来说太小了。理论最大吞吐量受限于mbits = (window / (rtt_ms / 1000)) / 131072。因此,使用 的默认窗口window=262144和相当适中的 RTT rtt_ms=20,您最终将获得 100 Mbit/s 的理论最大值。

实际最大值低于...实际上,远低于理论最大值(参见我的测试结果)。这可能是 usrsctp 堆栈中的一个错误(请参阅sctplab/usrsctp#245)。

Firefox 中的缓冲区大小已增加(请参阅错误 1051685),但在 Chrom(e|ium) 使用的libwebrtc 中未增加。

发布版本

优化级别 3 有所作为(废话!)。

消息大小

您可能想要发送 256 KiB 大小的消息。

除非你需要支持 Chrome < ??? (抱歉,我目前不知道它在哪里着陆......),那么最大消息大小为 64 KiB(请参阅issue 7774)。

除非您还需要支持 Firefox < 56,在这种情况下,最大消息大小为 16 KiB(请参阅错误 979417)。

它还取决于您在暂停发送之前发送了多少(即缓冲区的高水位线),以及您在缓冲区排空后继续发送的时间(即缓冲区的低水位线)。我的测试表明,以1 MiB的高水位为目标并设置256 KiB的低水位会产生足够的吞吐量。

这减少了 API 调用量并可以提高吞吐量。

最终结果

在 RAWRTC 上使用具有默认设置的优化级别 3 使我达到约 600 Mbit/s。

基于此,将 SCTP 和 UDP 缓冲区大小增加到 4 MiB 使我进一步提高到 ~700 Mbit/s,一个 CPU 内核处于 100% 负载。

然而,我相信仍有改进的空间,但它不太可能是低悬的。


如何查看数据是否真正直接点对点传输,或者是否使用了 TURN 服务器?

about:webrtc在 Firefox 或chrome://webrtc-internalsChrom(e|ium) 中打开并查找所选的 ICE 候选对。或者使用 Wireshark。