这个系列文章我们来介绍一位海外工程师如何探索 WebRTC 音视频技术,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍计算真实的端到端往返时间 (RTT)。
—— 来自公众号“关键帧Keyframe”的分享
随着 WebRTC 网络的发展,你需要一些方法来确保其性能最优。WebRTC 提供了一个低级的 getStats方法,但遗憾的是,在该 API 变得实用之前,需要进行大量的数据聚合和分析。一个很好的例子是,当两个 WebRTC 终端之间有一个或多个选择性转发单元 (SFU) 来中继流量时,如何计算两者之间真实的端到端延迟。早在模拟电话时代,国际电信联盟 (ITU) 就已将说话人和听者之间的延迟识别为通话质量的关键因素。当前的统计指标将这一指标封装在一个名为往返时间 (RTT) 的指标中。
如何获取端到端 RTT?除了 getStats,你还需要一些额外的工具。ObserveRTC 是一个开源项目,旨在帮助进行聚合和分析,以解决此类问题。Balázs Kreith 是该项目的联合创始人和主要维护者,拥有博士学位,且是一名 WebRTC 软件工程师。他撰写了一篇博文,讨论如何使用类似 ObserveRTC 的系统计算端到端 RTT。随后,他还提供了一个基于 Docker 的简单教程,用于在 SFU 环境中计算端到端 RTT,你可以在几分钟内运行起来。我询问了在级联 SFU 环境中这种情况将如何运作,他也为此制作了一个示例!继续阅读,了解有关 RTT、端到端延迟以及相关教程的更多详细信息。

从事实时通信系统工作是一件很有趣的事情。具有挑战性。令人沮丧。令人疲惫不堪。但 mostly Fun!其中一个最大的挑战(也是导致沮丧的主要原因)是为会议质量提供一个可靠的指标。我认为我可以自信地说,对于工程师而言,回答“会议 X 的质量如何?”这个问题就像让一个盲人告诉你昨天天空是否多云一样困难。因为他们没有看到。
我想我可以自信地说,工程师永远无法直接看到他们所工作的系统提供的绝大多数通话——客户可能不喜欢有工程师参加每次通话。然而,我们必须提供一种可靠的方法来衡量和改进服务质量。尽管对于不同计算应使用的指标存在诸多争议,但有一个指标几乎总是在列表中:往返时间 (RTT),它代表连接延迟。
我们可以从客户端 JavaScript 获取 RTT,但这并不意味着我们获得了从一个客户端到另一个客户端的真实端到端 RTT。如果我们使用媒体服务器(如 MCU 或 SFU),那么浏览器统计提供的 RTT 是客户端与媒体服务器之间的 RTT——而不是另一个用户。当媒体服务器相互连接且用户未连接到相同的媒体服务器时,情况变得更加复杂。在这种情况下,我们如何计算端到端 RTT?
在本文中,我将讨论如何在一对一直连、客户端 – SFU 以及级联 SFU 环境中使用 ObserveRTC 开源工具提取、聚合和表示 RTT。
1、WebRTC getStats 评述
WebRTC 的统计 API(通常称为 getStats)是 WebRTC 对等连接所公开的各种指标集合。如果你有睡眠问题,它也非常适合作为睡前读物。客户端 WebRTC 应用发送或接收的每个 MediaStreamTrack 都会经过 RTCPeerConnection,因此可以通过 stats 获取发送或接收的数据包数量等指标。
了解可用 stats 的最简单方法是加载 chrome://webrtc-internals 并查看所有下拉菜单。括号 [ ] 中的项是计算得出的。其他所有项均源自 stats 报告。

pc1.getStats().then(reports=>reports.forEach(report=>{if(report.id.includes('RTCRemoteInboundRtpVideoStream'))console.log(report.roundTripTime)}));
由于你的对等连接无需离开你的电脑,你应该会看到 0.001 或其他非常小的值作为响应。
1.2、大多数 stats 需要一些聚合
获取这些 stats 很简单。但要生成有意义的指标通常并非易事。有意义的指标通常需要对 stats 进行某种聚合。例如,要计算轨道的发送比特率,我们首先需要通过对等连接或发送方 stats 过滤出相应的轨道。从该分组中,我们可以提取与轨道对应的 RTP 源产生的总字节数。然后要获取实际的发送速率,我们需要减去每个报告之间的差值并除以报告之间的时间段。
回到 webrtc.github.io/samples/src/content/peerconnection/pc1/,你可以粘贴以下代码以查看其工作原理:
let pc1Stats, ts, lastTs, bs, lastBs, bitrate;
let statsInterval = setInterval(async ()=>{
// the sample sets pc1 to null on hangup
if(!pc1 || pc1.connectionState !== 'connected'){
clearInterval(statsInterval);
return;
}
// We know we want to look at pc1
pc1Stats = await pc1.getStats();
pc1Stats.forEach(stats => {
// note: we know pc1 only has a single outbound video stream here , but isnot always be the case
if (stats.id.includes('RTCOutboundRTPVideoStream')) {
bs = stats.bytesSent;
ts = stats.timestamp;
bitrate = ((bs-lastBs)*8)/((ts-lastTs)/1000);
console.log(bitrate);
lastBs = bs;
lastTs = ts;
}
});
}, 1000);
这应该会显示一个与你在 chrome://webrtc-internals 中看到的类似的比特率。
除了迭代 stats 和等待承诺兑现外,你几乎总是需要浏览每个 stats 报告。在这个非常简化的示例中,我们只监控了一个视频轨道,但通常你需要对多个轨道进行额外的过滤。只要跟踪各种 ID 以关联各种报告,就有许多方法可以实现这一点。例如,如果你想知道特定轨道的编解码器,你需要列出发送方 stats,从发送方 stats 中获取 codecId和 trackIdentifier,然后在下一次迭代中进行识别。如果你想了解用于传输的选定 ICE 候选对的本地 ICE 候选,你需要了解选定候选对的 id,然后获取本地候选对的 id,之后你可以筛选出要使用的本地候选对。依此类推。
2、当存在 SFU 时的端到端 RTT
往返时间 (RTT) 是实时通信中最重要的指标之一。RTT 意味着两个客户端之间的延迟,这是对感知质量进行任何估算的关键因素。
当两个参与者通过直接的对等连接相互连接时,两个客户端之间的实际 RTT 即为 WebRTC stats 提供的 RTT。

然而,在现代 WebRTC 系统中,更典型的用例是使用选择性转发单元 (SFU) 或多点控制单元 (MCU) 服务器在用户之间路由流。每个客户端都会连接到该服务器。在这种情况下,从每个客户端的 getStats获取的 stats 仅描述客户端与服务器之间的连接。在下面的例子中,Alice 的真实端到端 RTT 是 Alice 到 SFU 的 RTT 加上 SFU 到 Bob 的 RTT 之和。

2.1、级联 SFU
为了使情况更加有趣,SFU 可能会相互连接。每个客户端连接到离他们最近的 SFU,然后 SFU 之间相互通信以中继流量(也称为级联 SFU)。

在这种情况下,我们还需要考虑 SFU 之间的额外 RTT。有人可能会想出某种复杂的数据通道 ping 机制来实现这一点。然而,如果你已经在收集 SFU 的 RTC stats(你应该这样做),你只需聚合每个客户端测量的 RTT 并将其添加到 SFU 到 SFU 的 RTT 中即可。一旦所有这些数据被集中到一个地方,你还需要为正确的通话筛选数据,然后为正确的传出 RTP 流筛选数据。
那么如何做到这一切呢?回答这些棘手的 stats 聚合问题是促使我启动 ObserveRTC 项目的原因之一。
3、ObserveRTC —— 一个用于 WebRTC stats 的开源工具
ObserveRTC 是一个开源的 WebRTC 监控工具。ObserveRTC 从各种监控器收集 stats——用于浏览器的 client-monitor-js 和用于基于 Node.js 的 SFU 的 sfu-monitor-js——并将这些 stats 发送到观察者实例进行聚合和存储协调。

3.1、为 getStats 添加一个模式
client-monitor 就像是一个 getStats 的包装器,好处是它使用了一个分层模式来跟踪 stats 之间的关系,而不是原始的 getStats 报告。例如,通过这种模式,你可以从 outbound-rtp跳转到对应的 remote-inbound-rtp,或者检索 trackId,或者获取传输信息等。
for (const outboundRtp of monitor.storage.outboundRtps()) {
const { packetsSent, ssrc } = outboundRtp.stats;
const trackId = outboundRtp.getTrackId();
const remoteInboundRtp = outboundRtp.getRemoteInboundRtp();
const { roundTripTime } = remoteInboundRtp.stats;
console.log(`Track: ${trackId} ssrc: ${ssrc} RTT: ${roundTripTime}`);
if (1.0 < roundTripTime) {
// we have a round trip time higher than 1s
}
}
查看完整的导航图以获取完整的模式参考。
3.2、聚合统计信息
观察者接收来自各种监控器的样本。然后:
- 识别会议 / 通话
- 创建事件(通话开始、通话结束、客户端加入、客户端离开等)
- 匹配客户端的 inbound-rtp 会话与远程客户端的 outbound-rtp 会话
- 匹配 SFU 的 RTP 会话与浏览器端客户端的 inbound 和 outbound-rtp 会话。
- 匹配内部 SFU 会话
这些数据被输出到一系列报告中,这些报告通过揭示与其他客户端的关系扩展了客户端提供的样本。例如,一个入站视频轨道报告基于一个入站视频样本,但扩展了从发送该流的远程客户端获取的 stats 数据。此外,每个报告都有一个 callId,有助于识别客户端所在的会议 / 通话。
了解如何使用 ObserveRTC 的最佳方式是实践操作。为此,我们创建了 full-stack-example 仓库。在 full-stack-example 中,观察者将报告保存到 MongoDB。你可以在这里找到使用 Python Jupyter 笔记本查询 MongoDB 的示例(在下一节中会进行解释)。
3.3、了解更多
该项目包含许多组件,但 Docker 镜像使其易于入门。深入探讨 ObserveRTC 超出了本文的范围,但你可以在 Introduction – ObserveRTC 中了解更多。本文的参考内容将主要关注如何在存在 SFU 的情况下使用 ObserveRTC 解决端到端 RTT 问题。
4、使用 ObserveRTC 计算端到端 RTT
本节将提供一个使用 ObserveRTC 计算端到端往返时间 (RTT) 的分步教程。
5、示例测试环境
我们使用 ObserveRTC full-stack 示例仓库来设置测试环境。测试环境中包含一个简单的 react 应用,该应用包含一个 WebRTC 浏览器客户端,集成了 client-monitor-js。SFU 基于 mediasoup,有其自己的 sfu-monitor-js。观察者从 observer-config 文件夹获取配置,该配置使其将报告发送到 mongodb。为了模拟延迟,我们将使用 Docker 流量控制工具 docker-tc,并通过环境变量设置延迟值。
6、简单测试环境设置教程
首先下载仓库:
git clonehttps://github.com/ObserveRTC/full-stack-examples.git
cdfull-stack-examples
在继续之前,你需要知道本地网络接口可以访问 docker 中运行的服务的 IP 地址。SFU 必须向客户端宣布一个 IP,使客户端能够访问它。你可以通过在 macOS 或 Linux 上输入 ifconfig或在 Windows 上输入 ipconfig来获取该 IP 地址。对于本地测试,可以使用你的局域网地址,例如 10.10.0.50。
现在我们已经知道这个 IP 地址,让我们通过以下命令启动我们的监控 webrtc 堆栈:
SFU_ANNOUNCED_IP={YOUR_LOCAL_IP}docker-compose up
该命令启动:
- my-webrtc-app:一个单一的 react 浏览器侧 WebRTC 应用
- mediasoup-sfu:my-webrtc-app 加入的一个 SFU
- observer:监听由 mediasoup-sfu 和 my-webrtc-app 提供的样本的服务
- mongodb:用于观察者报告的数据库
- mongo-express:用于查询 mongo 的 UI。
- notebooks:用于分析已保存报告的 Jupyter 笔记本
my-webrtc-app 和 mediasoup-sfu 分别配置并启动 client-monitor-js 和 sfu-monitor-js。
启动后,在两个浏览器标签页中访问 http://localhost:9000 并观看自己。我们建议使用 Chrome,因为它允许在回环上进行 ICE(这里有关于 Firefox 的问题的详细讨论)。
roomId和 userId 是自动生成的。等待几分钟让所有内容启动。同时,如果你查看 Docker 服务的日志,你会看到观察者检测到通话,并通知发现入站和出站轨道以及 SFU RTP 垫之间的关系。
访问 http://localhost:8081(admin/password)并检查 observertc-reports数据库。你应该会看到每 30 秒就有新数据流入——除非你更改了它,否则这是观察者向数据库报告的默认频率。
在我们开始分析报告之前,查看 docker-compose.yaml文件。在那里你可以看到 mediasoup-sfu服务下的环境变量 OUTBOUND_LATENCY_IN_MS,以及 my-webrtc-app 中的 SAMPLING_PERIOD_IN_MS。OUTBOUND_LATENCY_IN_MS控制通过在容器内应用 tc 来延迟传出流量。尽管它为传出流量设置了规则,但从运行在 localhost 上的客户端的角度来看,该延迟是 RTT 的主要因素。在 webrtc-app部分中,SAMPLING_PERIOD_IN_MS控制 client-monitor 的采样时间以生成样本。
7、ObserveRTC 报告
转发到 mongo 的报告具有类型、schemaVersion和有效载荷字段。schemaVersion用于兼容性目的,有效载荷取决于类型。不同类型报告用于不同目的,这里我们将专注于以下类型的报告:
OUTBOUND_AUDIO_TRACKOUTBOUND_VIDEO_TRACKINBOUND_AUDIO_TRACKINBOUND_VIDEO_TRACK
除了观察者接收到的对应 stats 外,该服务还会扩展报告以包含信息,以便识别哪个报告属于哪个对等连接、客户端和通话。
此外,入站音频和视频轨道报告还有以下附加公共字段:
remoteClientId识别轨道来源的客户端remotePeerConnectionId识别远程客户端上的对等连接,该对等连接提供此轨道接收媒体的出站轨道remoteTrackId识别远程客户端上的出站轨道 idsfuSinkId识别 SFU 订阅的sfuStream
你可以自己在 Mongo Express 中使用高级搜索过滤器 {type: { $in: ["INBOUND_VIDEO_TRACK", "OUTBOUND_VIDEO_TRACK", "INBOUND_AUDIO_TRACK", "OUTBOUND_AUDIO_TRACK"] } }或在浏览器中使用此 URL 进行调查。
7.1、使用 ObserveRTC 报告值计算 RTT
那么,我们如何计算两个用户之间的端到端 RTT 呢?
RTT 测量作为 OUTBOUND_AUDIO_TRACK和 OUTBOUND_VIDEO_TRACK报告的一部分。这提供了用户与 SFU 之间的 RTT 信息。INBOUND_AUDIO_TRACK和 INBOUND_VIDEO_TRACK报告具有出站轨道 id、远程对等连接和发布媒体流的远程客户端。借助这些信息,我们可以追溯并绘制图表。
7.2、收集 RTT 测量并追溯对等连接
也许并不那么简单。我在 full-stack-examples 中提供了一个 Jupyter 笔记本,用于计算用户之间的端到端 RTT,并在此处描述该过程。Jupyter 笔记本是 docker 堆栈的一部分,可通过 http://localhost:8888 访问。
客户端定期且异步地创建样本。例如,如果 client-monitor-js 的采样周期为 5 分钟,那么 Alice 会在 12:00 和 12:05 创建样本。与此同时,Bob 的样本会在 12:02 和 12:07 创建。Alice 报告的样本包含她与服务器之间的 RTT,而 Bob 报告的样本包含他与服务器之间的 RTT。由于一个样本中包含多个 RTT 测量值,因为客户端拥有的所有对等连接上的所有媒体轨道的指标都会包含在一个样本中。
在上面链接的笔记本中,第一个单元格是列出每个通话及其对应的客户端。我们将使用这些值来调查其中之一。
Room: Havana
--------
Call 9699b873-beeb-4d7c-9694-9c08534a24b9
UserId: Nagini
ClientId: e80ad6c2-0710-490c-92d9-91bed563cff6
Joined: 1656932609953
Left: 1656933704440
Duration: 18 min
UserId: Rita Skeeter
ClientId: 139fcaf6-4f46-4a66-abbe-3c65010503d3
Joined: 1656932622349
Left: 1656933694444
Duration: 17 min
在我们知道要查找的内容后,下一步是收集客户端与 SFU 之间的 RTT 并按对等连接进行分组。我们将按对等连接进行分组,因为同一条对等连接上的轨道使用相同的网络传输。
# a mongodb pipeline
pipeline = ...
cursor = reportsDatabase.aggregate(pipeline)
for report in cursor:
payload = report["payload"]
peerconnection_id = payload["peerConnectionId"]
rtt_in_s = payload["roundTripTime"]
timestamp = payload["timestamp"]
measurements = peer_connection_rtts.get(peerconnection_id, [])
measurement = (rtt_in_s, timestamp)
measurements.append(measurement)
peer_connection_rtts[peerconnection_id] = measurements
# data check
for id in peer_connection_rtts:
print("Number of measurements to analyze on %s: %s" % (id, len(peer_connection_rtts[r])))
下一步是创建追溯映射。首先,我们希望追溯本地客户端接收轨道的对等连接到发送这些轨道的远程客户端的对等连接。其次,由于只有出站视频和音频轨道报告包含 RTT 测量值,我们还需要映射哪个客户端的哪个对等连接发送到哪个远程客户端的哪个对等连接。
至少对我来说,后一句话有点难以理解,所以让我们用虚构的用户 Alice 和 Bob 举个例子。Alice 有两个对等连接,一个用于向 SFU 发送轨道,一个用于从 SFU 接收轨道。我们将这两个对等连接分别称为 alice_snd_pc和 _alice_rcv_pc_。Bob 也有两个对等连接用于相同的目的——我们将它们称为 bob_snd_pc和 _bob_rcv_pc_。
只有发送——即“snd”——对等连接的报告包含 RTT 测量值,因此我们需要在 alice_snd_pc和 bob_snd_pc中找到这些 RTT 值。我们想知道 Alice 接收对等连接的端到端 RTTs。报告中包含 alice_rcv_pc与 bob_snd_pc之间的连接信息。在这一点上,我们知道 Bob 用于发送轨道的对等连接,因此我们知道 Bob 与他连接的 SFU 之间的 RTT。但我们还需要知道 Alice 用于向她连接的 SFU 发送轨道的对等连接的 RTT,这与 Bob 接收对等连接的 SFU 希望是同一个 SFU。
pipeline = ...
cursor = reportsDatabase.aggregate(pipeline)
for report in cursor:
payload = report["payload"]
client_id = payload["clientId"]
client_peerconnection_id = payload["peerConnectionId"]
remote_client_id = payload["remoteClientId"]
remote_client_peerconnection_id = payload["remotePeerConnectionId"]
if client_peerconnection_id isnotNone:
inb_pc_ids = client_inb_pc_ids.get(client_id, set())
inb_pc_ids.add(client_peerconnection_id)
client_inb_pc_ids[client_id] = inb_pc_ids
if remote_client_id isnotNoneand remote_client_peerconnection_id isnotNone:
inb_pc_outb_pairs[client_peerconnection_id] = (remote_client_peerconnection_id, remote_client_id)
client_remote_peers = client_outb_pc_pairs.get(remote_client_id, {})
client_remote_peers[client_id] = remote_client_peerconnection_id
client_outb_pc_pairs[client_id] = client_remote_peers
# data check
for id in client_outb_pc_pairs:
print("client_id:%s maps to the following remote_peer_ids: %s" % (id, client_outb_pc_pairs[id])
我们从 INBOUND_AUDIO_TRACK和 INBOUND_VIDEO_TRACK创建以下映射:
- client_inb_pc_ids映射客户端及其用于接收轨道的对等连接
- inb_pc_outb_pairs映射接收轨道的对等连接到发送它们的对等连接
- client_outb_pc_pairs维护内部映射,指示哪个远程客户端通过哪个对等连接发送轨道
最后,我们只需要对 RTT 进行求和并绘制图表。我们选择每个用户用于向 SFU 发送轨道的对等连接。我们对这两个选定对等连接的 RTT 进行求和,同时考虑 RTT 的测量时间戳。
for client_inb_pc_id in client_inb_pc_ids[CLIENT_ID]:
remote_pc_id, remote_client_id = inb_pc_outb_pairs[client_inb_pc_id]
remote_measurements = peer_connection_rtts[remote_pc_id]
remote_client_peers = client_outb_pc_pairs[remote_client_id]
client_outb_pc_id = remote_client_peers[CLIENT_ID]
local_measurements = peer_connection_rtts[client_outb_pc_id]
sorted_local_measurements = sorted(local_measurements, key=lambda x: x[1])
sorted_remote_measurements = sorted(remote_measurements, key=lambda x: x[1])
i, j, loc_size, rem_size = 0, 0, len(sorted_local_measurements), len(sorted_remote_measurements)
end_to_end_rtts = []
timestamps = []
whileTrue:
if loc_size <= i or rem_size <= j:
break
local_client_to_sfu_rtt, local_client_actual_ts = sorted_local_measurements[i]
remote_client_to_sfu_rtt, remote_client_actual_ts = sorted_remote_measurements[j]
if i + 1 < loc_size and sorted_local_measurements[i + 1][1] < remote_client_actual_ts:
i = i + 1
continue
if j + 1 < rem_size and sorted_remote_measurements[j + 1][1] < local_client_actual_ts:
j = j + 1
continue
end_to_end_rtt = local_client_to_sfu_rtt + remote_client_to_sfu_rtt
ts = max(local_client_actual_ts, remote_client_actual_ts)
end_to_end_rtts.append(end_to_end_rtt)
timestamps.append(ts)
i = i + 1
j = j + 1
client_to_client_rtts[remote_client_id] = (timestamps, end_to_end_rtts)
print("Average End-to-End RTT: %0.3f ms" % (sum(end_to_end_rtts) / len(end_to_end_rtts)))
之后,我们可以绘制图表。
import matplotlib.pyplot as plt
for remote_client_id, remote_client_rtts in client_to_client_rtts.items():
x, y = remote_client_rtts
fig, ax = plt.subplots()
ax.set_title("end-to-end RTT between " + remote_client_id + " and " + CLIENT_ID)
ax.step(x, y, linewidth=2.5)
ax.set_xlabel('timestamps')
ax.set_ylabel('RTT [s]')
plt.show()
它应该看起来像这样:
我将 SFU 与连接客户端之间的默认 RTT 设置为 400 毫秒,这使得两个客户端之间的端到端 RTT 总和约为 800 毫秒。
注意:在我们的示例中使用了 MongoDB,而 mongo 中查询执行的性能高度依赖于你的数据库集群配置。报告可以基于用于识别的字段(如 callId、clientId、peerConnectionId、trackId、sfuId、sfuTransportId等)进行索引和分片。
此外,MongoDB 并不是观察者可以转发报告的唯一选择。根据需求,支持的接收器种类正在增长——目前,我们还支持 Kafka 和 AWS Kinesis 数据火 hose。
8、级联 SFU 环境
通常,现实世界中的情况会变得更加有趣!让我们更进一步,使用多个相互连接的 SFU。与使用一个 SFU 的场景相比,这里的情况并没有发生巨大变化,但扩展了许多内容。我们在端到端 RTT 计算过程中所缺少的是互连 SFU 之间的 RTT。这就是 ObserveRTC 堆栈中的 sfu-monitor 能够为我们提供的信息。sfu-monitor 对 SFU 到 SFU 和 SFU 到用户的传输进行采样。样本可以发送到观察者,观察者处理所有 SFU 的样本并生成报告。我们需要 INBOUND_SFU_RTP_PAD和 OUTBOUND_SFU_RTP_PAD报告。属于同一 SFU_RTP_PAD的报告指的是由同步源标识的 RTP 会话。(对于那些与 GStreamer 打过交道的人来说,“pad”这个术语可能很熟悉,比如我 ????)
与客户端应用程序提供的样本生成的报告类似,INBOUND_SFU_RTP_PAD报告包含有关远程 SFU 或客户端对应方的信息。属于 SFU 之间打开的传输的 pads 在报告中被标记了一个内部标志。如果 inbound RTP pad 的内部标志为 true,那么观察者会尝试将其与 outbound RTP pad 匹配。如果该标志为 false,那么观察者会尝试将该 pad 与客户端出站轨道匹配。
要计算客户端与远程客户端之间的端到端 RTT,我们需要将互连 SFU 的 RTT 纳入计算过程。
同一个 ObserveRTC full-stack-example 仓库还包含一个级联 SFU 端到端 RTT 计算示例。与之前一样,你可以通过运行以下命令来运行 Docker 示例:
SFU_ANNOUNCED_IP={YOUR LOCAL IP ADDRESS} docker compose -f docker-compose-cascaded-sfus.yaml up
请注意级联 docker-compose YAML 和非级联版本之间的以下区别:
- 多个
mediasoup_sfu服务实例 - 这里有一个
SFU_PEERS环境变量,通知mediasoup_sfu启动与对等方的管道连接。 WEBSOCKET_PORT不同,因此不同的 SFU 在不同的端口上监听来自客户端的 WebSocket 连接- 不同 SFU 的
RTCMIN_PORT和RTCMAX_PORT不同。
要从网页部分连接到不同的 SFU,你需要使用 http://localhost:9000?sfuPort=5959 和 http://localhost:9000?sfuPort=7171,其中 sfuPort等于你分配给不同 SFU 的 WEBSOCKET_PORT。为此创建的笔记本在 Docker 示例中运行。如果你为你的 CALL_ID和 CLIENT_ID运行该笔记本中的每个单元格,你最终应该会看到如下所示的图表:
9、结语
现在,你应该对如何测量端到端 RTT 有了良好的理解。希望你也对开源项目 ObserveRTC 如何与 WebRTC 的 getStats 配合使用,以分析和排查 WebRTC 通话有了更好的理解。ObserveRTC 的路线图包括监控 TURN 服务、升级内存数据库网格以及云集成。非常欢迎贡献 :)。祝 WebRTC 黑客生活愉快!
音视频方向学习、求职,欢迎加入我们的星球
丰富的音视频知识、面试题、技术方案干货分享,还可以进行面试辅导

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。