🍉 加载中...


WebRTC Stats 统计信息中值得关注的数据

11 minute read

通过对等连接传输的音频、视频或数据包可能会丢失,并且会出现不同程度的网络延迟。

使用什么统计数据?

  • 往返时间(RTT)和抖动(Jitter)

往返时间(Round Trip Time)测量发送请求和获得响应所需的时间,它是网络速度的良好指标,越低越好。 RTT 可以从 remoteinbound-rtp 报告(音频和视频)以及 candidate-pair 报告(基于 STUN 请求)中收集。

抖动(Jitter)测量数据包延迟的变化,过高的值和频繁的变化是诊断质量问题的良好指标。为了有好的音视频质量,网络应该尽可能的稳定。可以在出站流的 remote-inbound-rtp 报告以及入站流的 inbound-rtp 报告中收集抖动。

  • 发送和接收的字节数

bytesSentbytesReceived 属性允许实时测量传入和传出比特率。为此,您需要获取 2 个连续报告来减去这些值,然后除以从时间戳属性获取的该间隔的持续时间。

  • 质量限制原因

QualityLimitationReason 属性给出了传出流可能被降级的原因。如果获得的值不等于 none ,这意味着某些因素限制了您的传出流低于所请求质量的 100%。这可能是您的带宽问题(值等于 bandwidth )、请求过多的计算机或设备问题(值等于 cpu )或其他原因(值等于 other )。

QualityLimitationReason Chrome 最近引入的新字段,可用于检测任何 CPU 问题。掌握有关 CPU 的信息对于检测不良质量的原因非常重要,带宽并不总是原因。

  • 丢包(packetLost)、NACK、FIR、PLI

丢包(packetLost) 属性允许了解为传入和传出流传输的数据包是否已在网络中的某个位置丢失。需要注意的是,并不是有数据包丢失,质量感知就会下降。WebRTC 有一些内部机制来重传数据包丢失,例如 Opus 中使用的前向性纠错技术 (FEC)。但是,获得数据包丢失的信息是有关网络质量的良好信息。丢失的数据包可以在传入流的 inbound-rtp 报告中收集,并在传出流的 remote-inbound-rtp 中收集。

nackCount(否定确认)属性是数据包丢失的一个很好的指示器,因为它指示 WebRTC 堆栈要求接收者重新传输数据包的次数,以及相反,接收者要求您的堆栈重新传输数据包的次数。一个好的建议是降低比特率,以防收件人向您发送 nack。

firCount(完整帧内请求)属性是另一个指标。当接收到 FIR 消息时,它表明接收者不再能够正确呈现流,因此应该发送完整的帧,而不仅仅是增量。

pliCount(图片丢失指示)属性与 firCount 非常相似。当接收者丢失一个全帧时,他发送一条 PLI 消息来指示发送者重新发送一个全帧。

这些指标告诉应用程序有关网络损耗的质量。在大多数情况下,降低比特率应该有助于快速恢复更好的情况。不要忘记,WebRTC 堆栈会自动根据质量调整传出流。

Nack、FIR 和 PLI 仅适用于视频流,可以在 inbound-rtp 报告和 outbound-rtp 报告中收集这些属性。

NACK 是接收者发送的显式协议消息,用于报告由于某种原因(例如,通过网络传输的数据接收时有错误或无法读取),必须重新发送特定的预期信号。使用 NACK 消息的协议通常能够报告消息被 NACK 的原因。

如何应对质量问题?

  • 显示质量指标

大多数应用程序首先显示质量指示器,以向用户表明质量不好。大多数情况,是说明网络不好。事实上,这是用户体验反应,告知用户“嘿,别担心,这一切都在控制之中……”。

大多数情况下,该指标基于平均意见分数 (MOS),该分数介于 1 到 4.5 之间,可反映通话质量(音频部分)。当MOS低于3.6时,感知开始从好转为坏。当分数在一段时间内低于3时,用户需要付出一些额外的努力来倾听和理解说话者。最后,当分数低于 2 时,对话就不再容易理解。

计算 MOS 可以通过计算 R 值来实现,然后将其转换为分数。为此,您需要获取丢包百分比、RTT 和抖动。然后计算方法可以在这里找到:Monitoring VoIP call using Improved simple E-model
  • 更改比特率

应用程序有可能控制或以不同的方式限制堆栈使用的比特率,这可以在调用之前通过修改 SDP 并添加新行来完成。

# For Chrome/Safari
b=AS:500" //limit to 500kbits

# For Firefox
b=TIAS:500000

在通话过程中,可以通过使用 RTCRTPSender 上的函数 setParameters() 来 “动态” 更改所使用的带宽,如下所示:

 1const sender = peerConnection.getSenders()[0];
 2
 3// For compatibility reason
 4const parameters = sender.getParameters();
 5if (!parameters.encodings) {
 6  parameters.encodings = [{}];
 7}
 8// Limit to 500kbps
 9parameters.encodings[0].maxBitrate = 500000;
10sender.setParameters(parameters).then(()=> {
11  // In case of success
12  console.log("limiter set");
13}).catch(err => {
14  // In case of error
15  console.error(err);
16});
17
18// To remove the limiter, property maxBitrate should be removed
19delete parameters.encodings[0].maxBitrate;
20sender.setParameters(parameters).then(() => {
21// In case of success
22  console.log("limiter removed");
23}).catch(err => {
24  // In case of error
25  console.error(err);
26})

另一种可能性是使用参数 `scaleResolutionDownBy`` 来缩小分辨率。例如,如果值为 2,则视频大小为原始大小的 1/4。但正如您将看到的,降低比特率会降低视频质量以适应给定的比特率。

更改比特率或缩小分辨率来限制带宽(双方)是减少一段时间内网络拥塞的一种方法。一旦统计数据看起来再次良好,就可以消除此限制。

  • 显示较少的视频 (SFU)

当在显示大量参与者视频的会议中时,如果应用程序检测到 CPU 存在问题(使用 qualityLimitationReason 属性时),应用程序可以决定渲染较少的视频(例如,同时只渲染 4 个,而不是渲染 6 个视频)。

CPU 限制随时可能出现,但最常见的是 CPU 功率较低的平板电脑。但是,如果您在调用期间在计算中打开了多个应用程序,其中一个应用程序占用了大量 CPU,则可能会遇到同样的问题:这将影响流的编码和解码。

计算示例

本地发送的音频数据

使用 type===‘audio’ 的 outbound 数据进行计算

  • SendBits = outbountRtp.bytesSent * 8 ,(一个字节有8位)
  • SendBitrate = (outbountRtp.bytesSent * 8 - (prevOutbountRtp.SendBits || 0)) / timeGap
  • packetsLost = remoteInboundRtp.packetsLost
  • roundTripTime = remoteInboundRtp.roundTripTime

本地发送的视频数据

使用 type===‘video’ 的outbound数据进行计算

  • 码率计算方法同上
  • SendFrame = outbountRtp.framesSent
  • 发送帧率(和码率的计算方式类似):
1SendFrameRate =
2      +(
3        (outboundRtp.framesSent - (prevStats.SendFrame || 0)) /
4        this.timeGap
5      ).toFixed(3) * 1000
  • packetsLost = remoteInboundRtp.packetsLost
  • roundTripTime = remoteInboundRtp.roundTripTime
  • packetLossRate(丢包率):
1  const pl = Math.abs(remoteInboundRtp.packetsLost - prevStats.packetsLost)
2  const pr = Math.abs(outboundRtp.packetsSent - prevStats.packetsSent)
3  PacketLossRate = +(pl / (pl + pr)).toFixed(3)

远端传过来的音频数据

通过 inboundRtp 来计算,和本地音频流一致。

远端传过来的视频数据

  • 渲染帧率
1  result.RenderFrameRate =
2      +(
3        (stats.rtp.framesDecoded - (prevStats.framesDecoded || 0)) /
4        this.timeGap
5      ).toFixed(3) * 1000

番外

弱网模拟工具: network emulator、facebook ATC、QNET弱网测试工具、Network Link Conditioner

推荐阅读:

来源

内容节选自:https://www.webrtc-developers.com/webrtc-statistics-using-getstats/#round-trip-time-and-jitter