Skip to content

Commit 78455c7

Browse files
committed
feat: faster rtt calculation and fallback on firefox
1 parent 97f992d commit 78455c7

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

peer/src/peer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ export class Peer {
346346
},
347347
metrics: {
348348
qualityScore: quality.qualityScore,
349-
rttUs: quality.rtt,
349+
rttUs: quality.rttUs,
350350
},
351351
});
352352
}

peer/src/quality.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ interface RTCReceiverStats extends RTCStats {
4040
// framesPerSecond?: number;
4141
}
4242

43+
// https://developer.mozilla.org/en-US/docs/Web/API/RTCRemoteInboundRtpStreamStats
44+
interface RTCRemoteInboundRtpStreamStats extends RTCStats {
45+
type: "remote-inbound-rtp";
46+
kind?: "audio" | "video";
47+
roundTripTime: number;
48+
}
49+
4350
interface RTCIceCandidatePairStats extends RTCStats {
4451
type: "candidate-pair";
4552
state?:
@@ -73,12 +80,13 @@ export interface QualityStats {
7380
export function calculateQualityScore(
7481
stats: RTCStatsReport,
7582
): QualityStats | null {
83+
const statsIter = stats.values() as MapIterator<RTCStats>;
7684
let audioReceiverStats: RTCReceiverStats | undefined;
7785
let videoReceiverStats: RTCReceiverStats | undefined;
78-
let activeCandidatePairStats: RTCIceCandidatePairStats | undefined;
86+
let rtt: number | undefined;
7987
let peerConnectionStats: RTCPeerConnectionStats | undefined;
8088

81-
for (const stat of stats.values()) {
89+
for (const stat of statsIter) {
8290
if (stat.type === "inbound-rtp" || stat.type === "rtp-receiver") {
8391
// https://developer.mozilla.org/en-US/docs/Web/API/RTCInboundRtpStreamStats
8492
const receiverStat = stat as RTCReceiverStats;
@@ -90,11 +98,20 @@ export function calculateQualityScore(
9098
} else if (stat.type === "candidate-pair") {
9199
// https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePairStats
92100
const candidatePairStat = stat as RTCIceCandidatePairStats;
93-
if (candidatePairStat.state === "succeeded") {
94-
activeCandidatePairStats = candidatePairStat;
101+
// prioritize remote-inbound-rtp rtt
102+
if (candidatePairStat.state === "succeeded" && !rtt) {
103+
rtt = candidatePairStat.currentRoundTripTime;
95104
}
96105
} else if (stat.type === "peer-connection") {
97106
peerConnectionStats = stat as RTCPeerConnectionStats;
107+
} else if (stat.type === "remote-inbound-rtp") {
108+
// There are 2 cases when we need this:
109+
// 1. Fallback for Firefox's missing ICE RTT support
110+
// 2. Faster RTT calculation as it is used in RTP streams
111+
//
112+
// If there's only data channel without media streams, Firefox won't generate RTT.
113+
const remoteInboundStat = stat as RTCRemoteInboundRtpStreamStats;
114+
rtt = remoteInboundStat.roundTripTime;
98115
}
99116
}
100117

@@ -144,13 +161,10 @@ export function calculateQualityScore(
144161
}
145162

146163
let latencyScore = 80;
147-
if (activeCandidatePairStats) {
148-
const rtt = activeCandidatePairStats.currentRoundTripTime;
149-
if (rtt !== undefined) {
150-
// second to microseconds
151-
quality.rttUs = BigInt(rtt * 1e6);
152-
latencyScore = rtt < 0.1 ? 100 : (rtt < 0.3 ? 80 : (rtt < 0.5 ? 60 : 40));
153-
}
164+
if (!!rtt) {
165+
// second to microseconds
166+
quality.rttUs = BigInt(Math.trunc(rtt * 1e6));
167+
latencyScore = rtt < 0.1 ? 100 : (rtt < 0.3 ? 80 : (rtt < 0.5 ? 60 : 40));
154168
}
155169

156170
const overallQuality = Math.round(

0 commit comments

Comments
 (0)