Skip to content

Commit 190825c

Browse files
committed
fix publishing bitrate
1 parent d01db88 commit 190825c

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

src/connectionHelper/checks/Checker.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type RTCEngine from '../../room/RTCEngine';
55
import Room, { ConnectionState } from '../../room/Room';
66
import { RoomEvent } from '../../room/events';
77
import type { SimulationScenario } from '../../room/types';
8+
import { sleep } from '../../room/utils';
89

910
type LogMessage = {
1011
level: 'info' | 'warning' | 'error';
@@ -126,18 +127,31 @@ export abstract class Checker extends (EventEmitter as new () => TypedEmitter<Ch
126127
this.setStatus(CheckStatus.SKIPPED);
127128
}
128129

129-
protected async switchProtocol(protocol: 'tcp' | 'tls') {
130-
this.room.simulateScenario(`force-${protocol}` as SimulationScenario);
131-
const promise = new Promise<void>((resolve, reject) => {
132-
const timeout = setTimeout(() => {
133-
reject(new Error('Timeout waiting for reconnection'));
134-
}, 10000);
135-
this.room.once(RoomEvent.Reconnected, () => {
136-
clearTimeout(timeout);
137-
resolve();
138-
});
130+
protected async switchProtocol(protocol: 'udp' | 'tcp' | 'tls') {
131+
let hasReconnecting = false;
132+
let hasReconnected = false;
133+
this.room.on(RoomEvent.Reconnecting, () => {
134+
hasReconnecting = true;
135+
});
136+
this.room.once(RoomEvent.Reconnected, () => {
137+
hasReconnected = true;
139138
});
140-
return promise;
139+
this.room.simulateScenario(`force-${protocol}` as SimulationScenario);
140+
await new Promise((resolve) => setTimeout(resolve, 1000));
141+
if (!hasReconnecting) {
142+
// no need to wait for reconnection
143+
return;
144+
}
145+
146+
// wait for 10 seconds for reconnection
147+
const timeout = Date.now() + 10000;
148+
while (Date.now() < timeout) {
149+
if (hasReconnected) {
150+
return;
151+
}
152+
await sleep(100);
153+
}
154+
throw new Error(`Could not reconnect using ${protocol} protocol after 10 seconds`);
141155
}
142156

143157
protected appendMessage(message: string) {

src/connectionHelper/checks/cloudRegion.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class CloudRegionCheck extends Checker {
4545
});
4646
const bestRegion = regionStats[0];
4747
this.bestStats = bestRegion;
48-
this.appendMessage(`Best Cloud region: ${bestRegion.region}`);
48+
this.appendMessage(`best Cloud region: ${bestRegion.region}`);
4949
}
5050

5151
getInfo(): CheckInfo {
@@ -84,7 +84,6 @@ export class CloudRegionCheck extends Checker {
8484
};
8585
stats?.forEach((stat) => {
8686
if (stat.type === 'candidate-pair' && stat.nominated) {
87-
console.log('stat', stat);
8887
regionStats.rtt = stat.currentRoundTripTime * 1000;
8988
}
9089
});

src/connectionHelper/checks/connectionProtocol.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export interface ProtocolStats {
1212
count: number;
1313
}
1414

15+
const TEST_DURATION = 10000;
16+
1517
export class ConnectionProtocolCheck extends Checker {
1618
private bestStats?: ProtocolStats;
1719

@@ -24,43 +26,40 @@ export class ConnectionProtocolCheck extends Checker {
2426
const tcpStats = await this.checkConnectionProtocol('tcp');
2527
this.bestStats = udpStats;
2628
// udp should is the better protocol typically. however, we'd prefer TCP when either of these conditions are true:
27-
// 1. the bandwidth limitation is worse on UDP by 500ms (10% of the test duration)
29+
// 1. the bandwidth limitation is worse on UDP by 500ms
2830
// 2. the packet loss is higher on UDP by 1%
2931
if (
3032
udpStats.qualityLimitationDurations.bandwidth -
3133
tcpStats.qualityLimitationDurations.bandwidth >
3234
0.5 ||
3335
(udpStats.packetsLost - tcpStats.packetsLost) / udpStats.packetsSent > 0.01
3436
) {
35-
this.appendMessage('best connection quality via TCP');
37+
this.appendMessage('best connection quality via tcp');
3638
this.bestStats = tcpStats;
3739
} else {
38-
this.appendMessage('best connection quality via UDP');
40+
this.appendMessage('best connection quality via udp');
3941
}
4042

43+
const stats = this.bestStats;
4144
this.appendMessage(
42-
`upstream bitrate: ${(this.bestStats.bitrateTotal / this.bestStats.count / 1000 / 1000).toFixed(2)} mbps`,
43-
);
44-
this.appendMessage(
45-
`RTT: ${((this.bestStats.rttTotal / this.bestStats.count) * 1000).toFixed(2)} ms`,
46-
);
47-
this.appendMessage(
48-
`jitter: ${((this.bestStats.jitterTotal / this.bestStats.count) * 1000).toFixed(2)} ms`,
45+
`upstream bitrate: ${(stats.bitrateTotal / stats.count / 1000 / 1000).toFixed(2)} mbps`,
4946
);
47+
this.appendMessage(`RTT: ${((stats.rttTotal / stats.count) * 1000).toFixed(2)} ms`);
48+
this.appendMessage(`jitter: ${((stats.jitterTotal / stats.count) * 1000).toFixed(2)} ms`);
5049

51-
if (this.bestStats.packetsLost > 0) {
52-
this.appendMessage(
53-
`packets lost: ${((this.bestStats.packetsLost / this.bestStats.packetsSent) * 100).toFixed(2)}%`,
50+
if (stats.packetsLost > 0) {
51+
this.appendWarning(
52+
`packets lost: ${((stats.packetsLost / stats.packetsSent) * 100).toFixed(2)}%`,
5453
);
5554
}
56-
if (this.bestStats.qualityLimitationDurations.bandwidth > 0) {
55+
if (stats.qualityLimitationDurations.bandwidth > 1) {
5756
this.appendWarning(
58-
`bandwidth limited ${((this.bestStats.qualityLimitationDurations.bandwidth / 5) * 100).toFixed(2)}%`,
57+
`bandwidth limited ${((stats.qualityLimitationDurations.bandwidth / (TEST_DURATION / 1000)) * 100).toFixed(2)}%`,
5958
);
6059
}
61-
if (this.bestStats.qualityLimitationDurations.cpu > 0) {
60+
if (stats.qualityLimitationDurations.cpu > 0) {
6261
this.appendWarning(
63-
`cpu limited ${((this.bestStats.qualityLimitationDurations.cpu / 5) * 100).toFixed(2)}%`,
62+
`cpu limited ${((stats.qualityLimitationDurations.cpu / (TEST_DURATION / 1000)) * 100).toFixed(2)}%`,
6463
);
6564
}
6665
}
@@ -72,10 +71,11 @@ export class ConnectionProtocolCheck extends Checker {
7271
}
7372

7473
private async checkConnectionProtocol(protocol: 'tcp' | 'udp'): Promise<ProtocolStats> {
75-
this.appendMessage(`connecting via ${protocol}`);
7674
await this.connect();
7775
if (protocol === 'tcp') {
7876
await this.switchProtocol('tcp');
77+
} else {
78+
await this.switchProtocol('udp');
7979
}
8080

8181
// create a canvas with animated content
@@ -103,8 +103,12 @@ export class ConnectionProtocolCheck extends Checker {
103103
// publish to room
104104
const pub = await this.room.localParticipant.publishTrack(videoTrack, {
105105
simulcast: false,
106+
degradationPreference: 'maintain-resolution',
107+
videoEncoding: {
108+
maxBitrate: 2000000,
109+
},
106110
});
107-
const track = pub.track!;
111+
const track = pub!.track!;
108112

109113
const protocolStats: ProtocolStats = {
110114
protocol,
@@ -124,7 +128,6 @@ export class ConnectionProtocolCheck extends Checker {
124128
protocolStats.packetsSent = stat.packetsSent;
125129
protocolStats.qualityLimitationDurations = stat.qualityLimitationDurations;
126130
protocolStats.bitrateTotal += stat.targetBitrate;
127-
128131
protocolStats.count++;
129132
} else if (stat.type === 'remote-inbound-rtp') {
130133
protocolStats.packetsLost = stat.packetsLost;
@@ -135,10 +138,11 @@ export class ConnectionProtocolCheck extends Checker {
135138
}, 1000);
136139

137140
// wait a bit to gather stats
138-
await new Promise((resolve) => setTimeout(resolve, 5000));
141+
await new Promise((resolve) => setTimeout(resolve, TEST_DURATION));
139142
clearInterval(interval);
140143

141144
videoTrack.stop();
145+
canvas.remove();
142146
await this.disconnect();
143147
return protocolStats;
144148
}

0 commit comments

Comments
 (0)