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