@observertc/observer-js 0.42.8 → 1.0.0-beta.1
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/.prettierrc +6 -6
- package/README.md +493 -63
- package/lib/ObservedCall.d.ts +63 -43
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +188 -108
- 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/ObservedCertificate.d.ts +19 -0
- package/lib/ObservedCertificate.d.ts.map +1 -0
- package/lib/ObservedCertificate.js +38 -0
- package/lib/ObservedClient.d.ts +81 -136
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +581 -744
- package/lib/ObservedClientEventMonitor.d.ts +91 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +254 -0
- package/lib/ObservedClientSummary.d.ts +23 -0
- package/lib/ObservedClientSummary.d.ts.map +1 -0
- package/lib/ObservedClientSummary.js +2 -0
- package/lib/ObservedCodec.d.ts +22 -0
- package/lib/ObservedCodec.d.ts.map +1 -0
- package/lib/ObservedCodec.js +45 -0
- package/lib/ObservedDataChannel.d.ts +25 -69
- package/lib/ObservedDataChannel.d.ts.map +1 -1
- package/lib/ObservedDataChannel.js +69 -109
- package/lib/ObservedIceCandidate.d.ts +29 -0
- package/lib/ObservedIceCandidate.d.ts.map +1 -0
- package/lib/ObservedIceCandidate.js +59 -0
- package/lib/ObservedIceCandidatePair.d.ts +45 -0
- package/lib/ObservedIceCandidatePair.d.ts.map +1 -0
- package/lib/ObservedIceCandidatePair.js +127 -0
- package/lib/ObservedIceTransport.d.ts +36 -0
- package/lib/ObservedIceTransport.d.ts.map +1 -0
- package/lib/ObservedIceTransport.js +93 -0
- package/lib/ObservedInboundRtp.d.ts +92 -0
- package/lib/ObservedInboundRtp.d.ts.map +1 -0
- package/lib/ObservedInboundRtp.js +193 -0
- package/lib/ObservedInboundTrack.d.ts +32 -0
- package/lib/ObservedInboundTrack.d.ts.map +1 -0
- package/lib/ObservedInboundTrack.js +60 -0
- package/lib/ObservedMediaPlayout.d.ts +22 -0
- package/lib/ObservedMediaPlayout.d.ts.map +1 -0
- package/lib/ObservedMediaPlayout.js +42 -0
- package/lib/ObservedMediaSource.d.ts +28 -0
- package/lib/ObservedMediaSource.d.ts.map +1 -0
- package/lib/ObservedMediaSource.js +55 -0
- package/lib/ObservedOutboundRtp.d.ts +62 -0
- package/lib/ObservedOutboundRtp.d.ts.map +1 -0
- package/lib/ObservedOutboundRtp.js +144 -0
- package/lib/ObservedOutboundTrack.d.ts +32 -0
- package/lib/ObservedOutboundTrack.d.ts.map +1 -0
- package/lib/ObservedOutboundTrack.js +60 -0
- package/lib/ObservedPeerConnection.d.ts +154 -80
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +709 -357
- package/lib/ObservedPeerConnectionTransport.d.ts +17 -0
- package/lib/ObservedPeerConnectionTransport.d.ts.map +1 -0
- package/lib/ObservedPeerConnectionTransport.js +34 -0
- package/lib/ObservedRemoteInboundRtp.d.ts +30 -0
- package/lib/ObservedRemoteInboundRtp.d.ts.map +1 -0
- package/lib/ObservedRemoteInboundRtp.js +60 -0
- package/lib/ObservedRemoteOutboundRtp.d.ts +30 -0
- package/lib/ObservedRemoteOutboundRtp.d.ts.map +1 -0
- package/lib/ObservedRemoteOutboundRtp.js +60 -0
- 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 +49 -54
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +131 -226
- package/lib/ObserverEventMonitor.d.ts +138 -0
- package/lib/ObserverEventMonitor.d.ts.map +1 -0
- package/lib/ObserverEventMonitor.js +433 -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/Middleware.d.ts +10 -1
- package/lib/common/Middleware.d.ts.map +1 -1
- package/lib/common/Middleware.js +55 -36
- package/lib/common/logger.d.ts +8 -4
- package/lib/common/logger.d.ts.map +1 -1
- package/lib/common/logger.js +44 -68
- package/lib/common/types.d.ts +0 -21
- package/lib/common/types.d.ts.map +1 -1
- package/lib/common/types.js +1 -0
- package/lib/common/utils.d.ts +3 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +23 -3
- package/lib/detectors/Detector.d.ts +5 -0
- package/lib/detectors/Detector.d.ts.map +1 -0
- package/lib/detectors/Detector.js +3 -0
- package/lib/detectors/Detectors.d.ts +11 -0
- package/lib/detectors/Detectors.d.ts.map +1 -0
- package/lib/detectors/Detectors.js +34 -0
- package/lib/index.d.ts +26 -24
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +45 -41
- package/lib/mediasoup/ObservedMediaRouter.d.ts +10 -0
- package/lib/mediasoup/ObservedMediaRouter.d.ts.map +1 -0
- package/lib/mediasoup/ObservedMediaRouter.js +6 -0
- package/lib/monitors/TurnUsageMonitor.d.ts +0 -52
- package/lib/monitors/TurnUsageMonitor.d.ts.map +1 -1
- package/lib/monitors/TurnUsageMonitor.js +145 -120
- package/lib/schema/ClientEventTypes.d.ts +228 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -0
- package/lib/schema/ClientEventTypes.js +41 -0
- package/lib/schema/ClientMetaTypes.d.ts +34 -0
- package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
- package/lib/schema/ClientMetaTypes.js +16 -0
- package/lib/schema/ClientSample.d.ts +1333 -0
- package/lib/schema/ClientSample.d.ts.map +1 -0
- package/lib/schema/ClientSample.js +4 -0
- package/lib/scores/CalculatedScore.d.ts +6 -0
- package/lib/scores/CalculatedScore.d.ts.map +1 -0
- package/lib/scores/CalculatedScore.js +2 -0
- package/lib/scores/DefaultCallScoreCalculator.d.ts +7 -0
- package/lib/scores/DefaultCallScoreCalculator.d.ts.map +1 -0
- package/lib/scores/DefaultCallScoreCalculator.js +21 -0
- package/lib/scores/ScoreCalculator.d.ts +4 -0
- package/lib/scores/ScoreCalculator.d.ts.map +1 -0
- package/lib/scores/ScoreCalculator.js +2 -0
- package/lib/updaters/CallUpdater.d.ts +5 -0
- 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/lib/utils/RemoteTrackResolver.d.ts +7 -0
- package/lib/utils/RemoteTrackResolver.d.ts.map +1 -0
- package/lib/utils/RemoteTrackResolver.js +2 -0
- package/package.json +4 -4
- package/src/ObservedCall.ts +276 -164
- package/src/ObservedCallEventMonitor.ts +392 -0
- package/src/ObservedCallSummary.ts +22 -0
- package/src/ObservedCertificate.ts +43 -0
- package/src/ObservedClient.ts +625 -1006
- package/src/ObservedClientEventMonitor.ts +309 -0
- package/src/ObservedClientSummary.ts +24 -0
- package/src/ObservedCodec.ts +49 -0
- package/src/ObservedDataChannel.ts +71 -181
- package/src/ObservedIceCandidate.ts +64 -0
- package/src/ObservedIceCandidatePair.ts +134 -0
- package/src/ObservedIceTransport.ts +99 -0
- package/src/ObservedInboundRtp.ts +205 -0
- package/src/ObservedInboundTrack.ts +75 -0
- package/src/ObservedMediaPlayout.ts +49 -0
- package/src/ObservedMediaSource.ts +60 -0
- package/src/ObservedOutboundRtp.ts +156 -0
- package/src/ObservedOutboundTrack.ts +74 -0
- package/src/ObservedPeerConnection.ts +917 -402
- package/src/ObservedPeerConnectionTransport.ts +38 -0
- package/src/ObservedRemoteInboundRtp.ts +64 -0
- package/src/ObservedRemoteOutboundRtp.ts +65 -0
- package/src/ObservedTURN.ts +86 -0
- package/src/ObservedTurnServer.ts +72 -0
- package/src/Observer.ts +182 -298
- package/src/ObserverEventMonitor.ts +551 -0
- package/src/ObserverSummary.ts +15 -0
- package/src/common/Middleware.ts +70 -42
- package/src/common/logger.ts +60 -69
- package/src/common/types.ts +0 -42
- package/src/common/utils.ts +24 -2
- package/src/detectors/Detector.ts +6 -0
- package/src/detectors/Detectors.ts +38 -0
- package/src/index.ts +26 -88
- package/src/mediasoup/ObservedMediaRouter.ts +10 -0
- package/src/monitors/TurnUsageMonitor.ts +164 -164
- package/src/schema/ClientEventTypes.ts +280 -0
- package/src/schema/ClientMetaTypes.ts +41 -0
- package/src/schema/ClientSample.ts +1682 -0
- package/src/scores/CalculatedScore.ts +6 -0
- package/src/scores/DefaultCallScoreCalculator.ts +23 -0
- package/src/scores/ScoreCalculator.ts +3 -0
- package/src/updaters/CallUpdater.ts +5 -0
- 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/src/utils/RemoteTrackResolver.ts +12 -0
- package/tsconfig.json +3 -3
- package/lib/ObservedICE.d.ts +0 -64
- package/lib/ObservedICE.d.ts.map +0 -1
- package/lib/ObservedICE.js +0 -141
- package/lib/ObservedInboundAudioTrack.d.ts +0 -96
- package/lib/ObservedInboundAudioTrack.d.ts.map +0 -1
- package/lib/ObservedInboundAudioTrack.js +0 -217
- package/lib/ObservedInboundVideoTrack.d.ts +0 -101
- package/lib/ObservedInboundVideoTrack.d.ts.map +0 -1
- package/lib/ObservedInboundVideoTrack.js +0 -232
- package/lib/ObservedOutboundAudioTrack.d.ts +0 -87
- package/lib/ObservedOutboundAudioTrack.d.ts.map +0 -1
- package/lib/ObservedOutboundAudioTrack.js +0 -186
- package/lib/ObservedOutboundVideoTrack.d.ts +0 -91
- package/lib/ObservedOutboundVideoTrack.d.ts.map +0 -1
- package/lib/ObservedOutboundVideoTrack.js +0 -193
- package/lib/ObservedSfu.d.ts +0 -59
- package/lib/ObservedSfu.d.ts.map +0 -1
- package/lib/ObservedSfu.js +0 -157
- package/lib/ObservedSfuInboundRtpPad.d.ts +0 -42
- package/lib/ObservedSfuInboundRtpPad.d.ts.map +0 -1
- package/lib/ObservedSfuInboundRtpPad.js +0 -71
- package/lib/ObservedSfuOutboundRtpPad.d.ts +0 -42
- package/lib/ObservedSfuOutboundRtpPad.d.ts.map +0 -1
- package/lib/ObservedSfuOutboundRtpPad.js +0 -72
- package/lib/ObservedSfuSctpChannel.d.ts +0 -42
- package/lib/ObservedSfuSctpChannel.d.ts.map +0 -1
- package/lib/ObservedSfuSctpChannel.js +0 -57
- package/lib/ObservedSfuTransport.d.ts +0 -58
- package/lib/ObservedSfuTransport.d.ts.map +0 -1
- package/lib/ObservedSfuTransport.js +0 -120
- package/lib/RemoteTrackAssigner.d.ts +0 -14
- package/lib/RemoteTrackAssigner.d.ts.map +0 -1
- package/lib/RemoteTrackAssigner.js +0 -52
- package/lib/ReportsCollector.d.ts +0 -109
- package/lib/ReportsCollector.d.ts.map +0 -1
- package/lib/ReportsCollector.js +0 -207
- package/lib/common/CalculatedScore.d.ts +0 -80
- package/lib/common/CalculatedScore.d.ts.map +0 -1
- package/lib/common/CalculatedScore.js +0 -162
- package/lib/common/CallEventType.d.ts +0 -63
- package/lib/common/CallEventType.d.ts.map +0 -1
- package/lib/common/CallEventType.js +0 -39
- package/lib/common/CallMetaReports.d.ts +0 -42
- package/lib/common/CallMetaReports.d.ts.map +0 -1
- package/lib/common/CallMetaReports.js +0 -36
- package/lib/common/QualityScoreUtils.d.ts +0 -1
- package/lib/common/QualityScoreUtils.d.ts.map +0 -1
- package/lib/common/QualityScoreUtils.js +0 -1
- package/lib/common/TypedEventEmitter.d.ts +0 -22
- package/lib/common/TypedEventEmitter.d.ts.map +0 -1
- package/lib/common/TypedEventEmitter.js +0 -11
- package/lib/common/callEventReports.d.ts +0 -10
- package/lib/common/callEventReports.d.ts.map +0 -1
- package/lib/common/callEventReports.js +0 -112
- package/lib/monitors/CallSummary.d.ts +0 -37
- package/lib/monitors/CallSummary.d.ts.map +0 -1
- package/lib/monitors/CallSummaryMonitor.d.ts +0 -32
- package/lib/monitors/CallSummaryMonitor.d.ts.map +0 -1
- package/lib/monitors/CallSummaryMonitor.js +0 -152
- package/lib/monitors/ClientIssueMonitor.d.ts +0 -32
- package/lib/monitors/ClientIssueMonitor.d.ts.map +0 -1
- package/lib/monitors/ClientIssueMonitor.js +0 -49
- package/lib/monitors/SfuServerMonitor.d.ts +0 -79
- package/lib/monitors/SfuServerMonitor.d.ts.map +0 -1
- package/lib/monitors/SfuServerMonitor.js +0 -198
- package/src/ObservedICE.ts +0 -237
- package/src/ObservedInboundAudioTrack.ts +0 -344
- package/src/ObservedInboundVideoTrack.ts +0 -361
- package/src/ObservedOutboundAudioTrack.ts +0 -307
- package/src/ObservedOutboundVideoTrack.ts +0 -319
- package/src/ObservedSfu.ts +0 -231
- package/src/ObservedSfuInboundRtpPad.ts +0 -106
- package/src/ObservedSfuOutboundRtpPad.ts +0 -107
- package/src/ObservedSfuSctpChannel.ts +0 -103
- package/src/ObservedSfuTransport.ts +0 -185
- package/src/RemoteTrackAssigner.ts +0 -68
- package/src/ReportsCollector.ts +0 -336
- package/src/common/CalculatedScore.ts +0 -188
- package/src/common/CallEventType.ts +0 -69
- package/src/common/CallMetaReports.ts +0 -82
- package/src/common/QualityScoreUtils.ts +0 -0
- package/src/common/TypedEventEmitter.ts +0 -32
- package/src/common/callEventReports.ts +0 -178
- package/src/monitors/CallSummary.ts +0 -38
- package/src/monitors/CallSummaryMonitor.ts +0 -192
- package/src/monitors/ClientIssueMonitor.ts +0 -88
- package/src/monitors/SfuServerMonitor.ts +0 -285
- /package/lib/{monitors/CallSummary.js → ObservedCallSummary.js} +0 -0
|
@@ -1,65 +1,146 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import { PeerConnectionTransport } from '@observertc/sample-schemas-js';
|
|
3
2
|
import { ObservedClient } from './ObservedClient';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { CertificateStats, CodecStats, DataChannelStats, IceCandidateStats, InboundRtpStats, InboundTrackSample, MediaPlayoutStats, MediaSourceStats, OutboundRtpStats, OutboundTrackSample, PeerConnectionSample, PeerConnectionTransportStats, RemoteInboundRtpStats, RemoteOutboundRtpStats } from './schema/ClientSample';
|
|
4
|
+
import { ObservedInboundRtp } from './ObservedInboundRtp';
|
|
5
|
+
import { createLogger } from './common/logger';
|
|
6
|
+
import { MediaKind } from './common/types';
|
|
7
|
+
import { ObservedOutboundRtp } from './ObservedOutboundRtp';
|
|
8
|
+
import { ObservedCertificate } from './ObservedCertificate';
|
|
9
|
+
import { ObservedCodec } from './ObservedCodec';
|
|
6
10
|
import { ObservedDataChannel } from './ObservedDataChannel';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { ObservedIceCandidate } from './ObservedIceCandidate';
|
|
12
|
+
import { ObservedIceCandidatePair } from './ObservedIceCandidatePair';
|
|
13
|
+
import { ObservedIceTransport } from './ObservedIceTransport';
|
|
14
|
+
import { ObservedMediaSource } from './ObservedMediaSource';
|
|
15
|
+
import { ObservedPeerConnectionTransport } from './ObservedPeerConnectionTransport';
|
|
16
|
+
import { ObservedMediaPlayout } from './ObservedMediaPlayout';
|
|
17
|
+
import { ObservedRemoteInboundRtp } from './ObservedRemoteInboundRtp';
|
|
18
|
+
import { ObservedRemoteOutboundRtp } from './ObservedRemoteOutboundRtp';
|
|
19
|
+
import { ObservedInboundTrack } from './ObservedInboundTrack';
|
|
20
|
+
import { ObservedOutboundTrack } from './ObservedOutboundTrack';
|
|
21
|
+
import { CalculatedScore } from './scores/CalculatedScore';
|
|
22
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
23
|
+
import { getMedian } from './common/utils';
|
|
24
|
+
|
|
25
|
+
const logger = createLogger('ObservedPeerConnection');
|
|
14
26
|
|
|
15
27
|
export type ObservedPeerConnectionEvents = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
iceconnectionstatechange: [
|
|
29
|
+
{
|
|
30
|
+
state: string;
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
icegatheringstatechange: [
|
|
34
|
+
{
|
|
35
|
+
state: string;
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
connectionstatechange: [
|
|
39
|
+
{
|
|
40
|
+
state: string;
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
selectedcandidatepair: [];
|
|
44
|
+
|
|
45
|
+
'added-certificate': [ObservedCertificate];
|
|
46
|
+
'added-codec': [ObservedCodec];
|
|
47
|
+
'added-data-channel': [ObservedDataChannel];
|
|
48
|
+
'added-ice-candidate': [ObservedIceCandidate];
|
|
49
|
+
'added-ice-candidate-pair': [ObservedIceCandidatePair];
|
|
50
|
+
'added-ice-transport': [ObservedIceTransport];
|
|
51
|
+
'added-inbound-rtp': [ObservedInboundRtp];
|
|
52
|
+
'added-inbound-track': [ObservedInboundTrack];
|
|
53
|
+
'added-media-playout': [ObservedMediaPlayout];
|
|
54
|
+
'added-media-source': [ObservedMediaSource];
|
|
55
|
+
'added-outbound-rtp': [ObservedOutboundRtp];
|
|
56
|
+
'added-outbound-track': [ObservedOutboundTrack];
|
|
57
|
+
'added-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
58
|
+
'added-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
59
|
+
'added-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
60
|
+
'removed-certificate': [ObservedCertificate];
|
|
61
|
+
'removed-codec': [ObservedCodec];
|
|
62
|
+
'removed-data-channel': [ObservedDataChannel];
|
|
63
|
+
'removed-ice-candidate': [ObservedIceCandidate];
|
|
64
|
+
'removed-ice-candidate-pair': [ObservedIceCandidatePair];
|
|
65
|
+
'removed-ice-transport': [ObservedIceTransport];
|
|
66
|
+
'removed-inbound-rtp': [ObservedInboundRtp];
|
|
67
|
+
'removed-inbound-track': [ObservedInboundTrack];
|
|
68
|
+
'removed-media-playout': [ObservedMediaPlayout];
|
|
69
|
+
'removed-media-source': [ObservedMediaSource];
|
|
70
|
+
'removed-outbound-rtp': [ObservedOutboundRtp];
|
|
71
|
+
'removed-outbound-track': [ObservedOutboundTrack];
|
|
72
|
+
'removed-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
73
|
+
'removed-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
74
|
+
'removed-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
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
|
+
'muted-inbound-track': [ObservedInboundTrack];
|
|
91
|
+
'muted-outbound-track': [ObservedOutboundTrack];
|
|
92
|
+
'unmuted-inbound-track': [ObservedInboundTrack];
|
|
93
|
+
'unmuted-outbound-track': [ObservedOutboundTrack];
|
|
94
|
+
|
|
95
|
+
'update': [],
|
|
96
|
+
close: [];
|
|
31
97
|
};
|
|
32
98
|
|
|
33
|
-
export type ObservedPeerConnectionStats = Omit<PeerConnectionTransport, 'transportId' | 'label'>;
|
|
34
|
-
|
|
35
99
|
export declare interface ObservedPeerConnection {
|
|
36
|
-
on<U extends keyof ObservedPeerConnectionEvents>(
|
|
37
|
-
|
|
38
|
-
|
|
100
|
+
on<U extends keyof ObservedPeerConnectionEvents>(
|
|
101
|
+
event: U,
|
|
102
|
+
listener: (...args: ObservedPeerConnectionEvents[U]) => void
|
|
103
|
+
): this;
|
|
104
|
+
off<U extends keyof ObservedPeerConnectionEvents>(
|
|
105
|
+
event: U,
|
|
106
|
+
listener: (...args: ObservedPeerConnectionEvents[U]) => void
|
|
107
|
+
): this;
|
|
108
|
+
once<U extends keyof ObservedPeerConnectionEvents>(
|
|
109
|
+
event: U,
|
|
110
|
+
listener: (...args: ObservedPeerConnectionEvents[U]) => void
|
|
111
|
+
): this;
|
|
39
112
|
emit<U extends keyof ObservedPeerConnectionEvents>(event: U, ...args: ObservedPeerConnectionEvents[U]): boolean;
|
|
40
113
|
}
|
|
41
114
|
|
|
42
115
|
export class ObservedPeerConnection extends EventEmitter {
|
|
43
|
-
|
|
44
|
-
public visited = true;
|
|
116
|
+
private _visited = true;
|
|
45
117
|
|
|
118
|
+
public appData?: Record<string, unknown>;
|
|
119
|
+
public readonly calculatedScore: CalculatedScore = {
|
|
120
|
+
weight: 1,
|
|
121
|
+
value: undefined,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
public closed = false;
|
|
46
125
|
// timestamp of the PEER_CONNECTION_OPENED event
|
|
47
|
-
public
|
|
126
|
+
public openedAt?: number;
|
|
48
127
|
// timestamp of the PEER_CONNECTION_CLOSED event
|
|
49
|
-
public
|
|
50
|
-
|
|
51
|
-
private _elapsedTimeSinceLastUpdate?: number;
|
|
52
|
-
private _statsTimestamp?: number;
|
|
53
|
-
private _stabilityScores: number[] = [];
|
|
128
|
+
public closedAt?: number;
|
|
129
|
+
public updated = Date.now();
|
|
54
130
|
|
|
55
|
-
public
|
|
131
|
+
public connectionState?: string;
|
|
132
|
+
public iceConnectionState?: string;
|
|
133
|
+
public iceGatheringState?: string;
|
|
56
134
|
|
|
57
|
-
public
|
|
135
|
+
public availableIncomingBitrate = 0;
|
|
136
|
+
public availableOutgoingBitrate = 0;
|
|
58
137
|
public totalInboundPacketsLost = 0;
|
|
59
138
|
public totalInboundPacketsReceived = 0;
|
|
60
139
|
public totalOutboundPacketsSent = 0;
|
|
61
140
|
public totalDataChannelBytesSent = 0;
|
|
62
141
|
public totalDataChannelBytesReceived = 0;
|
|
142
|
+
public totalDataChannelMessagesSent = 0;
|
|
143
|
+
public totalDataChannelMessagesReceived = 0;
|
|
63
144
|
|
|
64
145
|
public totalSentAudioBytes = 0;
|
|
65
146
|
public totalSentVideoBytes = 0;
|
|
@@ -75,182 +156,165 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
75
156
|
public deltaOutboundPacketsSent = 0;
|
|
76
157
|
public deltaDataChannelBytesSent = 0;
|
|
77
158
|
public deltaDataChannelBytesReceived = 0;
|
|
159
|
+
public deltaDataChannelMessagesSent = 0;
|
|
160
|
+
public deltaDataChannelMessagesReceived = 0;
|
|
78
161
|
public deltaInboundReceivedBytes = 0;
|
|
79
162
|
public deltaOutboundSentBytes = 0;
|
|
80
|
-
|
|
163
|
+
|
|
81
164
|
public deltaReceivedAudioBytes = 0;
|
|
82
165
|
public deltaReceivedVideoBytes = 0;
|
|
83
166
|
public deltaReceivedAudioPackets = 0;
|
|
84
167
|
public deltaReceivedVideoPackets = 0;
|
|
85
168
|
public deltaSentAudioBytes = 0;
|
|
86
169
|
public deltaSentVideoBytes = 0;
|
|
170
|
+
public deltaTransportSentBytes = 0;
|
|
171
|
+
public deltaTransportReceivedBytes = 0;
|
|
172
|
+
|
|
87
173
|
public receivingPacketsPerSecond = 0;
|
|
88
174
|
public sendingPacketsPerSecond = 0;
|
|
89
175
|
public sendingAudioBitrate = 0;
|
|
90
176
|
public sendingVideoBitrate = 0;
|
|
91
177
|
public receivingAudioBitrate = 0;
|
|
92
178
|
public receivingVideoBitrate = 0;
|
|
93
|
-
|
|
94
|
-
public
|
|
95
|
-
public
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
public readonly
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
public
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
179
|
+
|
|
180
|
+
public currentRttInMs?: number;
|
|
181
|
+
public currentJitter?: number;
|
|
182
|
+
|
|
183
|
+
public usingTCP = false;
|
|
184
|
+
public usingTURN = false;
|
|
185
|
+
|
|
186
|
+
public observedTurnServer?: ObservedTurnServer;
|
|
187
|
+
public readonly observedCertificates = new Map<string, ObservedCertificate>();
|
|
188
|
+
public readonly observedCodecs = new Map<string, ObservedCodec>();
|
|
189
|
+
public readonly observedDataChannels = new Map<string, ObservedDataChannel>();
|
|
190
|
+
public readonly observedIceCandidates = new Map<string, ObservedIceCandidate>();
|
|
191
|
+
public readonly observedIceCandidatesPair = new Map<string, ObservedIceCandidatePair>();
|
|
192
|
+
public readonly observedIceTransports = new Map<string, ObservedIceTransport>();
|
|
193
|
+
public readonly observedInboundRtps = new Map<number, ObservedInboundRtp>();
|
|
194
|
+
public readonly observedInboundTracks = new Map<string, ObservedInboundTrack>();
|
|
195
|
+
public readonly observedMediaPlayouts = new Map<string, ObservedMediaPlayout>();
|
|
196
|
+
public readonly observedMediaSources = new Map<string, ObservedMediaSource>();
|
|
197
|
+
public readonly observedOutboundRtps = new Map<number, ObservedOutboundRtp>();
|
|
198
|
+
public readonly observedOutboundTracks = new Map<string, ObservedOutboundTrack>();
|
|
199
|
+
public readonly observedPeerConnectionTransports = new Map<string, ObservedPeerConnectionTransport>();
|
|
200
|
+
public readonly observedRemoteInboundRtps = new Map<number, ObservedRemoteInboundRtp>();
|
|
201
|
+
public readonly observedRemoteOutboundRtps = new Map<number, ObservedRemoteOutboundRtp>();
|
|
202
|
+
|
|
203
|
+
public constructor(public readonly peerConnectionId: string, public readonly client: ObservedClient) {
|
|
113
204
|
super();
|
|
114
205
|
this.setMaxListeners(Infinity);
|
|
115
206
|
}
|
|
116
207
|
|
|
117
|
-
public get
|
|
118
|
-
return this.
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
public get roomId() {
|
|
122
|
-
return this.client.roomId;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public get callId() {
|
|
126
|
-
return this.client.callId;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
public get clientId() {
|
|
130
|
-
return this.client.clientId;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public get mediaUnitId() {
|
|
134
|
-
return this.client.mediaUnitId;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public get label() {
|
|
138
|
-
return this._model.label;
|
|
208
|
+
public get score() {
|
|
209
|
+
return this.calculatedScore.value;
|
|
139
210
|
}
|
|
140
211
|
|
|
141
|
-
public
|
|
142
|
-
|
|
143
|
-
}
|
|
212
|
+
public get visited() {
|
|
213
|
+
const visited = this._visited;
|
|
144
214
|
|
|
145
|
-
|
|
146
|
-
return this.ICE.usingTURN;
|
|
147
|
-
}
|
|
215
|
+
this._visited = false;
|
|
148
216
|
|
|
149
|
-
|
|
150
|
-
return this.ICE.stats?.availableOutgoingBitrate;
|
|
217
|
+
return visited;
|
|
151
218
|
}
|
|
152
219
|
|
|
153
|
-
public get
|
|
154
|
-
return this.
|
|
220
|
+
public get codecs() {
|
|
221
|
+
return [ ...this.observedCodecs.values() ];
|
|
155
222
|
}
|
|
156
223
|
|
|
157
|
-
public get
|
|
158
|
-
|
|
159
|
-
return this._model.peerConnectionId!;
|
|
224
|
+
public get inboundRtps() {
|
|
225
|
+
return [ ...this.observedInboundRtps.values() ];
|
|
160
226
|
}
|
|
161
227
|
|
|
162
|
-
public get
|
|
163
|
-
return this.
|
|
228
|
+
public get remoteOutboundRtps() {
|
|
229
|
+
return [ ...this.observedRemoteOutboundRtps.values() ];
|
|
164
230
|
}
|
|
165
231
|
|
|
166
|
-
public get
|
|
167
|
-
return this.
|
|
232
|
+
public get outboundRtps() {
|
|
233
|
+
return [ ...this.observedOutboundRtps.values() ];
|
|
168
234
|
}
|
|
169
235
|
|
|
170
|
-
public get
|
|
171
|
-
return this.
|
|
236
|
+
public get remoteInboundRtps() {
|
|
237
|
+
return [ ...this.observedRemoteInboundRtps.values() ];
|
|
172
238
|
}
|
|
173
239
|
|
|
174
|
-
public get
|
|
175
|
-
return this.
|
|
240
|
+
public get mediaSources() {
|
|
241
|
+
return [ ...this.observedMediaSources.values() ];
|
|
176
242
|
}
|
|
177
243
|
|
|
178
|
-
public get
|
|
179
|
-
return this.
|
|
244
|
+
public get mediaPlayouts() {
|
|
245
|
+
return [ ...this.observedMediaPlayouts.values() ];
|
|
180
246
|
}
|
|
181
247
|
|
|
182
|
-
public get
|
|
183
|
-
return this.
|
|
248
|
+
public get dataChannels() {
|
|
249
|
+
return [ ...this.observedDataChannels.values() ];
|
|
184
250
|
}
|
|
185
251
|
|
|
186
|
-
public get
|
|
187
|
-
return this.
|
|
252
|
+
public get peerConnectionTransports() {
|
|
253
|
+
return [ ...this.observedPeerConnectionTransports.values() ];
|
|
188
254
|
}
|
|
189
255
|
|
|
190
|
-
public get
|
|
191
|
-
return this.
|
|
256
|
+
public get iceTransports() {
|
|
257
|
+
return [ ...this.observedIceTransports.values() ];
|
|
192
258
|
}
|
|
193
259
|
|
|
194
|
-
public get
|
|
195
|
-
return this.
|
|
260
|
+
public get iceCandidates() {
|
|
261
|
+
return [ ...this.observedIceCandidates.values() ];
|
|
196
262
|
}
|
|
197
263
|
|
|
198
|
-
public get
|
|
199
|
-
return this.
|
|
264
|
+
public get iceCandidatePairs() {
|
|
265
|
+
return [ ...this.observedIceCandidatesPair.values() ];
|
|
200
266
|
}
|
|
201
267
|
|
|
202
|
-
public
|
|
203
|
-
this.
|
|
204
|
-
this._inboundAudioTracks.forEach((track) => (track.marker = value));
|
|
205
|
-
this._inboundVideoTracks.forEach((track) => (track.marker = value));
|
|
206
|
-
this._outboundAudioTracks.forEach((track) => (track.marker = value));
|
|
207
|
-
this._outboundVideoTracks.forEach((track) => (track.marker = value));
|
|
208
|
-
this._dataChannels.forEach((channel) => (channel.marker = value));
|
|
209
|
-
this.ICE.marker = value;
|
|
268
|
+
public get certificates() {
|
|
269
|
+
return [ ...this.observedCertificates.values() ];
|
|
210
270
|
}
|
|
211
271
|
|
|
212
|
-
public
|
|
213
|
-
this.
|
|
214
|
-
|
|
215
|
-
serviceId: this.serviceId,
|
|
216
|
-
mediaUnitId: this.mediaUnitId,
|
|
217
|
-
roomId: this.roomId,
|
|
218
|
-
callId: this.callId,
|
|
219
|
-
clientId: this.clientId,
|
|
220
|
-
userId: this.client.userId,
|
|
221
|
-
peerConnectionId: this.peerConnectionId,
|
|
222
|
-
marker: this.client.marker,
|
|
223
|
-
timestamp: params.timestamp ?? Date.now(),
|
|
224
|
-
});
|
|
272
|
+
public get selectedIceCandidatePairs() {
|
|
273
|
+
return this.iceTransports.map((iceTransport) => iceTransport.getSelectedCandidatePair())
|
|
274
|
+
.filter((pair) => pair !== undefined) as ObservedIceCandidatePair[];
|
|
225
275
|
}
|
|
226
276
|
|
|
227
|
-
public get
|
|
228
|
-
return this.
|
|
277
|
+
public get selectedIceCandiadtePairForTurn() {
|
|
278
|
+
return this.selectedIceCandidatePairs
|
|
279
|
+
.filter((pair) =>
|
|
280
|
+
pair.getLocalCandidate()?.candidateType === 'relay' &&
|
|
281
|
+
pair.getRemoteCandidate()?.url?.startsWith('turn:')
|
|
282
|
+
);
|
|
229
283
|
}
|
|
230
284
|
|
|
231
285
|
public close() {
|
|
232
|
-
if (this.
|
|
233
|
-
this.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
286
|
+
if (this.closed) return;
|
|
287
|
+
this.closed = true;
|
|
288
|
+
|
|
289
|
+
this.observedCertificates.clear();
|
|
290
|
+
this.observedCodecs.clear();
|
|
291
|
+
this.observedDataChannels.clear();
|
|
292
|
+
this.observedIceCandidates.clear();
|
|
293
|
+
this.observedIceCandidatesPair.clear();
|
|
294
|
+
this.observedIceTransports.clear();
|
|
295
|
+
this.observedInboundRtps.clear();
|
|
296
|
+
this.observedInboundTracks.clear();
|
|
297
|
+
this.observedMediaPlayouts.clear();
|
|
298
|
+
this.observedMediaSources.clear();
|
|
299
|
+
this.observedOutboundRtps.clear();
|
|
300
|
+
this.observedOutboundTracks.clear();
|
|
301
|
+
this.observedPeerConnectionTransports.clear();
|
|
302
|
+
this.observedRemoteInboundRtps.clear();
|
|
303
|
+
this.observedRemoteOutboundRtps.clear();
|
|
304
|
+
|
|
305
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
306
|
+
|
|
307
|
+
if (!this.closedAt) this.closedAt = Date.now();
|
|
308
|
+
|
|
246
309
|
this.emit('close');
|
|
247
310
|
}
|
|
248
311
|
|
|
249
|
-
public
|
|
250
|
-
|
|
251
|
-
|
|
312
|
+
public accept(sample: PeerConnectionSample) {
|
|
313
|
+
if (this.closed) return;
|
|
314
|
+
this._visited = true;
|
|
252
315
|
|
|
253
|
-
|
|
316
|
+
this.availableIncomingBitrate = 0;
|
|
317
|
+
this.availableOutgoingBitrate = 0;
|
|
254
318
|
this.deltaInboundPacketsLost = 0;
|
|
255
319
|
this.deltaInboundPacketsReceived = 0;
|
|
256
320
|
this.deltaOutboundPacketsSent = 0;
|
|
@@ -258,316 +322,767 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
258
322
|
this.deltaDataChannelBytesReceived = 0;
|
|
259
323
|
this.deltaInboundReceivedBytes = 0;
|
|
260
324
|
this.deltaOutboundSentBytes = 0;
|
|
261
|
-
|
|
262
325
|
this.deltaReceivedAudioBytes = 0;
|
|
263
326
|
this.deltaReceivedVideoBytes = 0;
|
|
264
327
|
this.deltaReceivedAudioPackets = 0;
|
|
265
328
|
this.deltaReceivedVideoPackets = 0;
|
|
266
329
|
this.deltaSentAudioBytes = 0;
|
|
267
330
|
this.deltaSentVideoBytes = 0;
|
|
331
|
+
this.deltaTransportReceivedBytes = 0;
|
|
332
|
+
this.deltaTransportSentBytes = 0;
|
|
333
|
+
|
|
268
334
|
this.sendingAudioBitrate = 0;
|
|
269
335
|
this.sendingVideoBitrate = 0;
|
|
270
336
|
this.receivingAudioBitrate = 0;
|
|
271
337
|
this.receivingVideoBitrate = 0;
|
|
272
338
|
|
|
273
|
-
|
|
339
|
+
const now = Date.now();
|
|
340
|
+
const elapsedTimeInMs = now - this.updated;
|
|
341
|
+
const elapsedTimeInSec = elapsedTimeInMs / 1000;
|
|
342
|
+
const rttMeasurementsInSec: number[] = [];
|
|
343
|
+
const jitterMeasurements: number[] = [];
|
|
344
|
+
|
|
345
|
+
if (sample.certificates) {
|
|
346
|
+
for (const certificate of sample.certificates) {
|
|
347
|
+
this._updateCertificateStats(certificate);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (sample.codecs) {
|
|
351
|
+
for (const codec of sample.codecs) {
|
|
352
|
+
this._updateCodecStats(codec);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (sample.dataChannels) {
|
|
356
|
+
for (const dataChannel of sample.dataChannels) {
|
|
357
|
+
const observedDataChannel = this._updateDataChannelStats(dataChannel);
|
|
358
|
+
|
|
359
|
+
if (!observedDataChannel) continue;
|
|
360
|
+
|
|
361
|
+
this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
|
|
362
|
+
this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
|
|
363
|
+
this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
|
|
364
|
+
this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (sample.iceCandidates) {
|
|
368
|
+
for (const iceCandidate of sample.iceCandidates) {
|
|
369
|
+
this._updateIceCandidateStats(iceCandidate);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (sample.iceCandidatePairs) {
|
|
373
|
+
for (const iceCandidatePair of sample.iceCandidatePairs) {
|
|
374
|
+
const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
|
|
375
|
+
|
|
376
|
+
if (!observedCandidatePair) continue;
|
|
377
|
+
|
|
378
|
+
if (observedCandidatePair.currentRoundTripTime) {
|
|
379
|
+
rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
|
|
380
|
+
}
|
|
381
|
+
if (observedCandidatePair.availableIncomingBitrate) {
|
|
382
|
+
this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
|
|
383
|
+
}
|
|
384
|
+
if (observedCandidatePair.availableOutgoingBitrate) {
|
|
385
|
+
this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (sample.iceTransports) {
|
|
390
|
+
for (const iceTransport of sample.iceTransports) {
|
|
391
|
+
const observedIceTransport = this._updateIceTransportStats(iceTransport);
|
|
392
|
+
|
|
393
|
+
if (!observedIceTransport) return;
|
|
394
|
+
|
|
395
|
+
observedIceTransport.bytesReceived;
|
|
396
|
+
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (sample.inboundRtps) {
|
|
400
|
+
for (const inboundRtp of sample.inboundRtps) {
|
|
401
|
+
const observedInboundRtp = this._updateInboundRtpStats(inboundRtp);
|
|
402
|
+
|
|
403
|
+
if (!observedInboundRtp) continue;
|
|
404
|
+
|
|
405
|
+
this.deltaInboundPacketsLost += observedInboundRtp.deltaLostPackets;
|
|
406
|
+
this.deltaInboundPacketsReceived += observedInboundRtp.deltaReceivedPackets;
|
|
407
|
+
this.deltaInboundReceivedBytes += observedInboundRtp.deltaBytesReceived;
|
|
408
|
+
|
|
409
|
+
switch (inboundRtp.kind) {
|
|
410
|
+
case 'audio':
|
|
411
|
+
this.deltaReceivedAudioBytes += observedInboundRtp.deltaBytesReceived;
|
|
412
|
+
this.deltaReceivedAudioPackets += observedInboundRtp.deltaReceivedPackets;
|
|
413
|
+
break;
|
|
414
|
+
case 'video':
|
|
415
|
+
this.deltaReceivedVideoBytes += observedInboundRtp.deltaBytesReceived;
|
|
416
|
+
this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (observedInboundRtp.jitter) {
|
|
421
|
+
jitterMeasurements.push(observedInboundRtp.jitter);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (sample.mediaPlayouts) {
|
|
426
|
+
for (const mediaPlayout of sample.mediaPlayouts) {
|
|
427
|
+
this._updateMediaPlayoutStats(mediaPlayout);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (sample.mediaSources) {
|
|
431
|
+
for (const mediaSource of sample.mediaSources) {
|
|
432
|
+
this._updateMediaSourceStats(mediaSource);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (sample.outboundRtps) {
|
|
436
|
+
for (const outboundRtp of sample.outboundRtps) {
|
|
437
|
+
const observedOutboundRtp = this._updateOutboundRtpStats(outboundRtp);
|
|
438
|
+
|
|
439
|
+
if (!observedOutboundRtp) continue;
|
|
440
|
+
|
|
441
|
+
this.deltaOutboundPacketsSent += observedOutboundRtp.deltaPacketsSent ?? 0;
|
|
442
|
+
this.deltaOutboundSentBytes += observedOutboundRtp.deltaBytesSent ?? 0;
|
|
443
|
+
|
|
444
|
+
switch (outboundRtp.kind) {
|
|
445
|
+
case 'audio':
|
|
446
|
+
this.deltaSentAudioBytes += observedOutboundRtp.deltaBytesSent;
|
|
447
|
+
this.deltaSentAudioBytes += observedOutboundRtp.deltaPacketsSent;
|
|
448
|
+
break;
|
|
449
|
+
case 'video':
|
|
450
|
+
this.deltaSentVideoBytes += observedOutboundRtp.deltaBytesSent;
|
|
451
|
+
this.deltaSentVideoBytes += observedOutboundRtp.deltaPacketsSent;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (sample.peerConnectionTransports) {
|
|
458
|
+
for (const peerConnectionTransport of sample.peerConnectionTransports) {
|
|
459
|
+
const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
460
|
+
|
|
461
|
+
if (!observedTransport) continue;
|
|
462
|
+
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (sample.remoteInboundRtps) {
|
|
466
|
+
for (const remoteInboundRtp of sample.remoteInboundRtps) {
|
|
467
|
+
const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
468
|
+
|
|
469
|
+
if (!observedRemoteInboundRtp) continue;
|
|
470
|
+
|
|
471
|
+
if (observedRemoteInboundRtp.roundTripTime) {
|
|
472
|
+
rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (sample.remoteOutboundRtps) {
|
|
477
|
+
for (const remoteOutboundRtp of sample.remoteOutboundRtps) {
|
|
478
|
+
const observedRemoteOutboundRtp = this._updateRemoteOutboundRtpStats(remoteOutboundRtp);
|
|
479
|
+
|
|
480
|
+
if (!observedRemoteOutboundRtp) continue;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// tracks should be updated last as they are derived stats
|
|
485
|
+
// and depends on base stats but they all received in the sample sample
|
|
486
|
+
if (sample.inboundTracks) {
|
|
487
|
+
for (const inboundTrack of sample.inboundTracks) {
|
|
488
|
+
this._updateInboundTrackSample(inboundTrack);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (sample.outboundTracks) {
|
|
492
|
+
for (const outboundTrack of sample.outboundTracks) {
|
|
493
|
+
this._updateOutboundTrackSample(outboundTrack);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
|
|
498
|
+
this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
|
|
499
|
+
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
|
|
500
|
+
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
501
|
+
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
502
|
+
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
503
|
+
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
504
|
+
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
|
|
505
|
+
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
|
|
506
|
+
this.totalSentAudioBytes += this.deltaSentAudioBytes;
|
|
507
|
+
this.totalSentVideoBytes += this.deltaSentVideoBytes;
|
|
508
|
+
this.totalReceivedAudioPacktes += this.deltaReceivedAudioPackets;
|
|
509
|
+
this.totalReceivedVideoPackets += this.deltaReceivedVideoPackets;
|
|
510
|
+
this.totalSentAudioPackets += this.deltaSentAudioBytes;
|
|
511
|
+
this.totalSentVideoPackets += this.deltaSentVideoBytes;
|
|
512
|
+
|
|
513
|
+
this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
|
|
514
|
+
this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / elapsedTimeInSec;
|
|
515
|
+
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / elapsedTimeInSec;
|
|
516
|
+
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / elapsedTimeInSec;
|
|
517
|
+
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / elapsedTimeInSec;
|
|
518
|
+
this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / elapsedTimeInSec;
|
|
519
|
+
|
|
520
|
+
if (rttMeasurementsInSec.length > 0) {
|
|
521
|
+
this.currentRttInMs = getMedian(rttMeasurementsInSec, false) * 1000;
|
|
522
|
+
} else {
|
|
523
|
+
this.currentRttInMs = undefined;
|
|
524
|
+
}
|
|
525
|
+
if (jitterMeasurements.length > 0) {
|
|
526
|
+
this.currentJitter = getMedian(jitterMeasurements, false);
|
|
527
|
+
} else {
|
|
528
|
+
this.currentJitter = undefined;
|
|
529
|
+
}
|
|
530
|
+
const wasUsingTURN = this.usingTURN;
|
|
531
|
+
const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
|
|
532
|
+
const selectedCandidatePairForTurn: ObservedIceCandidatePair[] = [];
|
|
533
|
+
|
|
534
|
+
this.usingTCP = false;
|
|
535
|
+
this.usingTURN = false;
|
|
536
|
+
|
|
537
|
+
for (const selectedCandidatePair of selectedIceCandidatePairs) {
|
|
538
|
+
if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
|
|
539
|
+
this.usingTCP = true;
|
|
540
|
+
}
|
|
541
|
+
if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
|
|
542
|
+
selectedCandidatePairForTurn.push(selectedCandidatePair);
|
|
543
|
+
this.usingTURN = true;
|
|
544
|
+
}
|
|
545
|
+
this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
|
|
546
|
+
this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (this.usingTURN) {
|
|
550
|
+
if (!this.observedTurnServer) {
|
|
551
|
+
this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
|
|
552
|
+
}
|
|
553
|
+
this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
|
|
554
|
+
} else if (wasUsingTURN) {
|
|
555
|
+
if (!this.usingTURN) {
|
|
556
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
this.calculatedScore.value = sample.score;
|
|
560
|
+
this.updated = now;
|
|
561
|
+
this._checkVisited();
|
|
562
|
+
|
|
563
|
+
this.emit('update');
|
|
274
564
|
}
|
|
275
565
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
566
|
+
private _checkVisited() {
|
|
567
|
+
for (const certificate of [ ...this.observedCertificates.values() ]) {
|
|
568
|
+
if (certificate.visited) continue;
|
|
279
569
|
|
|
280
|
-
|
|
281
|
-
if (this._model.label !== sample.label) {
|
|
282
|
-
this._model.label = sample.label;
|
|
570
|
+
this.observedCertificates.delete(certificate.id);
|
|
283
571
|
}
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
this.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
572
|
+
for (const codec of [ ...this.observedCodecs.values() ]) {
|
|
573
|
+
if (codec.visited) continue;
|
|
574
|
+
|
|
575
|
+
this.observedCodecs.delete(codec.id);
|
|
576
|
+
this.emit('removed-codec', codec);
|
|
577
|
+
}
|
|
578
|
+
for (const dataChannel of [ ...this.observedDataChannels.values() ]) {
|
|
579
|
+
if (dataChannel.visited) continue;
|
|
580
|
+
|
|
581
|
+
this.observedDataChannels.delete(dataChannel.id);
|
|
582
|
+
this.emit('removed-data-channel', dataChannel);
|
|
583
|
+
}
|
|
584
|
+
for (const iceCandidate of [ ...this.observedIceCandidates.values() ]) {
|
|
585
|
+
if (iceCandidate.visited) continue;
|
|
586
|
+
|
|
587
|
+
this.observedIceCandidates.delete(iceCandidate.id);
|
|
588
|
+
this.emit('removed-ice-candidate', iceCandidate);
|
|
589
|
+
}
|
|
590
|
+
for (const iceCandidatePair of [ ...this.observedIceCandidatesPair.values() ]) {
|
|
591
|
+
if (iceCandidatePair.visited) continue;
|
|
592
|
+
|
|
593
|
+
this.observedIceCandidatesPair.delete(iceCandidatePair.id);
|
|
594
|
+
this.emit('removed-ice-candidate-pair', iceCandidatePair);
|
|
595
|
+
}
|
|
596
|
+
for (const iceTransport of [ ...this.observedIceTransports.values() ]) {
|
|
597
|
+
if (iceTransport.visited) continue;
|
|
598
|
+
|
|
599
|
+
this.observedIceTransports.delete(iceTransport.id);
|
|
600
|
+
this.emit('removed-ice-transport', iceTransport);
|
|
601
|
+
}
|
|
602
|
+
for (const inboundRtp of [ ...this.observedInboundRtps.values() ]) {
|
|
603
|
+
if (inboundRtp.visited) continue;
|
|
604
|
+
|
|
605
|
+
this.observedInboundRtps.delete(inboundRtp.ssrc);
|
|
606
|
+
this.emit('removed-inbound-rtp', inboundRtp);
|
|
607
|
+
}
|
|
608
|
+
for (const inboundTrack of [ ...this.observedInboundTracks.values() ]) {
|
|
609
|
+
if (inboundTrack.visited) continue;
|
|
610
|
+
|
|
611
|
+
this.observedInboundTracks.delete(inboundTrack.id);
|
|
612
|
+
this.emit('removed-inbound-track', inboundTrack);
|
|
613
|
+
}
|
|
614
|
+
for (const mediaPlayout of [ ...this.observedMediaPlayouts.values() ]) {
|
|
615
|
+
if (mediaPlayout.visited) continue;
|
|
616
|
+
|
|
617
|
+
this.observedMediaPlayouts.delete(mediaPlayout.id);
|
|
618
|
+
this.emit('removed-media-playout', mediaPlayout);
|
|
619
|
+
}
|
|
620
|
+
for (const mediaSource of [ ...this.observedMediaSources.values() ]) {
|
|
621
|
+
if (mediaSource.visited) continue;
|
|
622
|
+
|
|
623
|
+
this.observedMediaSources.delete(mediaSource.id);
|
|
624
|
+
this.emit('removed-media-source', mediaSource);
|
|
625
|
+
}
|
|
626
|
+
for (const outboundRtp of [ ...this.observedOutboundRtps.values() ]) {
|
|
627
|
+
if (outboundRtp.visited) continue;
|
|
628
|
+
|
|
629
|
+
this.observedOutboundRtps.delete(outboundRtp.ssrc);
|
|
630
|
+
this.emit('removed-outbound-rtp', outboundRtp);
|
|
631
|
+
}
|
|
632
|
+
for (const outboundTrack of [ ...this.observedOutboundTracks.values() ]) {
|
|
633
|
+
if (outboundTrack.visited) continue;
|
|
312
634
|
|
|
313
|
-
|
|
314
|
-
this.
|
|
315
|
-
}
|
|
316
|
-
this.
|
|
635
|
+
this.observedOutboundTracks.delete(outboundTrack.id);
|
|
636
|
+
this.emit('removed-outbound-track', outboundTrack);
|
|
637
|
+
}
|
|
638
|
+
for (const peerConnectionTransport of [ ...this.observedPeerConnectionTransports.values() ]) {
|
|
639
|
+
if (peerConnectionTransport.visited) continue;
|
|
640
|
+
|
|
641
|
+
this.observedPeerConnectionTransports.delete(peerConnectionTransport.id);
|
|
642
|
+
this.emit('removed-peer-connection-transport', peerConnectionTransport);
|
|
643
|
+
}
|
|
644
|
+
for (const remoteInboundRtp of [ ...this.observedRemoteInboundRtps.values() ]) {
|
|
645
|
+
if (remoteInboundRtp.visited) continue;
|
|
317
646
|
|
|
318
|
-
|
|
647
|
+
this.observedRemoteInboundRtps.delete(remoteInboundRtp.ssrc);
|
|
648
|
+
this.emit('removed-remote-inbound-rtp', remoteInboundRtp);
|
|
649
|
+
}
|
|
650
|
+
for (const remoteOutboundRtp of [ ...this.observedRemoteOutboundRtps.values() ]) {
|
|
651
|
+
if (remoteOutboundRtp.visited) continue;
|
|
319
652
|
|
|
320
|
-
|
|
653
|
+
this.observedRemoteOutboundRtps.delete(remoteOutboundRtp.ssrc);
|
|
654
|
+
this.emit('removed-remote-outbound-rtp', remoteOutboundRtp);
|
|
655
|
+
}
|
|
321
656
|
}
|
|
322
657
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
658
|
+
private _updateCertificateStats(stats: CertificateStats) {
|
|
659
|
+
let observedCertificate = this.observedCertificates.get(stats.id);
|
|
660
|
+
|
|
661
|
+
if (!observedCertificate) {
|
|
662
|
+
if (!stats.timestamp || !stats.id || !stats.fingerprint) {
|
|
663
|
+
return logger.warn(
|
|
664
|
+
`ObservedPeerConnection received an invalid CertificateStats (missing timestamp OR id OR fingerprint field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
665
|
+
stats
|
|
666
|
+
);
|
|
667
|
+
}
|
|
327
668
|
|
|
328
|
-
|
|
329
|
-
this._inboundVideoTracks.delete(result.trackId);
|
|
330
|
-
});
|
|
331
|
-
this._inboundVideoTracks.set(result.trackId, result);
|
|
669
|
+
observedCertificate = new ObservedCertificate(stats.timestamp, stats.id, this);
|
|
332
670
|
|
|
333
|
-
|
|
671
|
+
observedCertificate.update(stats);
|
|
334
672
|
|
|
335
|
-
|
|
673
|
+
this.observedCertificates.set(stats.id, observedCertificate);
|
|
674
|
+
this.emit('added-certificate', observedCertificate);
|
|
675
|
+
} else {
|
|
676
|
+
observedCertificate.update(stats);
|
|
677
|
+
this.emit('updated-certificate', observedCertificate);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return observedCertificate;
|
|
336
681
|
}
|
|
337
682
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const result = new ObservedOutboundAudioTrack(config, this);
|
|
683
|
+
private _updateCodecStats(stats: CodecStats) {
|
|
684
|
+
let observedCodec = this.observedCodecs.get(stats.id);
|
|
342
685
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
686
|
+
if (!observedCodec) {
|
|
687
|
+
if (!stats.timestamp || !stats.id || !stats.mimeType) {
|
|
688
|
+
return logger.warn(
|
|
689
|
+
`ObservedPeerConnection received an invalid CodecStats (missing timestamp OR id OR mimeType field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
690
|
+
stats
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
observedCodec = new ObservedCodec(stats.timestamp, stats.id, stats.mimeType, this);
|
|
347
695
|
|
|
348
|
-
|
|
696
|
+
observedCodec.update(stats);
|
|
697
|
+
|
|
698
|
+
this.observedCodecs.set(stats.id, observedCodec);
|
|
699
|
+
this.emit('added-codec', observedCodec);
|
|
700
|
+
} else {
|
|
701
|
+
observedCodec.update(stats);
|
|
702
|
+
}
|
|
703
|
+
this.emit('updated-codec', observedCodec);
|
|
349
704
|
|
|
350
|
-
return
|
|
705
|
+
return observedCodec;
|
|
351
706
|
}
|
|
352
707
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
708
|
+
private _updateDataChannelStats(stats: DataChannelStats) {
|
|
709
|
+
let observedDataChannel = this.observedDataChannels.get(stats.id);
|
|
710
|
+
|
|
711
|
+
if (!observedDataChannel) {
|
|
712
|
+
if (!stats.timestamp || !stats.id) {
|
|
713
|
+
return logger.warn(
|
|
714
|
+
`ObservedPeerConnection received an invalid DataChannelStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
715
|
+
stats
|
|
716
|
+
);
|
|
717
|
+
}
|
|
357
718
|
|
|
358
|
-
|
|
359
|
-
this._outboundVideoTracks.delete(result.trackId);
|
|
360
|
-
});
|
|
361
|
-
this._outboundVideoTracks.set(result.trackId, result);
|
|
719
|
+
observedDataChannel = new ObservedDataChannel(stats.timestamp, stats.id, this);
|
|
362
720
|
|
|
363
|
-
|
|
721
|
+
observedDataChannel.update(stats);
|
|
364
722
|
|
|
365
|
-
|
|
723
|
+
this.observedDataChannels.set(stats.id, observedDataChannel);
|
|
724
|
+
this.emit('added-data-channel', observedDataChannel);
|
|
725
|
+
} else {
|
|
726
|
+
observedDataChannel.update(stats);
|
|
727
|
+
}
|
|
728
|
+
this.emit('updated-data-channel', observedDataChannel);
|
|
729
|
+
|
|
730
|
+
return observedDataChannel;
|
|
366
731
|
}
|
|
367
732
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const result = new ObservedDataChannel({
|
|
372
|
-
channelId,
|
|
373
|
-
}, this);
|
|
733
|
+
private _updateIceCandidateStats(stats: IceCandidateStats) {
|
|
734
|
+
let observedIceCandidate = this.observedIceCandidates.get(stats.id);
|
|
374
735
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
736
|
+
if (!observedIceCandidate) {
|
|
737
|
+
if (!stats.timestamp || !stats.id) {
|
|
738
|
+
return logger.warn(
|
|
739
|
+
`ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
740
|
+
stats
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
observedIceCandidate = new ObservedIceCandidate(stats.timestamp, stats.id, this);
|
|
379
745
|
|
|
380
|
-
|
|
746
|
+
observedIceCandidate.update(stats);
|
|
747
|
+
|
|
748
|
+
this.observedIceCandidates.set(stats.id, observedIceCandidate);
|
|
749
|
+
this.emit('added-ice-candidate', observedIceCandidate);
|
|
750
|
+
} else {
|
|
751
|
+
observedIceCandidate.update(stats);
|
|
752
|
+
}
|
|
753
|
+
this.emit('updated-ice-candidate', observedIceCandidate);
|
|
381
754
|
|
|
382
|
-
return
|
|
755
|
+
return observedIceCandidate;
|
|
383
756
|
}
|
|
384
757
|
|
|
385
|
-
|
|
386
|
-
let
|
|
387
|
-
|
|
388
|
-
|
|
758
|
+
private _updateIceCandidatePairStats(stats: IceCandidateStats) {
|
|
759
|
+
let observedIceCandidatePair = this.observedIceCandidatesPair.get(stats.id);
|
|
760
|
+
|
|
761
|
+
if (!observedIceCandidatePair) {
|
|
762
|
+
if (!stats.timestamp || !stats.id) {
|
|
763
|
+
return logger.warn(
|
|
764
|
+
`ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
765
|
+
stats
|
|
766
|
+
);
|
|
767
|
+
}
|
|
389
768
|
|
|
390
|
-
|
|
391
|
-
track.updateMetrics();
|
|
769
|
+
observedIceCandidatePair = new ObservedIceCandidatePair(stats.timestamp, stats.id, this);
|
|
392
770
|
|
|
393
|
-
|
|
394
|
-
this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
|
|
395
|
-
this.deltaInboundReceivedBytes += track.deltaBytesReceived;
|
|
396
|
-
|
|
397
|
-
this.deltaReceivedAudioBytes += track.deltaBytesReceived;
|
|
398
|
-
this.deltaReceivedAudioPackets += track.deltaReceivedPackets;
|
|
771
|
+
observedIceCandidatePair.update(stats);
|
|
399
772
|
|
|
400
|
-
this.
|
|
773
|
+
this.observedIceCandidatesPair.set(stats.id, observedIceCandidatePair);
|
|
774
|
+
this.emit('added-ice-candidate-pair', observedIceCandidatePair);
|
|
775
|
+
} else {
|
|
776
|
+
observedIceCandidatePair.update(stats);
|
|
777
|
+
}
|
|
778
|
+
this.emit('updated-ice-candidate-pair', observedIceCandidatePair);
|
|
779
|
+
|
|
780
|
+
return observedIceCandidatePair;
|
|
781
|
+
}
|
|
401
782
|
|
|
402
|
-
|
|
403
|
-
|
|
783
|
+
private _updateIceTransportStats(stats: IceCandidateStats) {
|
|
784
|
+
let observedIceTransport = this.observedIceTransports.get(stats.id);
|
|
404
785
|
|
|
405
|
-
|
|
406
|
-
|
|
786
|
+
if (!observedIceTransport) {
|
|
787
|
+
if (!stats.timestamp || !stats.id) {
|
|
788
|
+
return logger.warn(
|
|
789
|
+
`ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
790
|
+
stats
|
|
791
|
+
);
|
|
792
|
+
}
|
|
407
793
|
|
|
408
|
-
|
|
409
|
-
track.updateMetrics();
|
|
794
|
+
observedIceTransport = new ObservedIceTransport(stats.timestamp, stats.id, this);
|
|
410
795
|
|
|
411
|
-
|
|
412
|
-
this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
|
|
413
|
-
this.deltaInboundReceivedBytes += track.deltaBytesReceived;
|
|
414
|
-
|
|
415
|
-
this.deltaReceivedVideoBytes += track.deltaBytesReceived;
|
|
416
|
-
this.deltaReceivedVideoPackets += track.deltaReceivedPackets;
|
|
796
|
+
observedIceTransport.update(stats);
|
|
417
797
|
|
|
418
|
-
this.
|
|
798
|
+
this.observedIceTransports.set(stats.id, observedIceTransport);
|
|
799
|
+
this.emit('added-ice-transport', observedIceTransport);
|
|
800
|
+
} else {
|
|
801
|
+
observedIceTransport.update(stats);
|
|
802
|
+
}
|
|
803
|
+
this.emit('updated-ice-transport', observedIceTransport);
|
|
419
804
|
|
|
420
|
-
|
|
421
|
-
|
|
805
|
+
return observedIceTransport;
|
|
806
|
+
}
|
|
422
807
|
|
|
423
|
-
|
|
424
|
-
|
|
808
|
+
private _updateInboundRtpStats(stats: InboundRtpStats) {
|
|
809
|
+
let observedInboundRtp = this.observedInboundRtps.get(stats.ssrc);
|
|
425
810
|
|
|
426
|
-
|
|
427
|
-
|
|
811
|
+
if (!observedInboundRtp) {
|
|
812
|
+
if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind || !stats.trackIdentifier) {
|
|
813
|
+
return logger.warn(
|
|
814
|
+
`ObservedPeerConnection received an invalid InboundRtpStats (missing timestamp OR id OR ssrc OR kind OR trackIdentifier field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
815
|
+
stats
|
|
816
|
+
);
|
|
817
|
+
}
|
|
428
818
|
|
|
429
|
-
|
|
430
|
-
|
|
819
|
+
observedInboundRtp = new ObservedInboundRtp(
|
|
820
|
+
stats.timestamp,
|
|
821
|
+
stats.id,
|
|
822
|
+
stats.ssrc,
|
|
823
|
+
stats.kind as MediaKind,
|
|
824
|
+
stats.trackIdentifier,
|
|
825
|
+
this
|
|
826
|
+
);
|
|
431
827
|
|
|
432
|
-
|
|
433
|
-
this.deltaSentAudioBytes += track.deltaSentPackets;
|
|
434
|
-
|
|
435
|
-
this.sendingAudioBitrate += track.bitrate;
|
|
828
|
+
observedInboundRtp.update(stats);
|
|
436
829
|
|
|
437
|
-
|
|
438
|
-
|
|
830
|
+
this.observedInboundRtps.set(stats.ssrc, observedInboundRtp);
|
|
831
|
+
this.emit('added-inbound-rtp', observedInboundRtp);
|
|
832
|
+
} else {
|
|
833
|
+
observedInboundRtp.update(stats);
|
|
834
|
+
}
|
|
835
|
+
this.emit('updated-inbound-rtp', observedInboundRtp);
|
|
439
836
|
|
|
440
|
-
|
|
441
|
-
|
|
837
|
+
return observedInboundRtp;
|
|
838
|
+
}
|
|
442
839
|
|
|
443
|
-
|
|
444
|
-
|
|
840
|
+
private _updateInboundTrackSample(stats: InboundTrackSample) {
|
|
841
|
+
let observedInboundTrack = this.observedInboundTracks.get(stats.id);
|
|
445
842
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
843
|
+
if (!observedInboundTrack) {
|
|
844
|
+
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
845
|
+
return logger.warn(
|
|
846
|
+
`ObservedPeerConnection received an invalid InboundTrackSample (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
847
|
+
stats
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
const inboundRtp = [ ...this.observedInboundRtps.values() ].find((inbRtp) => inbRtp.trackIdentifier === stats.id);
|
|
852
|
+
const mediaPlayout = inboundRtp ?
|
|
853
|
+
[ ...this.observedMediaPlayouts.values() ].find((mp) => mp.id === inboundRtp.playoutId) : undefined;
|
|
854
|
+
|
|
855
|
+
observedInboundTrack = new ObservedInboundTrack(
|
|
856
|
+
stats.timestamp,
|
|
857
|
+
stats.id,
|
|
858
|
+
stats.kind as MediaKind,
|
|
859
|
+
this,
|
|
860
|
+
inboundRtp,
|
|
861
|
+
mediaPlayout,
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
observedInboundTrack.update(stats);
|
|
451
865
|
|
|
452
|
-
this.
|
|
866
|
+
this.observedInboundTracks.set(stats.id, observedInboundTrack);
|
|
867
|
+
this.emit('added-inbound-track', observedInboundTrack);
|
|
868
|
+
} else {
|
|
869
|
+
observedInboundTrack.update(stats);
|
|
870
|
+
}
|
|
871
|
+
this.emit('updated-inbound-track', observedInboundTrack);
|
|
453
872
|
|
|
454
|
-
|
|
455
|
-
|
|
873
|
+
return observedInboundTrack;
|
|
874
|
+
}
|
|
456
875
|
|
|
457
|
-
|
|
458
|
-
|
|
876
|
+
private _updateMediaPlayoutStats(stats: MediaPlayoutStats) {
|
|
877
|
+
let observedMediaPlayout = this.observedMediaPlayouts.get(stats.id);
|
|
459
878
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
879
|
+
if (!observedMediaPlayout) {
|
|
880
|
+
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
881
|
+
return logger.warn(
|
|
882
|
+
`ObservedPeerConnection received an invalid InboundRtpStats (missing timestamp OR id OR kind OR trackIdentifier field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
883
|
+
stats
|
|
884
|
+
);
|
|
885
|
+
}
|
|
464
886
|
|
|
465
|
-
|
|
466
|
-
|
|
887
|
+
observedMediaPlayout = new ObservedMediaPlayout(
|
|
888
|
+
stats.timestamp,
|
|
889
|
+
stats.id,
|
|
890
|
+
stats.kind as MediaKind,
|
|
891
|
+
this
|
|
892
|
+
);
|
|
467
893
|
|
|
468
|
-
|
|
894
|
+
observedMediaPlayout.update(stats);
|
|
469
895
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
896
|
+
this.observedMediaPlayouts.set(stats.id, observedMediaPlayout);
|
|
897
|
+
this.emit('added-media-playout', observedMediaPlayout);
|
|
898
|
+
} else {
|
|
899
|
+
observedMediaPlayout.update(stats);
|
|
473
900
|
}
|
|
901
|
+
this.emit('updated-media-playout', observedMediaPlayout);
|
|
474
902
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
903
|
+
return observedMediaPlayout;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
private _updateMediaSourceStats(stats: MediaSourceStats) {
|
|
907
|
+
let observedMediaSource = this.observedMediaSources.get(stats.id);
|
|
908
|
+
|
|
909
|
+
if (!observedMediaSource) {
|
|
910
|
+
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
911
|
+
return logger.warn(
|
|
912
|
+
`ObservedPeerConnection received an invalid InboundRtpStats (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
913
|
+
stats
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
observedMediaSource = new ObservedMediaSource(
|
|
918
|
+
stats.timestamp,
|
|
919
|
+
stats.id,
|
|
920
|
+
stats.kind as MediaKind,
|
|
921
|
+
this
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
observedMediaSource.update(stats);
|
|
925
|
+
|
|
926
|
+
this.observedMediaSources.set(stats.id, observedMediaSource);
|
|
927
|
+
this.emit('added-media-source', observedMediaSource);
|
|
928
|
+
} else {
|
|
929
|
+
observedMediaSource.update(stats);
|
|
930
|
+
}
|
|
931
|
+
this.emit('updated-media-source', observedMediaSource);
|
|
932
|
+
|
|
933
|
+
return observedMediaSource;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
private _updateOutboundRtpStats(stats: OutboundRtpStats) {
|
|
937
|
+
let observedOutboundRtp = this.observedOutboundRtps.get(stats.ssrc);
|
|
938
|
+
|
|
939
|
+
if (!observedOutboundRtp) {
|
|
940
|
+
if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
|
|
941
|
+
return logger.warn(
|
|
942
|
+
`ObservedPeerConnection received an invalid OutboundRtpStats (missing timestamp OR id OR ssrc OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
943
|
+
stats
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
observedOutboundRtp = new ObservedOutboundRtp(
|
|
948
|
+
stats.timestamp,
|
|
949
|
+
stats.id,
|
|
950
|
+
stats.ssrc,
|
|
951
|
+
stats.kind as MediaKind,
|
|
952
|
+
this
|
|
953
|
+
);
|
|
954
|
+
|
|
955
|
+
observedOutboundRtp.update(stats);
|
|
956
|
+
|
|
957
|
+
this.observedOutboundRtps.set(stats.ssrc, observedOutboundRtp);
|
|
958
|
+
this.emit('added-outbound-rtp', observedOutboundRtp);
|
|
959
|
+
} else {
|
|
960
|
+
observedOutboundRtp.update(stats);
|
|
961
|
+
}
|
|
962
|
+
this.emit('updated-outbound-rtp', observedOutboundRtp);
|
|
963
|
+
|
|
964
|
+
return observedOutboundRtp;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
public _updateOutboundTrackSample(stats: OutboundTrackSample) {
|
|
968
|
+
let observedOutboundTrack = this.observedOutboundTracks.get(stats.id);
|
|
489
969
|
|
|
490
|
-
if (
|
|
491
|
-
|
|
492
|
-
|
|
970
|
+
if (!observedOutboundTrack) {
|
|
971
|
+
if (!stats.timestamp || !stats.id || !stats.kind) {
|
|
972
|
+
return logger.warn(
|
|
973
|
+
`ObservedPeerConnection received an invalid OutboundTrackSample (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
974
|
+
stats
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
const observedMediaSource = [ ...this.observedMediaSources.values() ].find((mediaSource) => mediaSource.trackIdentifier === stats.id);
|
|
978
|
+
const outboundRtps = observedMediaSource
|
|
979
|
+
? [ ...this.observedOutboundRtps.values() ].filter((outboundRtp) => outboundRtp.mediaSourceId === observedMediaSource?.id) : undefined;
|
|
980
|
+
|
|
981
|
+
observedOutboundTrack = new ObservedOutboundTrack(
|
|
982
|
+
stats.timestamp,
|
|
983
|
+
stats.id,
|
|
984
|
+
stats.kind as MediaKind,
|
|
985
|
+
this,
|
|
986
|
+
outboundRtps,
|
|
987
|
+
observedMediaSource,
|
|
988
|
+
);
|
|
989
|
+
|
|
990
|
+
observedOutboundTrack.update(stats);
|
|
991
|
+
|
|
992
|
+
this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
|
|
993
|
+
this.emit('added-outbound-track', observedOutboundTrack);
|
|
493
994
|
} else {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
995
|
+
observedOutboundTrack.update(stats);
|
|
996
|
+
}
|
|
997
|
+
this.emit('updated-outbound-track', observedOutboundTrack);
|
|
998
|
+
|
|
999
|
+
return observedOutboundTrack;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
private _updatePeerConnectionTransportStats(stats: PeerConnectionTransportStats) {
|
|
1003
|
+
let observedPeerConnectionTransport = this.observedPeerConnectionTransports.get(stats.id);
|
|
1004
|
+
|
|
1005
|
+
if (!observedPeerConnectionTransport) {
|
|
1006
|
+
if (!stats.timestamp || !stats.id) {
|
|
1007
|
+
return logger.warn(
|
|
1008
|
+
`ObservedPeerConnection received an invalid PeerConnectionTransportStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
1009
|
+
stats
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
observedPeerConnectionTransport = new ObservedPeerConnectionTransport(stats.timestamp, stats.id, this);
|
|
1014
|
+
|
|
1015
|
+
observedPeerConnectionTransport.update(stats);
|
|
1016
|
+
|
|
1017
|
+
this.observedPeerConnectionTransports.set(stats.id, observedPeerConnectionTransport);
|
|
1018
|
+
this.emit('added-peer-connection-transport', observedPeerConnectionTransport);
|
|
1019
|
+
} else {
|
|
1020
|
+
observedPeerConnectionTransport.update(stats);
|
|
1021
|
+
}
|
|
1022
|
+
this.emit('updated-peer-connection-transport', observedPeerConnectionTransport);
|
|
1023
|
+
|
|
1024
|
+
return observedPeerConnectionTransport;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
private _updateRemoteInboundRtpStats(stats: RemoteInboundRtpStats) {
|
|
1028
|
+
let observedRemoteInboundRtp = this.observedRemoteInboundRtps.get(stats.ssrc);
|
|
1029
|
+
|
|
1030
|
+
if (!observedRemoteInboundRtp) {
|
|
1031
|
+
if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
|
|
1032
|
+
return logger.warn(
|
|
1033
|
+
`ObservedPeerConnection received an invalid RemoteInboundRtpStats (missing timestamp OR id OR ssrc OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
1034
|
+
stats
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
observedRemoteInboundRtp = new ObservedRemoteInboundRtp(
|
|
1039
|
+
stats.timestamp,
|
|
1040
|
+
stats.id,
|
|
1041
|
+
stats.ssrc,
|
|
1042
|
+
stats.kind as MediaKind,
|
|
1043
|
+
this
|
|
1044
|
+
);
|
|
1045
|
+
|
|
1046
|
+
observedRemoteInboundRtp.update(stats);
|
|
1047
|
+
|
|
1048
|
+
this.observedRemoteInboundRtps.set(stats.ssrc, observedRemoteInboundRtp);
|
|
1049
|
+
this.emit('added-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
1050
|
+
} else {
|
|
1051
|
+
observedRemoteInboundRtp.update(stats);
|
|
1052
|
+
}
|
|
1053
|
+
this.emit('updated-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
1054
|
+
|
|
1055
|
+
return observedRemoteInboundRtp;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
private _updateRemoteOutboundRtpStats(stats: RemoteOutboundRtpStats) {
|
|
1059
|
+
let observedRemoteOutboundRtp = this.observedRemoteOutboundRtps.get(stats.ssrc);
|
|
1060
|
+
|
|
1061
|
+
if (!observedRemoteOutboundRtp) {
|
|
1062
|
+
if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
|
|
1063
|
+
return logger.warn(
|
|
1064
|
+
`ObservedPeerConnection received an invalid RemoteOutboundRtpStats (missing timestamp OR id OR ssrc OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
|
|
1065
|
+
stats
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
observedRemoteOutboundRtp = new ObservedRemoteOutboundRtp(
|
|
1070
|
+
stats.timestamp,
|
|
1071
|
+
stats.id,
|
|
1072
|
+
stats.ssrc,
|
|
1073
|
+
stats.kind as MediaKind,
|
|
1074
|
+
this
|
|
1075
|
+
);
|
|
1076
|
+
|
|
1077
|
+
observedRemoteOutboundRtp.update(stats);
|
|
1078
|
+
|
|
1079
|
+
this.observedRemoteOutboundRtps.set(stats.ssrc, observedRemoteOutboundRtp);
|
|
1080
|
+
this.emit('added-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
1081
|
+
} else {
|
|
1082
|
+
observedRemoteOutboundRtp.update(stats);
|
|
1083
|
+
}
|
|
1084
|
+
this.emit('updated-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
1085
|
+
|
|
1086
|
+
return observedRemoteOutboundRtp;
|
|
1087
|
+
}
|
|
1088
|
+
}
|