@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-ea70eab.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ObservedCall.d.ts +43 -7
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +129 -13
- package/lib/ObservedCallEventMonitor.d.ts +104 -0
- package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
- package/lib/ObservedCallEventMonitor.js +314 -0
- package/lib/ObservedCallSummary.d.ts +18 -0
- package/lib/ObservedCallSummary.d.ts.map +1 -0
- package/lib/ObservedClient.d.ts +70 -11
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +392 -72
- package/lib/ObservedClientEventMonitor.d.ts +89 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +247 -0
- package/lib/ObservedClientSummary.d.ts +23 -0
- package/lib/ObservedClientSummary.d.ts.map +1 -0
- package/lib/ObservedClientSummary.js +2 -0
- package/lib/ObservedDataChannel.d.ts +6 -0
- package/lib/ObservedDataChannel.d.ts.map +1 -1
- package/lib/ObservedDataChannel.js +30 -0
- package/lib/ObservedIceCandidatePair.d.ts +6 -1
- package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
- package/lib/ObservedIceCandidatePair.js +45 -1
- package/lib/ObservedIceTransport.d.ts +4 -0
- package/lib/ObservedIceTransport.d.ts.map +1 -1
- package/lib/ObservedIceTransport.js +28 -0
- package/lib/ObservedInboundTrack.d.ts +2 -0
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +2 -0
- package/lib/ObservedOutboundTrack.d.ts +2 -0
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +2 -0
- package/lib/ObservedPeerConnection.d.ts +29 -2
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +181 -29
- package/lib/ObservedTURN.d.ts +31 -0
- package/lib/ObservedTURN.d.ts.map +1 -0
- package/lib/ObservedTURN.js +58 -0
- package/lib/ObservedTurnServer.d.ts +25 -0
- package/lib/ObservedTurnServer.d.ts.map +1 -0
- package/lib/ObservedTurnServer.js +59 -0
- package/lib/Observer.d.ts +43 -22
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +126 -40
- package/lib/ObserverEventMonitor.d.ts +130 -0
- package/lib/ObserverEventMonitor.d.ts.map +1 -0
- package/lib/ObserverEventMonitor.js +404 -0
- package/lib/ObserverSummary.d.ts +13 -0
- package/lib/ObserverSummary.d.ts.map +1 -0
- package/lib/ObserverSummary.js +2 -0
- package/lib/common/utils.d.ts +2 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +11 -3
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -1
- package/lib/schema/ClientEventTypes.d.ts +160 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -0
- package/lib/schema/ClientEventTypes.js +38 -0
- package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
- package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
- package/lib/schema/ClientMetaTypes.js +16 -0
- package/lib/schema/ClientSample.d.ts +1 -1
- package/lib/schema/ClientSample.d.ts.map +1 -1
- package/lib/updaters/CallUpdater.d.ts.map +1 -0
- package/lib/updaters/CallUpdater.js +2 -0
- package/lib/updaters/ObserverUpdater.d.ts +5 -0
- package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/ObserverUpdater.js +2 -0
- package/lib/updaters/OnAllCallObserverUpdater.d.ts +15 -0
- package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllClientCallUpdater.js +53 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyClientCallUpdater.js +36 -0
- package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
- package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
- package/lib/updaters/OnIntervalUpdater.js +17 -0
- package/lib/updaters/Updater.d.ts +6 -0
- package/lib/updaters/Updater.d.ts.map +1 -0
- package/lib/updaters/Updater.js +2 -0
- package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
- package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
- package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
- package/package.json +1 -1
- package/src/ObservedCall.ts +210 -16
- package/src/ObservedCallEventMonitor.ts +392 -0
- package/src/ObservedCallSummary.ts +22 -0
- package/src/ObservedClient.ts +490 -79
- package/src/ObservedClientEventMonitor.ts +301 -0
- package/src/ObservedClientSummary.ts +24 -0
- package/src/ObservedDataChannel.ts +32 -0
- package/src/ObservedIceCandidatePair.ts +44 -2
- package/src/ObservedIceTransport.ts +29 -0
- package/src/ObservedInboundTrack.ts +3 -0
- package/src/ObservedOutboundTrack.ts +3 -0
- package/src/ObservedPeerConnection.ts +210 -46
- package/src/ObservedTURN.ts +86 -0
- package/src/ObservedTurnServer.ts +72 -0
- package/src/Observer.ts +179 -64
- package/src/ObserverEventMonitor.ts +518 -0
- package/src/ObserverSummary.ts +15 -0
- package/src/common/utils.ts +12 -2
- package/src/index.ts +6 -0
- package/src/schema/ClientEventTypes.ts +176 -0
- package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
- package/src/schema/ClientSample.ts +1 -1
- package/src/updaters/ObserverUpdater.ts +5 -0
- package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
- package/src/updaters/OnAllClientCallUpdater.ts +61 -0
- package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
- package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
- package/src/updaters/OnIntervalUpdater.ts +19 -0
- package/src/updaters/Updater.ts +5 -0
- package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
- package/tsconfig.json +1 -1
- package/lib/schema/eventTypes.d.ts +0 -33
- package/lib/schema/eventTypes.d.ts.map +0 -1
- package/lib/schema/eventTypes.js +0 -38
- package/lib/schema/metaTypes.d.ts.map +0 -1
- package/lib/schema/metaTypes.js +0 -16
- package/lib/utils/CallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
- package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.js +0 -58
- package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
- package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/onAnyClientCallUpdater.js +0 -51
- package/src/schema/eventTypes.ts +0 -36
- package/src/utils/OnAllClientCallUpdater.ts +0 -68
- package/src/utils/onAnyClientCallUpdater.ts +0 -59
- /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
- /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
- /package/src/{utils → updaters}/CallUpdater.ts +0 -0
|
@@ -19,6 +19,8 @@ import { ObservedRemoteOutboundRtp } from './ObservedRemoteOutboundRtp';
|
|
|
19
19
|
import { ObservedInboundTrack } from './ObservedInboundTrack';
|
|
20
20
|
import { ObservedOutboundTrack } from './ObservedOutboundTrack';
|
|
21
21
|
import { CalculatedScore } from './scores/CalculatedScore';
|
|
22
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
23
|
+
import { getMedian } from './common/utils';
|
|
22
24
|
|
|
23
25
|
const logger = createLogger('ObservedPeerConnection');
|
|
24
26
|
|
|
@@ -70,7 +72,22 @@ export type ObservedPeerConnectionEvents = {
|
|
|
70
72
|
'removed-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
71
73
|
'removed-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
72
74
|
'removed-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
73
|
-
|
|
75
|
+
'updated-inbound-rtp': [ObservedInboundRtp];
|
|
76
|
+
'updated-outbound-rtp': [ObservedOutboundRtp];
|
|
77
|
+
'updated-inbound-track': [ObservedInboundTrack];
|
|
78
|
+
'updated-outbound-track': [ObservedOutboundTrack];
|
|
79
|
+
'updated-ice-candidate-pair': [ObservedIceCandidatePair];
|
|
80
|
+
'updated-ice-transport': [ObservedIceTransport];
|
|
81
|
+
'updated-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
82
|
+
'updated-media-source': [ObservedMediaSource];
|
|
83
|
+
'updated-media-playout': [ObservedMediaPlayout];
|
|
84
|
+
'updated-data-channel': [ObservedDataChannel];
|
|
85
|
+
'updated-ice-candidate': [ObservedIceCandidate];
|
|
86
|
+
'updated-certificate': [ObservedCertificate];
|
|
87
|
+
'updated-codec': [ObservedCodec];
|
|
88
|
+
'updated-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
89
|
+
'updated-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
90
|
+
'update': [],
|
|
74
91
|
close: [];
|
|
75
92
|
};
|
|
76
93
|
|
|
@@ -106,11 +123,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
106
123
|
public closedAt?: number;
|
|
107
124
|
public updated = Date.now();
|
|
108
125
|
|
|
126
|
+
public availableIncomingBitrate = 0;
|
|
127
|
+
public availableOutgoingBitrate = 0;
|
|
109
128
|
public totalInboundPacketsLost = 0;
|
|
110
129
|
public totalInboundPacketsReceived = 0;
|
|
111
130
|
public totalOutboundPacketsSent = 0;
|
|
112
131
|
public totalDataChannelBytesSent = 0;
|
|
113
132
|
public totalDataChannelBytesReceived = 0;
|
|
133
|
+
public totalDataChannelMessagesSent = 0;
|
|
134
|
+
public totalDataChannelMessagesReceived = 0;
|
|
114
135
|
|
|
115
136
|
public totalSentAudioBytes = 0;
|
|
116
137
|
public totalSentVideoBytes = 0;
|
|
@@ -126,6 +147,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
126
147
|
public deltaOutboundPacketsSent = 0;
|
|
127
148
|
public deltaDataChannelBytesSent = 0;
|
|
128
149
|
public deltaDataChannelBytesReceived = 0;
|
|
150
|
+
public deltaDataChannelMessagesSent = 0;
|
|
151
|
+
public deltaDataChannelMessagesReceived = 0;
|
|
129
152
|
public deltaInboundReceivedBytes = 0;
|
|
130
153
|
public deltaOutboundSentBytes = 0;
|
|
131
154
|
|
|
@@ -135,6 +158,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
135
158
|
public deltaReceivedVideoPackets = 0;
|
|
136
159
|
public deltaSentAudioBytes = 0;
|
|
137
160
|
public deltaSentVideoBytes = 0;
|
|
161
|
+
public deltaTransportSentBytes = 0;
|
|
162
|
+
public deltaTransportReceivedBytes = 0;
|
|
138
163
|
|
|
139
164
|
public receivingPacketsPerSecond = 0;
|
|
140
165
|
public sendingPacketsPerSecond = 0;
|
|
@@ -143,12 +168,13 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
143
168
|
public receivingAudioBitrate = 0;
|
|
144
169
|
public receivingVideoBitrate = 0;
|
|
145
170
|
|
|
146
|
-
public
|
|
147
|
-
public
|
|
171
|
+
public currentRttInMs?: number;
|
|
172
|
+
public currentJitter?: number;
|
|
148
173
|
|
|
149
174
|
public usingTCP = false;
|
|
150
175
|
public usingTURN = false;
|
|
151
176
|
|
|
177
|
+
public observedTurnServer?: ObservedTurnServer;
|
|
152
178
|
public readonly observedCertificates = new Map<string, ObservedCertificate>();
|
|
153
179
|
public readonly observedCodecs = new Map<string, ObservedCodec>();
|
|
154
180
|
public readonly observedDataChannels = new Map<string, ObservedDataChannel>();
|
|
@@ -239,6 +265,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
239
265
|
.filter((pair) => pair !== undefined) as ObservedIceCandidatePair[];
|
|
240
266
|
}
|
|
241
267
|
|
|
268
|
+
public get selectedIceCandiadtePairForTurn() {
|
|
269
|
+
return this.selectedIceCandidatePairs
|
|
270
|
+
.filter((pair) =>
|
|
271
|
+
pair.getLocalCandidate()?.candidateType === 'relay' &&
|
|
272
|
+
pair.getRemoteCandidate()?.url?.startsWith('turn:')
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
242
276
|
public close() {
|
|
243
277
|
if (this.closed) return;
|
|
244
278
|
this.closed = true;
|
|
@@ -259,6 +293,10 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
259
293
|
this.observedRemoteInboundRtps.clear();
|
|
260
294
|
this.observedRemoteOutboundRtps.clear();
|
|
261
295
|
|
|
296
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
297
|
+
|
|
298
|
+
if (!this.closedAt) this.closedAt = Date.now();
|
|
299
|
+
|
|
262
300
|
this.emit('close');
|
|
263
301
|
}
|
|
264
302
|
|
|
@@ -266,6 +304,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
266
304
|
if (this.closed) return;
|
|
267
305
|
this._visited = true;
|
|
268
306
|
|
|
307
|
+
this.availableIncomingBitrate = 0;
|
|
308
|
+
this.availableOutgoingBitrate = 0;
|
|
269
309
|
this.deltaInboundPacketsLost = 0;
|
|
270
310
|
this.deltaInboundPacketsReceived = 0;
|
|
271
311
|
this.deltaOutboundPacketsSent = 0;
|
|
@@ -279,6 +319,9 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
279
319
|
this.deltaReceivedVideoPackets = 0;
|
|
280
320
|
this.deltaSentAudioBytes = 0;
|
|
281
321
|
this.deltaSentVideoBytes = 0;
|
|
322
|
+
this.deltaTransportReceivedBytes = 0;
|
|
323
|
+
this.deltaTransportSentBytes = 0;
|
|
324
|
+
|
|
282
325
|
this.sendingAudioBitrate = 0;
|
|
283
326
|
this.sendingVideoBitrate = 0;
|
|
284
327
|
this.receivingAudioBitrate = 0;
|
|
@@ -287,6 +330,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
287
330
|
const now = Date.now();
|
|
288
331
|
const elapsedTimeInMs = now - this.updated;
|
|
289
332
|
const elapsedTimeInSec = elapsedTimeInMs / 1000;
|
|
333
|
+
const rttMeasurementsInSec: number[] = [];
|
|
334
|
+
const jitterMeasurements: number[] = [];
|
|
290
335
|
|
|
291
336
|
if (sample.certificates) {
|
|
292
337
|
for (const certificate of sample.certificates) {
|
|
@@ -300,7 +345,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
300
345
|
}
|
|
301
346
|
if (sample.dataChannels) {
|
|
302
347
|
for (const dataChannel of sample.dataChannels) {
|
|
303
|
-
this._updateDataChannelStats(dataChannel);
|
|
348
|
+
const observedDataChannel = this._updateDataChannelStats(dataChannel);
|
|
349
|
+
|
|
350
|
+
if (!observedDataChannel) continue;
|
|
351
|
+
|
|
352
|
+
this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
|
|
353
|
+
this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
|
|
354
|
+
this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
|
|
355
|
+
this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
|
|
304
356
|
}
|
|
305
357
|
}
|
|
306
358
|
if (sample.iceCandidates) {
|
|
@@ -310,12 +362,29 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
310
362
|
}
|
|
311
363
|
if (sample.iceCandidatePairs) {
|
|
312
364
|
for (const iceCandidatePair of sample.iceCandidatePairs) {
|
|
313
|
-
this._updateIceCandidatePairStats(iceCandidatePair);
|
|
365
|
+
const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
|
|
366
|
+
|
|
367
|
+
if (!observedCandidatePair) continue;
|
|
368
|
+
|
|
369
|
+
if (observedCandidatePair.currentRoundTripTime) {
|
|
370
|
+
rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
|
|
371
|
+
}
|
|
372
|
+
if (observedCandidatePair.availableIncomingBitrate) {
|
|
373
|
+
this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
|
|
374
|
+
}
|
|
375
|
+
if (observedCandidatePair.availableOutgoingBitrate) {
|
|
376
|
+
this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
|
|
377
|
+
}
|
|
314
378
|
}
|
|
315
379
|
}
|
|
316
380
|
if (sample.iceTransports) {
|
|
317
381
|
for (const iceTransport of sample.iceTransports) {
|
|
318
|
-
this._updateIceTransportStats(iceTransport);
|
|
382
|
+
const observedIceTransport = this._updateIceTransportStats(iceTransport);
|
|
383
|
+
|
|
384
|
+
if (!observedIceTransport) return;
|
|
385
|
+
|
|
386
|
+
observedIceTransport.bytesReceived;
|
|
387
|
+
|
|
319
388
|
}
|
|
320
389
|
}
|
|
321
390
|
if (sample.inboundRtps) {
|
|
@@ -338,6 +407,10 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
338
407
|
this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
|
|
339
408
|
break;
|
|
340
409
|
}
|
|
410
|
+
|
|
411
|
+
if (observedInboundRtp.jitter) {
|
|
412
|
+
jitterMeasurements.push(observedInboundRtp.jitter);
|
|
413
|
+
}
|
|
341
414
|
}
|
|
342
415
|
}
|
|
343
416
|
if (sample.mediaPlayouts) {
|
|
@@ -374,12 +447,21 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
374
447
|
}
|
|
375
448
|
if (sample.peerConnectionTransports) {
|
|
376
449
|
for (const peerConnectionTransport of sample.peerConnectionTransports) {
|
|
377
|
-
this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
450
|
+
const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
451
|
+
|
|
452
|
+
if (!observedTransport) continue;
|
|
453
|
+
|
|
378
454
|
}
|
|
379
455
|
}
|
|
380
456
|
if (sample.remoteInboundRtps) {
|
|
381
457
|
for (const remoteInboundRtp of sample.remoteInboundRtps) {
|
|
382
|
-
this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
458
|
+
const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
459
|
+
|
|
460
|
+
if (!observedRemoteInboundRtp) continue;
|
|
461
|
+
|
|
462
|
+
if (observedRemoteInboundRtp.roundTripTime) {
|
|
463
|
+
rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
|
|
464
|
+
}
|
|
383
465
|
}
|
|
384
466
|
}
|
|
385
467
|
if (sample.remoteOutboundRtps) {
|
|
@@ -408,6 +490,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
408
490
|
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
|
|
409
491
|
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
410
492
|
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
493
|
+
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
494
|
+
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
411
495
|
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
|
|
412
496
|
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
|
|
413
497
|
this.totalSentAudioBytes += this.deltaSentAudioBytes;
|
|
@@ -419,20 +503,55 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
419
503
|
|
|
420
504
|
this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
|
|
421
505
|
this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / elapsedTimeInSec;
|
|
422
|
-
this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedTimeInSec;
|
|
423
|
-
this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedTimeInSec;
|
|
424
|
-
this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedTimeInSec;
|
|
425
|
-
this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedTimeInSec;
|
|
426
|
-
|
|
506
|
+
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / elapsedTimeInSec;
|
|
507
|
+
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / elapsedTimeInSec;
|
|
508
|
+
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / elapsedTimeInSec;
|
|
509
|
+
this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / elapsedTimeInSec;
|
|
510
|
+
|
|
511
|
+
if (rttMeasurementsInSec.length > 0) {
|
|
512
|
+
this.currentRttInMs = getMedian(rttMeasurementsInSec, false) * 1000;
|
|
513
|
+
} else {
|
|
514
|
+
this.currentRttInMs = undefined;
|
|
515
|
+
}
|
|
516
|
+
if (jitterMeasurements.length > 0) {
|
|
517
|
+
this.currentJitter = getMedian(jitterMeasurements, false);
|
|
518
|
+
} else {
|
|
519
|
+
this.currentJitter = undefined;
|
|
520
|
+
}
|
|
521
|
+
const wasUsingTURN = this.usingTURN;
|
|
427
522
|
const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
|
|
523
|
+
const selectedCandidatePairForTurn: ObservedIceCandidatePair[] = [];
|
|
428
524
|
|
|
429
|
-
this.usingTCP =
|
|
430
|
-
this.usingTURN =
|
|
431
|
-
|
|
525
|
+
this.usingTCP = false;
|
|
526
|
+
this.usingTURN = false;
|
|
527
|
+
|
|
528
|
+
for (const selectedCandidatePair of selectedIceCandidatePairs) {
|
|
529
|
+
if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
|
|
530
|
+
this.usingTCP = true;
|
|
531
|
+
}
|
|
532
|
+
if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
|
|
533
|
+
selectedCandidatePairForTurn.push(selectedCandidatePair);
|
|
534
|
+
this.usingTURN = true;
|
|
535
|
+
}
|
|
536
|
+
this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
|
|
537
|
+
this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
|
|
538
|
+
}
|
|
432
539
|
|
|
540
|
+
if (this.usingTURN) {
|
|
541
|
+
if (!this.observedTurnServer) {
|
|
542
|
+
this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
|
|
543
|
+
}
|
|
544
|
+
this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
|
|
545
|
+
} else if (wasUsingTURN) {
|
|
546
|
+
if (!this.usingTURN) {
|
|
547
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
433
550
|
this.calculatedScore.value = sample.score;
|
|
434
551
|
this.updated = now;
|
|
435
552
|
this._checkVisited();
|
|
553
|
+
|
|
554
|
+
this.emit('update');
|
|
436
555
|
}
|
|
437
556
|
|
|
438
557
|
private _checkVisited() {
|
|
@@ -540,12 +659,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
540
659
|
|
|
541
660
|
observedCertificate = new ObservedCertificate(stats.timestamp, stats.id, this);
|
|
542
661
|
|
|
662
|
+
observedCertificate.update(stats);
|
|
663
|
+
|
|
543
664
|
this.observedCertificates.set(stats.id, observedCertificate);
|
|
544
665
|
this.emit('added-certificate', observedCertificate);
|
|
666
|
+
} else {
|
|
667
|
+
observedCertificate.update(stats);
|
|
668
|
+
this.emit('updated-certificate', observedCertificate);
|
|
545
669
|
}
|
|
546
670
|
|
|
547
|
-
observedCertificate.update(stats);
|
|
548
|
-
|
|
549
671
|
return observedCertificate;
|
|
550
672
|
}
|
|
551
673
|
|
|
@@ -562,12 +684,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
562
684
|
|
|
563
685
|
observedCodec = new ObservedCodec(stats.timestamp, stats.id, stats.mimeType, this);
|
|
564
686
|
|
|
687
|
+
observedCodec.update(stats);
|
|
688
|
+
|
|
565
689
|
this.observedCodecs.set(stats.id, observedCodec);
|
|
566
690
|
this.emit('added-codec', observedCodec);
|
|
691
|
+
} else {
|
|
692
|
+
observedCodec.update(stats);
|
|
693
|
+
this.emit('updated-codec', observedCodec);
|
|
567
694
|
}
|
|
568
695
|
|
|
569
|
-
observedCodec.update(stats);
|
|
570
|
-
|
|
571
696
|
return observedCodec;
|
|
572
697
|
}
|
|
573
698
|
|
|
@@ -584,12 +709,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
584
709
|
|
|
585
710
|
observedDataChannel = new ObservedDataChannel(stats.timestamp, stats.id, this);
|
|
586
711
|
|
|
712
|
+
observedDataChannel.update(stats);
|
|
713
|
+
|
|
587
714
|
this.observedDataChannels.set(stats.id, observedDataChannel);
|
|
588
715
|
this.emit('added-data-channel', observedDataChannel);
|
|
716
|
+
} else {
|
|
717
|
+
observedDataChannel.update(stats);
|
|
718
|
+
this.emit('updated-data-channel', observedDataChannel);
|
|
589
719
|
}
|
|
590
720
|
|
|
591
|
-
observedDataChannel.update(stats);
|
|
592
|
-
|
|
593
721
|
return observedDataChannel;
|
|
594
722
|
}
|
|
595
723
|
|
|
@@ -606,12 +734,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
606
734
|
|
|
607
735
|
observedIceCandidate = new ObservedIceCandidate(stats.timestamp, stats.id, this);
|
|
608
736
|
|
|
737
|
+
observedIceCandidate.update(stats);
|
|
738
|
+
|
|
609
739
|
this.observedIceCandidates.set(stats.id, observedIceCandidate);
|
|
610
740
|
this.emit('added-ice-candidate', observedIceCandidate);
|
|
741
|
+
} else {
|
|
742
|
+
observedIceCandidate.update(stats);
|
|
743
|
+
this.emit('updated-ice-candidate', observedIceCandidate);
|
|
611
744
|
}
|
|
612
745
|
|
|
613
|
-
observedIceCandidate.update(stats);
|
|
614
|
-
|
|
615
746
|
return observedIceCandidate;
|
|
616
747
|
}
|
|
617
748
|
|
|
@@ -628,12 +759,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
628
759
|
|
|
629
760
|
observedIceCandidatePair = new ObservedIceCandidatePair(stats.timestamp, stats.id, this);
|
|
630
761
|
|
|
762
|
+
observedIceCandidatePair.update(stats);
|
|
763
|
+
|
|
631
764
|
this.observedIceCandidatesPair.set(stats.id, observedIceCandidatePair);
|
|
632
765
|
this.emit('added-ice-candidate-pair', observedIceCandidatePair);
|
|
766
|
+
} else {
|
|
767
|
+
observedIceCandidatePair.update(stats);
|
|
768
|
+
this.emit('updated-ice-candidate-pair', observedIceCandidatePair);
|
|
633
769
|
}
|
|
634
770
|
|
|
635
|
-
observedIceCandidatePair.update(stats);
|
|
636
|
-
|
|
637
771
|
return observedIceCandidatePair;
|
|
638
772
|
}
|
|
639
773
|
|
|
@@ -650,12 +784,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
650
784
|
|
|
651
785
|
observedIceTransport = new ObservedIceTransport(stats.timestamp, stats.id, this);
|
|
652
786
|
|
|
787
|
+
observedIceTransport.update(stats);
|
|
788
|
+
|
|
653
789
|
this.observedIceTransports.set(stats.id, observedIceTransport);
|
|
654
790
|
this.emit('added-ice-transport', observedIceTransport);
|
|
791
|
+
} else {
|
|
792
|
+
observedIceTransport.update(stats);
|
|
793
|
+
this.emit('updated-ice-transport', observedIceTransport);
|
|
655
794
|
}
|
|
656
795
|
|
|
657
|
-
observedIceTransport.update(stats);
|
|
658
|
-
|
|
659
796
|
return observedIceTransport;
|
|
660
797
|
}
|
|
661
798
|
|
|
@@ -678,13 +815,16 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
678
815
|
stats.trackIdentifier,
|
|
679
816
|
this
|
|
680
817
|
);
|
|
818
|
+
|
|
819
|
+
observedInboundRtp.update(stats);
|
|
681
820
|
|
|
682
821
|
this.observedInboundRtps.set(stats.ssrc, observedInboundRtp);
|
|
683
822
|
this.emit('added-inbound-rtp', observedInboundRtp);
|
|
823
|
+
} else {
|
|
824
|
+
observedInboundRtp.update(stats);
|
|
825
|
+
this.emit('updated-inbound-rtp', observedInboundRtp);
|
|
684
826
|
}
|
|
685
827
|
|
|
686
|
-
observedInboundRtp.update(stats);
|
|
687
|
-
|
|
688
828
|
return observedInboundRtp;
|
|
689
829
|
}
|
|
690
830
|
|
|
@@ -712,12 +852,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
712
852
|
mediaPlayout,
|
|
713
853
|
);
|
|
714
854
|
|
|
855
|
+
observedInboundTrack.update(stats);
|
|
856
|
+
|
|
715
857
|
this.observedInboundTracks.set(stats.id, observedInboundTrack);
|
|
716
858
|
this.emit('added-inbound-track', observedInboundTrack);
|
|
859
|
+
} else {
|
|
860
|
+
observedInboundTrack.update(stats);
|
|
861
|
+
this.emit('updated-inbound-track', observedInboundTrack);
|
|
717
862
|
}
|
|
718
863
|
|
|
719
|
-
observedInboundTrack.update(stats);
|
|
720
|
-
|
|
721
864
|
return observedInboundTrack;
|
|
722
865
|
}
|
|
723
866
|
|
|
@@ -739,12 +882,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
739
882
|
this
|
|
740
883
|
);
|
|
741
884
|
|
|
885
|
+
observedMediaPlayout.update(stats);
|
|
886
|
+
|
|
742
887
|
this.observedMediaPlayouts.set(stats.id, observedMediaPlayout);
|
|
743
888
|
this.emit('added-media-playout', observedMediaPlayout);
|
|
889
|
+
} else {
|
|
890
|
+
observedMediaPlayout.update(stats);
|
|
891
|
+
this.emit('updated-media-playout', observedMediaPlayout);
|
|
744
892
|
}
|
|
745
893
|
|
|
746
|
-
observedMediaPlayout.update(stats);
|
|
747
|
-
|
|
748
894
|
return observedMediaPlayout;
|
|
749
895
|
}
|
|
750
896
|
|
|
@@ -766,12 +912,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
766
912
|
this
|
|
767
913
|
);
|
|
768
914
|
|
|
915
|
+
observedMediaSource.update(stats);
|
|
916
|
+
|
|
769
917
|
this.observedMediaSources.set(stats.id, observedMediaSource);
|
|
770
918
|
this.emit('added-media-source', observedMediaSource);
|
|
919
|
+
} else {
|
|
920
|
+
observedMediaSource.update(stats);
|
|
921
|
+
this.emit('updated-media-source', observedMediaSource);
|
|
771
922
|
}
|
|
772
923
|
|
|
773
|
-
observedMediaSource.update(stats);
|
|
774
|
-
|
|
775
924
|
return observedMediaSource;
|
|
776
925
|
}
|
|
777
926
|
|
|
@@ -794,11 +943,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
794
943
|
this
|
|
795
944
|
);
|
|
796
945
|
|
|
946
|
+
observedOutboundRtp.update(stats);
|
|
947
|
+
|
|
797
948
|
this.observedOutboundRtps.set(stats.ssrc, observedOutboundRtp);
|
|
798
949
|
this.emit('added-outbound-rtp', observedOutboundRtp);
|
|
950
|
+
} else {
|
|
951
|
+
observedOutboundRtp.update(stats);
|
|
952
|
+
this.emit('updated-outbound-rtp', observedOutboundRtp);
|
|
799
953
|
}
|
|
800
|
-
|
|
801
|
-
observedOutboundRtp.update(stats);
|
|
802
954
|
|
|
803
955
|
return observedOutboundRtp;
|
|
804
956
|
}
|
|
@@ -826,12 +978,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
826
978
|
observedMediaSource,
|
|
827
979
|
);
|
|
828
980
|
|
|
981
|
+
observedOutboundTrack.update(stats);
|
|
982
|
+
|
|
829
983
|
this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
|
|
830
984
|
this.emit('added-outbound-track', observedOutboundTrack);
|
|
985
|
+
} else {
|
|
986
|
+
observedOutboundTrack.update(stats);
|
|
987
|
+
this.emit('updated-outbound-track', observedOutboundTrack);
|
|
831
988
|
}
|
|
832
989
|
|
|
833
|
-
observedOutboundTrack.update(stats);
|
|
834
|
-
|
|
835
990
|
return observedOutboundTrack;
|
|
836
991
|
}
|
|
837
992
|
|
|
@@ -848,12 +1003,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
848
1003
|
|
|
849
1004
|
observedPeerConnectionTransport = new ObservedPeerConnectionTransport(stats.timestamp, stats.id, this);
|
|
850
1005
|
|
|
1006
|
+
observedPeerConnectionTransport.update(stats);
|
|
1007
|
+
|
|
851
1008
|
this.observedPeerConnectionTransports.set(stats.id, observedPeerConnectionTransport);
|
|
852
1009
|
this.emit('added-peer-connection-transport', observedPeerConnectionTransport);
|
|
1010
|
+
} else {
|
|
1011
|
+
observedPeerConnectionTransport.update(stats);
|
|
1012
|
+
this.emit('updated-peer-connection-transport', observedPeerConnectionTransport);
|
|
853
1013
|
}
|
|
854
1014
|
|
|
855
|
-
observedPeerConnectionTransport.update(stats);
|
|
856
|
-
|
|
857
1015
|
return observedPeerConnectionTransport;
|
|
858
1016
|
}
|
|
859
1017
|
|
|
@@ -876,12 +1034,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
876
1034
|
this
|
|
877
1035
|
);
|
|
878
1036
|
|
|
1037
|
+
observedRemoteInboundRtp.update(stats);
|
|
1038
|
+
|
|
879
1039
|
this.observedRemoteInboundRtps.set(stats.ssrc, observedRemoteInboundRtp);
|
|
880
1040
|
this.emit('added-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
1041
|
+
} else {
|
|
1042
|
+
observedRemoteInboundRtp.update(stats);
|
|
1043
|
+
this.emit('updated-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
881
1044
|
}
|
|
882
1045
|
|
|
883
|
-
observedRemoteInboundRtp.update(stats);
|
|
884
|
-
|
|
885
1046
|
return observedRemoteInboundRtp;
|
|
886
1047
|
}
|
|
887
1048
|
|
|
@@ -904,12 +1065,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
904
1065
|
this
|
|
905
1066
|
);
|
|
906
1067
|
|
|
1068
|
+
observedRemoteOutboundRtp.update(stats);
|
|
1069
|
+
|
|
907
1070
|
this.observedRemoteOutboundRtps.set(stats.ssrc, observedRemoteOutboundRtp);
|
|
908
1071
|
this.emit('added-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
1072
|
+
} else {
|
|
1073
|
+
observedRemoteOutboundRtp.update(stats);
|
|
1074
|
+
this.emit('updated-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
909
1075
|
}
|
|
910
1076
|
|
|
911
|
-
observedRemoteOutboundRtp.update(stats);
|
|
912
|
-
|
|
913
1077
|
return observedRemoteOutboundRtp;
|
|
914
1078
|
}
|
|
915
1079
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { EventEmitter } from 'stream';
|
|
2
|
+
import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
3
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
4
|
+
import { createLogger } from './common/logger';
|
|
5
|
+
|
|
6
|
+
const logger = createLogger('ObservedTURN');
|
|
7
|
+
|
|
8
|
+
export type ObservedTURNEventMap = {
|
|
9
|
+
'update': [ObservedTURN];
|
|
10
|
+
'close': [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export declare interface ObservedTURN {
|
|
14
|
+
on<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
15
|
+
off<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
16
|
+
once<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
17
|
+
emit<U extends keyof ObservedTURNEventMap>(event: U, ...args: ObservedTURNEventMap[U]): boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ObservedTURN extends EventEmitter {
|
|
21
|
+
public totalBytesSent = 0;
|
|
22
|
+
public totalBytesReceived = 0;
|
|
23
|
+
public totalPacketsSent = 0;
|
|
24
|
+
public totalPacketsReceived = 0;
|
|
25
|
+
|
|
26
|
+
public packetsSentPerSecond = 0;
|
|
27
|
+
public packetsReceivedPerSecond = 0;
|
|
28
|
+
public outboundBitrate = 0;
|
|
29
|
+
public inboundBitrate = 0;
|
|
30
|
+
public numberOfClients = 0;
|
|
31
|
+
|
|
32
|
+
public readonly servers = new Map<string, ObservedTurnServer>();
|
|
33
|
+
|
|
34
|
+
public constructor(
|
|
35
|
+
) {
|
|
36
|
+
super();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public update() {
|
|
40
|
+
const clientIds = new Set<string>();
|
|
41
|
+
|
|
42
|
+
this.packetsReceivedPerSecond = 0;
|
|
43
|
+
this.packetsSentPerSecond = 0;
|
|
44
|
+
this.outboundBitrate = 0;
|
|
45
|
+
this.inboundBitrate = 0;
|
|
46
|
+
|
|
47
|
+
for (const server of this.servers.values()) {
|
|
48
|
+
server.update();
|
|
49
|
+
server.observedPeerConnections.forEach((pc) => clientIds.add(pc.client.clientId));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.numberOfClients = clientIds.size;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public addPeerConnection(peerConnection: ObservedPeerConnection) {
|
|
56
|
+
const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => pair.getLocalCandidate()?.candidateType === 'relay' && pair.getRemoteCandidate()?.url?.startsWith('turn:'));
|
|
57
|
+
|
|
58
|
+
if (turnPairs.length !== 1) {
|
|
59
|
+
return (logger.warn(`Expected exactly one TURN pair, but found for peerconnection ${peerConnection.peerConnectionId}`, turnPairs.length), undefined);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const candidatePair = turnPairs[0];
|
|
63
|
+
const rawUrl = candidatePair.getRemoteCandidate()?.url;
|
|
64
|
+
|
|
65
|
+
if (!rawUrl) {
|
|
66
|
+
return (logger.warn(`No remote candidate URL found for peerconnection ${peerConnection.peerConnectionId}`), undefined);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const turnUrl = new URL(rawUrl);
|
|
70
|
+
const turnServerUrl = `${turnUrl.protocol}//${turnUrl.hostname}:${turnUrl.port}`;
|
|
71
|
+
let turnServer = this.servers.get(turnServerUrl);
|
|
72
|
+
|
|
73
|
+
if (!turnServer) {
|
|
74
|
+
turnServer = new ObservedTurnServer(turnServerUrl, this);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return turnServer;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public removePeerConnection(peerConnection: ObservedPeerConnection) {
|
|
81
|
+
for (const turnServer of this.servers.values()) {
|
|
82
|
+
turnServer.observedPeerConnections.delete(peerConnection.peerConnectionId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|