@observertc/observer-js 1.0.0-beta.2 → 1.0.0-beta.4

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.
Files changed (223) hide show
  1. package/README.md +773 -388
  2. package/dist/index.d.mts +2793 -0
  3. package/dist/index.mjs +3719 -0
  4. package/dist/index.mjs.map +1 -0
  5. package/package.json +21 -14
  6. package/.eslintrc.json +0 -143
  7. package/.prettierignore +0 -5
  8. package/.prettierrc +0 -7
  9. package/jest.config.js +0 -9
  10. package/lib/ObservedCall.d.ts +0 -86
  11. package/lib/ObservedCall.d.ts.map +0 -1
  12. package/lib/ObservedCall.js +0 -225
  13. package/lib/ObservedCallEventMonitor.d.ts +0 -104
  14. package/lib/ObservedCallEventMonitor.d.ts.map +0 -1
  15. package/lib/ObservedCallEventMonitor.js +0 -314
  16. package/lib/ObservedCallSummary.d.ts +0 -18
  17. package/lib/ObservedCallSummary.d.ts.map +0 -1
  18. package/lib/ObservedCallSummary.js +0 -2
  19. package/lib/ObservedCertificate.d.ts +0 -19
  20. package/lib/ObservedCertificate.d.ts.map +0 -1
  21. package/lib/ObservedCertificate.js +0 -38
  22. package/lib/ObservedClient.d.ts +0 -130
  23. package/lib/ObservedClient.d.ts.map +0 -1
  24. package/lib/ObservedClient.js +0 -650
  25. package/lib/ObservedClientEventMonitor.d.ts +0 -91
  26. package/lib/ObservedClientEventMonitor.d.ts.map +0 -1
  27. package/lib/ObservedClientEventMonitor.js +0 -254
  28. package/lib/ObservedClientSummary.d.ts +0 -23
  29. package/lib/ObservedClientSummary.d.ts.map +0 -1
  30. package/lib/ObservedClientSummary.js +0 -2
  31. package/lib/ObservedCodec.d.ts +0 -22
  32. package/lib/ObservedCodec.d.ts.map +0 -1
  33. package/lib/ObservedCodec.js +0 -45
  34. package/lib/ObservedDataChannel.d.ts +0 -30
  35. package/lib/ObservedDataChannel.d.ts.map +0 -1
  36. package/lib/ObservedDataChannel.js +0 -75
  37. package/lib/ObservedIceCandidate.d.ts +0 -29
  38. package/lib/ObservedIceCandidate.d.ts.map +0 -1
  39. package/lib/ObservedIceCandidate.js +0 -59
  40. package/lib/ObservedIceCandidatePair.d.ts +0 -45
  41. package/lib/ObservedIceCandidatePair.d.ts.map +0 -1
  42. package/lib/ObservedIceCandidatePair.js +0 -127
  43. package/lib/ObservedIceTransport.d.ts +0 -36
  44. package/lib/ObservedIceTransport.d.ts.map +0 -1
  45. package/lib/ObservedIceTransport.js +0 -93
  46. package/lib/ObservedInboundRtp.d.ts +0 -92
  47. package/lib/ObservedInboundRtp.d.ts.map +0 -1
  48. package/lib/ObservedInboundRtp.js +0 -193
  49. package/lib/ObservedInboundTrack.d.ts +0 -32
  50. package/lib/ObservedInboundTrack.d.ts.map +0 -1
  51. package/lib/ObservedInboundTrack.js +0 -60
  52. package/lib/ObservedMediaPlayout.d.ts +0 -22
  53. package/lib/ObservedMediaPlayout.d.ts.map +0 -1
  54. package/lib/ObservedMediaPlayout.js +0 -42
  55. package/lib/ObservedMediaSource.d.ts +0 -28
  56. package/lib/ObservedMediaSource.d.ts.map +0 -1
  57. package/lib/ObservedMediaSource.js +0 -55
  58. package/lib/ObservedOutboundRtp.d.ts +0 -62
  59. package/lib/ObservedOutboundRtp.d.ts.map +0 -1
  60. package/lib/ObservedOutboundRtp.js +0 -144
  61. package/lib/ObservedOutboundTrack.d.ts +0 -32
  62. package/lib/ObservedOutboundTrack.d.ts.map +0 -1
  63. package/lib/ObservedOutboundTrack.js +0 -60
  64. package/lib/ObservedPeerConnection.d.ts +0 -207
  65. package/lib/ObservedPeerConnection.d.ts.map +0 -1
  66. package/lib/ObservedPeerConnection.js +0 -773
  67. package/lib/ObservedPeerConnectionTransport.d.ts +0 -17
  68. package/lib/ObservedPeerConnectionTransport.d.ts.map +0 -1
  69. package/lib/ObservedPeerConnectionTransport.js +0 -34
  70. package/lib/ObservedRemoteInboundRtp.d.ts +0 -30
  71. package/lib/ObservedRemoteInboundRtp.d.ts.map +0 -1
  72. package/lib/ObservedRemoteInboundRtp.js +0 -60
  73. package/lib/ObservedRemoteOutboundRtp.d.ts +0 -30
  74. package/lib/ObservedRemoteOutboundRtp.d.ts.map +0 -1
  75. package/lib/ObservedRemoteOutboundRtp.js +0 -60
  76. package/lib/ObservedTURN.d.ts +0 -31
  77. package/lib/ObservedTURN.d.ts.map +0 -1
  78. package/lib/ObservedTURN.js +0 -58
  79. package/lib/ObservedTurnServer.d.ts +0 -25
  80. package/lib/ObservedTurnServer.d.ts.map +0 -1
  81. package/lib/ObservedTurnServer.js +0 -59
  82. package/lib/Observer.d.ts +0 -65
  83. package/lib/Observer.d.ts.map +0 -1
  84. package/lib/Observer.js +0 -166
  85. package/lib/ObserverEventMonitor.d.ts +0 -138
  86. package/lib/ObserverEventMonitor.d.ts.map +0 -1
  87. package/lib/ObserverEventMonitor.js +0 -433
  88. package/lib/ObserverSummary.d.ts +0 -13
  89. package/lib/ObserverSummary.d.ts.map +0 -1
  90. package/lib/ObserverSummary.js +0 -2
  91. package/lib/common/Middleware.d.ts +0 -17
  92. package/lib/common/Middleware.d.ts.map +0 -1
  93. package/lib/common/Middleware.js +0 -60
  94. package/lib/common/SingleExecutor.d.ts +0 -3
  95. package/lib/common/SingleExecutor.d.ts.map +0 -1
  96. package/lib/common/SingleExecutor.js +0 -31
  97. package/lib/common/logger.d.ts +0 -17
  98. package/lib/common/logger.d.ts.map +0 -1
  99. package/lib/common/logger.js +0 -50
  100. package/lib/common/types.d.ts +0 -3
  101. package/lib/common/types.d.ts.map +0 -1
  102. package/lib/common/types.js +0 -3
  103. package/lib/common/utils.d.ts +0 -11
  104. package/lib/common/utils.d.ts.map +0 -1
  105. package/lib/common/utils.js +0 -63
  106. package/lib/detectors/Detector.d.ts +0 -5
  107. package/lib/detectors/Detector.d.ts.map +0 -1
  108. package/lib/detectors/Detector.js +0 -3
  109. package/lib/detectors/Detectors.d.ts +0 -11
  110. package/lib/detectors/Detectors.d.ts.map +0 -1
  111. package/lib/detectors/Detectors.js +0 -34
  112. package/lib/index.d.ts +0 -28
  113. package/lib/index.d.ts.map +0 -1
  114. package/lib/index.js +0 -49
  115. package/lib/mediasoup/ObservedMediaRouter.d.ts +0 -10
  116. package/lib/mediasoup/ObservedMediaRouter.d.ts.map +0 -1
  117. package/lib/mediasoup/ObservedMediaRouter.js +0 -6
  118. package/lib/monitors/TurnUsageMonitor.d.ts +0 -1
  119. package/lib/monitors/TurnUsageMonitor.d.ts.map +0 -1
  120. package/lib/monitors/TurnUsageMonitor.js +0 -146
  121. package/lib/schema/ClientEventTypes.d.ts +0 -228
  122. package/lib/schema/ClientEventTypes.d.ts.map +0 -1
  123. package/lib/schema/ClientEventTypes.js +0 -41
  124. package/lib/schema/ClientMetaTypes.d.ts +0 -34
  125. package/lib/schema/ClientMetaTypes.d.ts.map +0 -1
  126. package/lib/schema/ClientMetaTypes.js +0 -16
  127. package/lib/schema/ClientSample.d.ts +0 -1333
  128. package/lib/schema/ClientSample.d.ts.map +0 -1
  129. package/lib/schema/ClientSample.js +0 -4
  130. package/lib/scores/CalculatedScore.d.ts +0 -6
  131. package/lib/scores/CalculatedScore.d.ts.map +0 -1
  132. package/lib/scores/CalculatedScore.js +0 -2
  133. package/lib/scores/DefaultCallScoreCalculator.d.ts +0 -7
  134. package/lib/scores/DefaultCallScoreCalculator.d.ts.map +0 -1
  135. package/lib/scores/DefaultCallScoreCalculator.js +0 -21
  136. package/lib/scores/ScoreCalculator.d.ts +0 -4
  137. package/lib/scores/ScoreCalculator.d.ts.map +0 -1
  138. package/lib/scores/ScoreCalculator.js +0 -2
  139. package/lib/updaters/CallUpdater.d.ts +0 -5
  140. package/lib/updaters/CallUpdater.d.ts.map +0 -1
  141. package/lib/updaters/CallUpdater.js +0 -2
  142. package/lib/updaters/ObserverUpdater.d.ts +0 -5
  143. package/lib/updaters/ObserverUpdater.d.ts.map +0 -1
  144. package/lib/updaters/ObserverUpdater.js +0 -2
  145. package/lib/updaters/OnAllCallObserverUpdater.d.ts +0 -15
  146. package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +0 -1
  147. package/lib/updaters/OnAllCallObserverUpdater.js +0 -50
  148. package/lib/updaters/OnAllClientCallUpdater.d.ts +0 -15
  149. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +0 -1
  150. package/lib/updaters/OnAllClientCallUpdater.js +0 -53
  151. package/lib/updaters/OnAnyCallObserverUpdater.d.ts +0 -12
  152. package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +0 -1
  153. package/lib/updaters/OnAnyCallObserverUpdater.js +0 -37
  154. package/lib/updaters/OnAnyClientCallUpdater.d.ts +0 -12
  155. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +0 -1
  156. package/lib/updaters/OnAnyClientCallUpdater.js +0 -36
  157. package/lib/updaters/OnIntervalUpdater.d.ts +0 -10
  158. package/lib/updaters/OnIntervalUpdater.d.ts.map +0 -1
  159. package/lib/updaters/OnIntervalUpdater.js +0 -17
  160. package/lib/updaters/Updater.d.ts +0 -6
  161. package/lib/updaters/Updater.d.ts.map +0 -1
  162. package/lib/updaters/Updater.js +0 -2
  163. package/lib/utils/MediasoupRemoteTrackResolver.d.ts +0 -25
  164. package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +0 -1
  165. package/lib/utils/MediasoupRemoteTrackResolver.js +0 -110
  166. package/lib/utils/RemoteTrackResolver.d.ts +0 -7
  167. package/lib/utils/RemoteTrackResolver.d.ts.map +0 -1
  168. package/lib/utils/RemoteTrackResolver.js +0 -2
  169. package/src/ObservedCall.ts +0 -342
  170. package/src/ObservedCallEventMonitor.ts +0 -392
  171. package/src/ObservedCallSummary.ts +0 -22
  172. package/src/ObservedCertificate.ts +0 -43
  173. package/src/ObservedClient.ts +0 -807
  174. package/src/ObservedClientEventMonitor.ts +0 -309
  175. package/src/ObservedClientSummary.ts +0 -24
  176. package/src/ObservedCodec.ts +0 -49
  177. package/src/ObservedDataChannel.ts +0 -85
  178. package/src/ObservedIceCandidate.ts +0 -64
  179. package/src/ObservedIceCandidatePair.ts +0 -134
  180. package/src/ObservedIceTransport.ts +0 -99
  181. package/src/ObservedInboundRtp.ts +0 -205
  182. package/src/ObservedInboundTrack.ts +0 -75
  183. package/src/ObservedMediaPlayout.ts +0 -49
  184. package/src/ObservedMediaSource.ts +0 -60
  185. package/src/ObservedOutboundRtp.ts +0 -156
  186. package/src/ObservedOutboundTrack.ts +0 -74
  187. package/src/ObservedPeerConnection.ts +0 -1088
  188. package/src/ObservedPeerConnectionTransport.ts +0 -38
  189. package/src/ObservedRemoteInboundRtp.ts +0 -64
  190. package/src/ObservedRemoteOutboundRtp.ts +0 -65
  191. package/src/ObservedTURN.ts +0 -86
  192. package/src/ObservedTurnServer.ts +0 -72
  193. package/src/Observer.ts +0 -251
  194. package/src/ObserverEventMonitor.ts +0 -551
  195. package/src/ObserverSummary.ts +0 -15
  196. package/src/common/Middleware.ts +0 -84
  197. package/src/common/SingleExecutor.ts +0 -36
  198. package/src/common/logger.ts +0 -82
  199. package/src/common/types.ts +0 -4
  200. package/src/common/utils.ts +0 -69
  201. package/src/detectors/Detector.ts +0 -6
  202. package/src/detectors/Detectors.ts +0 -38
  203. package/src/index.ts +0 -28
  204. package/src/mediasoup/ObservedMediaRouter.ts +0 -10
  205. package/src/monitors/TurnUsageMonitor.ts +0 -187
  206. package/src/schema/ClientEventTypes.ts +0 -280
  207. package/src/schema/ClientMetaTypes.ts +0 -41
  208. package/src/schema/ClientSample.ts +0 -1682
  209. package/src/scores/CalculatedScore.ts +0 -6
  210. package/src/scores/DefaultCallScoreCalculator.ts +0 -23
  211. package/src/scores/ScoreCalculator.ts +0 -3
  212. package/src/updaters/CallUpdater.ts +0 -5
  213. package/src/updaters/ObserverUpdater.ts +0 -5
  214. package/src/updaters/OnAllCallObserverUpdater.ts +0 -59
  215. package/src/updaters/OnAllClientCallUpdater.ts +0 -61
  216. package/src/updaters/OnAnyCallObserverUpdater.ts +0 -41
  217. package/src/updaters/OnAnyClientCallUpdater.ts +0 -39
  218. package/src/updaters/OnIntervalUpdater.ts +0 -19
  219. package/src/updaters/Updater.ts +0 -5
  220. package/src/utils/MediasoupRemoteTrackResolver.ts +0 -155
  221. package/src/utils/RemoteTrackResolver.ts +0 -12
  222. package/tsconfig.json +0 -19
  223. package/tslint.json +0 -6
package/dist/index.mjs ADDED
@@ -0,0 +1,3719 @@
1
+ // src/common/logger.ts
2
+ var mainLogger = new class {
3
+ trace = () => void 0;
4
+ // trace(module: string, ...args: any[]) {
5
+ // // eslint-disable-next-line no-console
6
+ // console.log(`[TRACE] ${module}`, ...args);
7
+ // }
8
+ debug(module, ...args) {
9
+ console.log(`[DEBUG] ${module}`, ...args);
10
+ }
11
+ info(module, ...args) {
12
+ console.info(`[INFO] ${module}`, ...args);
13
+ }
14
+ warn(module, ...args) {
15
+ console.warn(`[WARN] ${module}`, ...args);
16
+ }
17
+ error(module, ...args) {
18
+ console.error(`[ERROR] ${module}`, ...args);
19
+ }
20
+ }();
21
+ function createLogger(moduleName) {
22
+ return new class {
23
+ trace(...args) {
24
+ mainLogger.trace(moduleName, ...args);
25
+ }
26
+ debug(...args) {
27
+ mainLogger.debug(moduleName, ...args);
28
+ }
29
+ info(...args) {
30
+ mainLogger.info(moduleName, ...args);
31
+ }
32
+ warn(...args) {
33
+ mainLogger.warn(moduleName, ...args);
34
+ }
35
+ error(...args) {
36
+ mainLogger.error(moduleName, ...args);
37
+ }
38
+ }();
39
+ }
40
+ function setObserverLogger(logger7) {
41
+ mainLogger = logger7;
42
+ }
43
+
44
+ // src/ObservedCall.ts
45
+ import { EventEmitter as EventEmitter3 } from "events";
46
+
47
+ // src/ObservedClient.ts
48
+ import { EventEmitter as EventEmitter2 } from "events";
49
+
50
+ // src/ObservedPeerConnection.ts
51
+ import { EventEmitter } from "events";
52
+
53
+ // src/ObservedInboundRtp.ts
54
+ var ObservedInboundRtp = class {
55
+ constructor(timestamp, id, ssrc, kind, trackIdentifier, _peerConnection) {
56
+ this.timestamp = timestamp;
57
+ this.id = id;
58
+ this.ssrc = ssrc;
59
+ this.kind = kind;
60
+ this.trackIdentifier = trackIdentifier;
61
+ this._peerConnection = _peerConnection;
62
+ }
63
+ timestamp;
64
+ id;
65
+ ssrc;
66
+ kind;
67
+ trackIdentifier;
68
+ _peerConnection;
69
+ appData;
70
+ _visited = false;
71
+ transportId;
72
+ codecId;
73
+ packetsReceived;
74
+ packetsLost;
75
+ mid;
76
+ remoteId;
77
+ framesDecoded;
78
+ keyFramesDecoded;
79
+ framesRendered;
80
+ framesDropped;
81
+ frameWidth;
82
+ frameHeight;
83
+ framesPerSecond;
84
+ qpSum;
85
+ totalDecodeTime;
86
+ totalInterFrameDelay;
87
+ totalSquaredInterFrameDelay;
88
+ pauseCount;
89
+ totalPausesDuration;
90
+ freezeCount;
91
+ totalFreezesDuration;
92
+ lastPacketReceivedTimestamp;
93
+ headerBytesReceived;
94
+ packetsDiscarded;
95
+ fecBytesReceived;
96
+ fecPacketsReceived;
97
+ fecPacketsDiscarded;
98
+ bytesReceived;
99
+ nackCount;
100
+ firCount;
101
+ pliCount;
102
+ totalProcessingDelay;
103
+ estimatedPlayoutTimestamp;
104
+ jitterBufferDelay;
105
+ jitterBufferTargetDelay;
106
+ jitterBufferEmittedCount;
107
+ jitterBufferMinimumDelay;
108
+ totalSamplesReceived;
109
+ concealedSamples;
110
+ silentConcealedSamples;
111
+ concealmentEvents;
112
+ insertedSamplesForDeceleration;
113
+ removedSamplesForAcceleration;
114
+ audioLevel;
115
+ totalAudioEnergy;
116
+ totalSamplesDuration;
117
+ framesReceived;
118
+ decoderImplementation;
119
+ playoutId;
120
+ powerEfficientDecoder;
121
+ framesAssembledFromMultiplePackets;
122
+ totalAssemblyTime;
123
+ retransmittedPacketsReceived;
124
+ retransmittedBytesReceived;
125
+ rtxSsrc;
126
+ fecSsrc;
127
+ totalCorruptionProbability;
128
+ totalSquaredCorruptionProbability;
129
+ corruptionMeasurements;
130
+ attachments;
131
+ jitter;
132
+ bitrate = 0;
133
+ fractionLost;
134
+ bitPerPixel = 0;
135
+ deltaLostPackets = 0;
136
+ deltaReceivedPackets = 0;
137
+ deltaBytesReceived = 0;
138
+ deltaReceivedSamples = 0;
139
+ deltaSilentConcealedSamples = 0;
140
+ // Derived from the corresponding remote-outbound-rtp (sender report), when present.
141
+ remoteRttInMs;
142
+ remoteBytesSent;
143
+ remotePacketsSent;
144
+ remoteTimestamp;
145
+ get visited() {
146
+ const visited = this._visited;
147
+ this._visited = false;
148
+ return visited;
149
+ }
150
+ getPeerConnection() {
151
+ return this._peerConnection;
152
+ }
153
+ getRemoteOutboundRtp() {
154
+ return this._peerConnection.observedRemoteOutboundRtps.get(this.ssrc);
155
+ }
156
+ getIceTransport() {
157
+ return this._peerConnection.observedIceTransports.get(this.transportId ?? "");
158
+ }
159
+ getCodec() {
160
+ return this._peerConnection.observedCodecs.get(this.codecId ?? "");
161
+ }
162
+ getMediaPlayout() {
163
+ return this._peerConnection.observedMediaPlayouts.get(this.playoutId ?? "");
164
+ }
165
+ getTrack() {
166
+ return this._peerConnection.observedInboundTracks.get(this.trackIdentifier);
167
+ }
168
+ update(stats) {
169
+ this._visited = true;
170
+ this.deltaBytesReceived = 0;
171
+ this.deltaLostPackets = 0;
172
+ this.deltaReceivedPackets = 0;
173
+ this.deltaReceivedSamples = 0;
174
+ this.deltaSilentConcealedSamples = 0;
175
+ this.remoteRttInMs = void 0;
176
+ this.remoteBytesSent = void 0;
177
+ this.remotePacketsSent = void 0;
178
+ this.remoteTimestamp = void 0;
179
+ this.bitrate = 0;
180
+ this.jitter = void 0;
181
+ this.fractionLost = void 0;
182
+ this.bitPerPixel = 0;
183
+ const elapsedTimeInMs = stats.timestamp - this.timestamp;
184
+ if (elapsedTimeInMs) {
185
+ if (this.bytesReceived && stats.bytesReceived && this.bytesReceived < stats.bytesReceived) {
186
+ this.bitrate = (stats.bytesReceived - (this.bytesReceived ?? 0)) * 8 / elapsedTimeInMs;
187
+ }
188
+ if (this.packetsLost && stats.packetsLost && this.packetsLost < stats.packetsLost) {
189
+ this.deltaLostPackets = stats.packetsLost - this.packetsLost;
190
+ }
191
+ if (this.packetsReceived && stats.packetsReceived && this.packetsReceived < stats.packetsReceived) {
192
+ this.deltaReceivedPackets = stats.packetsReceived - this.packetsReceived;
193
+ }
194
+ if (this.totalSamplesReceived && stats.totalSamplesReceived && this.totalSamplesReceived < stats.totalSamplesReceived) {
195
+ this.deltaReceivedSamples = stats.totalSamplesReceived - this.totalSamplesReceived;
196
+ }
197
+ if (this.silentConcealedSamples && stats.silentConcealedSamples && this.silentConcealedSamples < stats.silentConcealedSamples) {
198
+ this.deltaSilentConcealedSamples = stats.silentConcealedSamples - this.silentConcealedSamples;
199
+ }
200
+ if (stats.bytesReceived && this.framesReceived && stats.framesReceived && this.framesReceived < stats.framesReceived) {
201
+ this.bitPerPixel = (stats.bytesReceived - (this.bytesReceived ?? 0)) / (stats.framesReceived - this.framesReceived);
202
+ }
203
+ if (this.deltaLostPackets && this.deltaReceivedPackets) {
204
+ this.fractionLost = this.deltaLostPackets / (this.deltaLostPackets + this.deltaReceivedPackets);
205
+ }
206
+ }
207
+ this.timestamp = stats.timestamp;
208
+ this.transportId = stats.transportId;
209
+ this.codecId = stats.codecId;
210
+ this.packetsReceived = stats.packetsReceived;
211
+ this.packetsLost = stats.packetsLost;
212
+ this.mid = stats.mid;
213
+ this.remoteId = stats.remoteId;
214
+ this.framesDecoded = stats.framesDecoded;
215
+ this.keyFramesDecoded = stats.keyFramesDecoded;
216
+ this.framesRendered = stats.framesRendered;
217
+ this.framesDropped = stats.framesDropped;
218
+ this.frameWidth = stats.frameWidth;
219
+ this.frameHeight = stats.frameHeight;
220
+ this.framesPerSecond = stats.framesPerSecond;
221
+ this.qpSum = stats.qpSum;
222
+ this.totalDecodeTime = stats.totalDecodeTime;
223
+ this.totalInterFrameDelay = stats.totalInterFrameDelay;
224
+ this.totalSquaredInterFrameDelay = stats.totalSquaredInterFrameDelay;
225
+ this.pauseCount = stats.pauseCount;
226
+ this.totalPausesDuration = stats.totalPausesDuration;
227
+ this.freezeCount = stats.freezeCount;
228
+ this.totalFreezesDuration = stats.totalFreezesDuration;
229
+ this.lastPacketReceivedTimestamp = stats.lastPacketReceivedTimestamp;
230
+ this.headerBytesReceived = stats.headerBytesReceived;
231
+ this.packetsDiscarded = stats.packetsDiscarded;
232
+ this.fecBytesReceived = stats.fecBytesReceived;
233
+ this.fecPacketsReceived = stats.fecPacketsReceived;
234
+ this.fecPacketsDiscarded = stats.fecPacketsDiscarded;
235
+ this.bytesReceived = stats.bytesReceived;
236
+ this.nackCount = stats.nackCount;
237
+ this.firCount = stats.firCount;
238
+ this.pliCount = stats.pliCount;
239
+ this.totalProcessingDelay = stats.totalProcessingDelay;
240
+ this.estimatedPlayoutTimestamp = stats.estimatedPlayoutTimestamp;
241
+ this.jitterBufferDelay = stats.jitterBufferDelay;
242
+ this.jitterBufferTargetDelay = stats.jitterBufferTargetDelay;
243
+ this.jitterBufferEmittedCount = stats.jitterBufferEmittedCount;
244
+ this.jitterBufferMinimumDelay = stats.jitterBufferMinimumDelay;
245
+ this.totalSamplesReceived = stats.totalSamplesReceived;
246
+ this.concealedSamples = stats.concealedSamples;
247
+ this.silentConcealedSamples = stats.silentConcealedSamples;
248
+ this.concealmentEvents = stats.concealmentEvents;
249
+ }
250
+ };
251
+
252
+ // src/ObservedOutboundRtp.ts
253
+ var ObservedOutboundRtp = class {
254
+ constructor(timestamp, id, ssrc, kind, _peerConnection) {
255
+ this.timestamp = timestamp;
256
+ this.id = id;
257
+ this.ssrc = ssrc;
258
+ this.kind = kind;
259
+ this._peerConnection = _peerConnection;
260
+ }
261
+ timestamp;
262
+ id;
263
+ ssrc;
264
+ kind;
265
+ _peerConnection;
266
+ _visited = false;
267
+ appData;
268
+ transportId;
269
+ codecId;
270
+ packetsSent;
271
+ bytesSent;
272
+ mid;
273
+ mediaSourceId;
274
+ remoteId;
275
+ rid;
276
+ headerBytesSent;
277
+ retransmittedPacketsSent;
278
+ retransmittedBytesSent;
279
+ rtxSsrc;
280
+ targetBitrate;
281
+ totalEncodedBytesTarget;
282
+ frameWidth;
283
+ frameHeight;
284
+ framesPerSecond;
285
+ framesSent;
286
+ hugeFramesSent;
287
+ framesEncoded;
288
+ keyFramesEncoded;
289
+ qpSum;
290
+ totalEncodeTime;
291
+ totalPacketSendDelay;
292
+ qualityLimitationReason;
293
+ qualityLimitationResolutionChanges;
294
+ nackCount;
295
+ firCount;
296
+ pliCount;
297
+ encoderImplementation;
298
+ powerEfficientEncoder;
299
+ active;
300
+ scalabilityMode;
301
+ qualityLimitationDurations;
302
+ attachments;
303
+ // derived fields
304
+ bitrate = 0;
305
+ payloadBitrate = 0;
306
+ packetRate = 0;
307
+ bitPerPixel = 0;
308
+ deltaPacketsSent = 0;
309
+ deltaBytesSent = 0;
310
+ // Derived from the corresponding remote-inbound-rtp (receiver report), when present.
311
+ remoteRttInMs;
312
+ remoteFractionLost;
313
+ remoteJitter;
314
+ remotePacketsLost;
315
+ get visited() {
316
+ const visited = this._visited;
317
+ this._visited = false;
318
+ return visited;
319
+ }
320
+ getPeerConnection() {
321
+ return this._peerConnection;
322
+ }
323
+ getRemoteInboundRtp() {
324
+ return this._peerConnection.observedRemoteInboundRtps.get(this.ssrc);
325
+ }
326
+ getCodec() {
327
+ return this._peerConnection.observedCodecs.get(this.codecId ?? "");
328
+ }
329
+ getMediaSource() {
330
+ return this._peerConnection.observedMediaSources.get(this.mediaSourceId ?? "");
331
+ }
332
+ getTrack() {
333
+ var _a;
334
+ return (_a = this.getMediaSource()) == null ? void 0 : _a.getTrack();
335
+ }
336
+ update(stats) {
337
+ this._visited = true;
338
+ this.bitPerPixel = 0;
339
+ this.bitrate = 0;
340
+ this.payloadBitrate = 0;
341
+ this.packetRate = 0;
342
+ this.deltaPacketsSent = 0;
343
+ this.deltaBytesSent = 0;
344
+ this.remoteRttInMs = void 0;
345
+ this.remoteFractionLost = void 0;
346
+ this.remoteJitter = void 0;
347
+ this.remotePacketsLost = void 0;
348
+ const elapsedTimeInMs = stats.timestamp - this.timestamp;
349
+ if (elapsedTimeInMs) {
350
+ if (stats.packetsSent !== void 0 && this.packetsSent !== void 0 && stats.packetsSent >= this.packetsSent) {
351
+ this.deltaPacketsSent = stats.packetsSent - this.packetsSent;
352
+ this.packetRate = this.deltaPacketsSent / (elapsedTimeInMs / 1e3);
353
+ }
354
+ if (stats.bytesSent !== void 0 && this.bytesSent !== void 0 && stats.bytesSent >= this.bytesSent) {
355
+ this.deltaBytesSent = stats.bytesSent - this.bytesSent;
356
+ this.bitrate = this.deltaBytesSent * 8 / (elapsedTimeInMs / 1e3);
357
+ }
358
+ if (stats.headerBytesSent !== void 0 && this.headerBytesSent !== void 0) {
359
+ this.payloadBitrate = (this.deltaBytesSent ?? 0 - (stats.headerBytesSent - this.headerBytesSent)) * 8 / (elapsedTimeInMs / 1e3);
360
+ }
361
+ if (this.framesSent !== void 0 && stats.framesSent !== void 0) {
362
+ this.bitPerPixel = this.deltaBytesSent ? this.deltaBytesSent * 8 / (this.framesSent - stats.framesSent) : 0;
363
+ }
364
+ }
365
+ this.timestamp = stats.timestamp;
366
+ this.transportId = stats.transportId;
367
+ this.codecId = stats.codecId;
368
+ this.packetsSent = stats.packetsSent;
369
+ this.bytesSent = stats.bytesSent;
370
+ this.mid = stats.mid;
371
+ this.mediaSourceId = stats.mediaSourceId;
372
+ this.remoteId = stats.remoteId;
373
+ this.rid = stats.rid;
374
+ this.headerBytesSent = stats.headerBytesSent;
375
+ this.retransmittedPacketsSent = stats.retransmittedPacketsSent;
376
+ this.retransmittedBytesSent = stats.retransmittedBytesSent;
377
+ this.rtxSsrc = stats.rtxSsrc;
378
+ this.targetBitrate = stats.targetBitrate;
379
+ this.totalEncodedBytesTarget = stats.totalEncodedBytesTarget;
380
+ this.frameWidth = stats.frameWidth;
381
+ this.frameHeight = stats.frameHeight;
382
+ this.framesPerSecond = stats.framesPerSecond;
383
+ this.framesSent = stats.framesSent;
384
+ this.hugeFramesSent = stats.hugeFramesSent;
385
+ this.framesEncoded = stats.framesEncoded;
386
+ this.keyFramesEncoded = stats.keyFramesEncoded;
387
+ this.qpSum = stats.qpSum;
388
+ this.totalEncodeTime = stats.totalEncodeTime;
389
+ this.totalPacketSendDelay = stats.totalPacketSendDelay;
390
+ this.qualityLimitationReason = stats.qualityLimitationReason;
391
+ this.qualityLimitationResolutionChanges = stats.qualityLimitationResolutionChanges;
392
+ this.nackCount = stats.nackCount;
393
+ this.firCount = stats.firCount;
394
+ this.pliCount = stats.pliCount;
395
+ this.encoderImplementation = stats.encoderImplementation;
396
+ this.powerEfficientEncoder = stats.powerEfficientEncoder;
397
+ this.active = stats.active;
398
+ this.scalabilityMode = stats.scalabilityMode;
399
+ this.qualityLimitationDurations = stats.qualityLimitationDurations;
400
+ this.attachments = stats.attachments;
401
+ }
402
+ };
403
+
404
+ // src/ObservedCertificate.ts
405
+ var ObservedCertificate = class {
406
+ constructor(timestamp, id, _peerConnection) {
407
+ this.timestamp = timestamp;
408
+ this.id = id;
409
+ this._peerConnection = _peerConnection;
410
+ }
411
+ timestamp;
412
+ id;
413
+ _peerConnection;
414
+ appData;
415
+ _visited = false;
416
+ fingerprint;
417
+ fingerprintAlgorithm;
418
+ base64Certificate;
419
+ issuerCertificateId;
420
+ attachments;
421
+ get visited() {
422
+ const visited = this._visited;
423
+ this._visited = false;
424
+ return visited;
425
+ }
426
+ getPeerConnection() {
427
+ return this._peerConnection;
428
+ }
429
+ update(stats) {
430
+ this._visited = true;
431
+ this.timestamp = stats.timestamp;
432
+ this.fingerprint = stats.fingerprint;
433
+ this.fingerprintAlgorithm = stats.fingerprintAlgorithm;
434
+ this.base64Certificate = stats.base64Certificate;
435
+ this.issuerCertificateId = stats.issuerCertificateId;
436
+ this.attachments = stats.attachments;
437
+ }
438
+ };
439
+
440
+ // src/ObservedCodec.ts
441
+ var ObservedCodec = class {
442
+ constructor(timestamp, id, mimeType, _peerConnection) {
443
+ this.timestamp = timestamp;
444
+ this.id = id;
445
+ this.mimeType = mimeType;
446
+ this._peerConnection = _peerConnection;
447
+ }
448
+ timestamp;
449
+ id;
450
+ mimeType;
451
+ _peerConnection;
452
+ _visited = false;
453
+ appData;
454
+ payloadType;
455
+ transportId;
456
+ clockRate;
457
+ channels;
458
+ sdpFmtpLine;
459
+ attachments;
460
+ get visited() {
461
+ const visited = this._visited;
462
+ this._visited = false;
463
+ return visited;
464
+ }
465
+ getPeerConnection() {
466
+ return this._peerConnection;
467
+ }
468
+ getIceTransport() {
469
+ return this._peerConnection.observedIceTransports.get(this.transportId ?? "");
470
+ }
471
+ update(stats) {
472
+ this._visited = true;
473
+ this.timestamp = stats.timestamp;
474
+ this.payloadType = stats.payloadType;
475
+ this.transportId = stats.transportId;
476
+ this.clockRate = stats.clockRate;
477
+ this.channels = stats.channels;
478
+ this.sdpFmtpLine = stats.sdpFmtpLine;
479
+ this.attachments = stats.attachments;
480
+ }
481
+ };
482
+
483
+ // src/ObservedDataChannel.ts
484
+ var ObservedDataChannel = class {
485
+ constructor(timestamp, id, _peerConnection) {
486
+ this.timestamp = timestamp;
487
+ this.id = id;
488
+ this._peerConnection = _peerConnection;
489
+ }
490
+ timestamp;
491
+ id;
492
+ _peerConnection;
493
+ _visited = false;
494
+ label;
495
+ protocol;
496
+ dataChannelIdentifier;
497
+ state;
498
+ messagesSent;
499
+ bytesSent;
500
+ messagesReceived;
501
+ bytesReceived;
502
+ attachments;
503
+ addedAt;
504
+ removedAt;
505
+ deltaBytesSent = 0;
506
+ deltaBytesReceived = 0;
507
+ deltaMessagesSent = 0;
508
+ deltaMessagesReceived = 0;
509
+ appData;
510
+ get visited() {
511
+ const visited = this._visited;
512
+ this._visited = false;
513
+ return visited;
514
+ }
515
+ getPeerConnection() {
516
+ return this._peerConnection;
517
+ }
518
+ update(stats) {
519
+ this._visited = true;
520
+ if (this.messagesSent && stats.messagesSent && stats.messagesSent >= this.messagesSent) {
521
+ this.deltaMessagesSent = stats.messagesSent - this.messagesSent;
522
+ } else {
523
+ this.deltaMessagesSent = 0;
524
+ }
525
+ if (this.messagesReceived && stats.messagesReceived && stats.messagesReceived >= this.messagesReceived) {
526
+ this.deltaMessagesReceived = stats.messagesReceived - this.messagesReceived;
527
+ } else {
528
+ this.deltaMessagesReceived = 0;
529
+ }
530
+ if (this.bytesSent && stats.bytesSent && stats.bytesSent >= this.bytesSent) {
531
+ this.deltaBytesSent = stats.bytesSent - this.bytesSent;
532
+ } else {
533
+ this.deltaBytesSent = 0;
534
+ }
535
+ if (this.bytesReceived && stats.bytesReceived && stats.bytesReceived >= this.bytesReceived) {
536
+ this.deltaBytesReceived = stats.bytesReceived - this.bytesReceived;
537
+ } else {
538
+ this.deltaBytesReceived = 0;
539
+ }
540
+ this.label = stats.label;
541
+ this.protocol = stats.protocol;
542
+ this.dataChannelIdentifier = stats.dataChannelIdentifier;
543
+ this.state = stats.state;
544
+ this.messagesSent = stats.messagesSent;
545
+ this.bytesSent = stats.bytesSent;
546
+ this.messagesReceived = stats.messagesReceived;
547
+ this.bytesReceived = stats.bytesReceived;
548
+ this.attachments = stats.attachments;
549
+ }
550
+ };
551
+
552
+ // src/ObservedIceCandidate.ts
553
+ var ObservedIceCandidate = class {
554
+ constructor(timestamp, id, _peerConnection) {
555
+ this.timestamp = timestamp;
556
+ this.id = id;
557
+ this._peerConnection = _peerConnection;
558
+ }
559
+ timestamp;
560
+ id;
561
+ _peerConnection;
562
+ _visited = false;
563
+ appData;
564
+ transportId;
565
+ address;
566
+ port;
567
+ protocol;
568
+ candidateType;
569
+ priority;
570
+ url;
571
+ relayProtocol;
572
+ foundation;
573
+ relatedAddress;
574
+ relatedPort;
575
+ usernameFragment;
576
+ tcpType;
577
+ attachments;
578
+ get visited() {
579
+ const visited = this._visited;
580
+ this._visited = false;
581
+ return visited;
582
+ }
583
+ getPeerConnection() {
584
+ return this._peerConnection;
585
+ }
586
+ getIceTransport() {
587
+ return this._peerConnection.observedIceTransports.get(this.transportId ?? "");
588
+ }
589
+ update(stats) {
590
+ this._visited = true;
591
+ this.timestamp = stats.timestamp;
592
+ this.transportId = stats.transportId;
593
+ this.address = stats.address;
594
+ this.port = stats.port;
595
+ this.protocol = stats.protocol;
596
+ this.candidateType = stats.candidateType;
597
+ this.priority = stats.priority;
598
+ this.url = stats.url;
599
+ this.relayProtocol = stats.relayProtocol;
600
+ this.foundation = stats.foundation;
601
+ this.relatedAddress = stats.relatedAddress;
602
+ this.relatedPort = stats.relatedPort;
603
+ this.usernameFragment = stats.usernameFragment;
604
+ this.tcpType = stats.tcpType;
605
+ this.attachments = stats.attachments;
606
+ }
607
+ };
608
+
609
+ // src/ObservedIceCandidatePair.ts
610
+ var ObservedIceCandidatePair = class {
611
+ constructor(timestamp, id, _peerConnection) {
612
+ this.timestamp = timestamp;
613
+ this.id = id;
614
+ this._peerConnection = _peerConnection;
615
+ }
616
+ timestamp;
617
+ id;
618
+ _peerConnection;
619
+ _visited = false;
620
+ appData;
621
+ transportId;
622
+ localCandidateId;
623
+ remoteCandidateId;
624
+ state;
625
+ nominated;
626
+ packetsSent;
627
+ packetsReceived;
628
+ bytesSent;
629
+ bytesReceived;
630
+ lastPacketSentTimestamp;
631
+ lastPacketReceivedTimestamp;
632
+ totalRoundTripTime;
633
+ currentRoundTripTime;
634
+ availableOutgoingBitrate;
635
+ availableIncomingBitrate;
636
+ requestsReceived;
637
+ requestsSent;
638
+ responsesReceived;
639
+ responsesSent;
640
+ consentRequestsSent;
641
+ packetsDiscardedOnSend;
642
+ bytesDiscardedOnSend;
643
+ attachments;
644
+ deltaBytesSent = 0;
645
+ deltaBytesReceived = 0;
646
+ deltaPacketsSent = 0;
647
+ deltaPacketsReceived = 0;
648
+ get visited() {
649
+ const visited = this._visited;
650
+ this._visited = false;
651
+ return visited;
652
+ }
653
+ getPeerConnection() {
654
+ return this._peerConnection;
655
+ }
656
+ getIceTransport() {
657
+ return this._peerConnection.observedIceTransports.get(this.transportId ?? "");
658
+ }
659
+ getLocalCandidate() {
660
+ return this._peerConnection.observedIceCandidates.get(this.localCandidateId ?? "");
661
+ }
662
+ getRemoteCandidate() {
663
+ return this._peerConnection.observedIceCandidates.get(this.remoteCandidateId ?? "");
664
+ }
665
+ update(stats) {
666
+ this._visited = true;
667
+ if (this.packetsSent && stats.packetsSent && stats.packetsSent >= this.packetsSent) {
668
+ this.deltaPacketsSent = stats.packetsSent - this.packetsSent;
669
+ } else {
670
+ this.deltaPacketsSent = 0;
671
+ }
672
+ if (this.packetsReceived && stats.packetsReceived && stats.packetsReceived >= this.packetsReceived) {
673
+ this.deltaPacketsReceived = stats.packetsReceived - this.packetsReceived;
674
+ } else {
675
+ this.deltaPacketsReceived = 0;
676
+ }
677
+ if (this.bytesSent && stats.bytesSent && stats.bytesSent >= this.bytesSent) {
678
+ this.deltaBytesSent = stats.bytesSent - this.bytesSent;
679
+ } else {
680
+ this.deltaBytesSent = 0;
681
+ }
682
+ if (this.bytesReceived && stats.bytesReceived && stats.bytesReceived >= this.bytesReceived) {
683
+ this.deltaBytesReceived = stats.bytesReceived - this.bytesReceived;
684
+ } else {
685
+ this.deltaBytesReceived = 0;
686
+ }
687
+ this.timestamp = stats.timestamp;
688
+ this.transportId = stats.transportId;
689
+ this.localCandidateId = stats.localCandidateId;
690
+ this.remoteCandidateId = stats.remoteCandidateId;
691
+ this.state = this._convertState(stats.state);
692
+ this.nominated = stats.nominated;
693
+ this.packetsSent = stats.packetsSent;
694
+ this.packetsReceived = stats.packetsReceived;
695
+ this.bytesSent = stats.bytesSent;
696
+ this.bytesReceived = stats.bytesReceived;
697
+ this.lastPacketSentTimestamp = stats.lastPacketSentTimestamp;
698
+ this.lastPacketReceivedTimestamp = stats.lastPacketReceivedTimestamp;
699
+ this.totalRoundTripTime = stats.totalRoundTripTime;
700
+ this.currentRoundTripTime = stats.currentRoundTripTime;
701
+ this.availableOutgoingBitrate = stats.availableOutgoingBitrate;
702
+ this.availableIncomingBitrate = stats.availableIncomingBitrate;
703
+ this.requestsReceived = stats.requestsReceived;
704
+ this.requestsSent = stats.requestsSent;
705
+ this.responsesReceived = stats.responsesReceived;
706
+ this.responsesSent = stats.responsesSent;
707
+ this.consentRequestsSent = stats.consentRequestsSent;
708
+ this.packetsDiscardedOnSend = stats.packetsDiscardedOnSend;
709
+ this.bytesDiscardedOnSend = stats.bytesDiscardedOnSend;
710
+ this.attachments = stats.attachments;
711
+ }
712
+ _convertState(state) {
713
+ switch (state) {
714
+ case "new":
715
+ case "in-progress":
716
+ case "waiting":
717
+ case "failed":
718
+ case "succeeded":
719
+ return state;
720
+ case "cancelled":
721
+ return "failed";
722
+ case "inprogress":
723
+ return "in-progress";
724
+ default:
725
+ return void 0;
726
+ }
727
+ }
728
+ };
729
+
730
+ // src/ObservedIceTransport.ts
731
+ var ObservedIceTransport = class {
732
+ constructor(timestamp, id, _peerConnection) {
733
+ this.timestamp = timestamp;
734
+ this.id = id;
735
+ this._peerConnection = _peerConnection;
736
+ }
737
+ timestamp;
738
+ id;
739
+ _peerConnection;
740
+ _visited = false;
741
+ appData;
742
+ packetsSent;
743
+ packetsReceived;
744
+ bytesSent;
745
+ bytesReceived;
746
+ iceRole;
747
+ iceLocalUsernameFragment;
748
+ dtlsState;
749
+ iceState;
750
+ selectedCandidatePairId;
751
+ localCertificateId;
752
+ remoteCertificateId;
753
+ tlsVersion;
754
+ dtlsCipher;
755
+ dtlsRole;
756
+ srtpCipher;
757
+ selectedCandidatePairChanges;
758
+ attachments;
759
+ deltaPacketsReceived = 0;
760
+ deltaPacketsSent = 0;
761
+ deltaBytesReceived = 0;
762
+ deltaBytesSent = 0;
763
+ get visited() {
764
+ const visited = this._visited;
765
+ this._visited = false;
766
+ return visited;
767
+ }
768
+ getPeerConnection() {
769
+ return this._peerConnection;
770
+ }
771
+ getSelectedCandidatePair() {
772
+ return this._peerConnection.observedIceCandidatesPair.get(this.selectedCandidatePairId ?? "");
773
+ }
774
+ update(stats) {
775
+ this._visited = true;
776
+ if (this.bytesReceived !== void 0 && stats.bytesReceived !== void 0 && this.bytesReceived <= stats.bytesReceived) {
777
+ this.deltaBytesReceived = stats.bytesReceived - this.bytesReceived;
778
+ } else {
779
+ this.deltaBytesReceived = 0;
780
+ }
781
+ if (this.bytesSent !== void 0 && stats.bytesSent !== void 0 && this.bytesSent <= stats.bytesSent) {
782
+ this.deltaBytesSent = stats.bytesSent - this.bytesSent;
783
+ } else {
784
+ this.deltaBytesSent = 0;
785
+ }
786
+ if (this.packetsReceived !== void 0 && stats.packetsReceived !== void 0 && this.packetsReceived <= stats.packetsReceived) {
787
+ this.deltaPacketsReceived = stats.packetsReceived - this.packetsReceived;
788
+ } else {
789
+ this.deltaPacketsReceived = 0;
790
+ }
791
+ if (this.packetsSent !== void 0 && stats.packetsSent !== void 0 && this.packetsSent <= stats.packetsSent) {
792
+ this.deltaPacketsSent = stats.packetsSent - this.packetsSent;
793
+ } else {
794
+ this.deltaPacketsSent = 0;
795
+ }
796
+ this.timestamp = stats.timestamp;
797
+ this.packetsSent = stats.packetsSent;
798
+ this.packetsReceived = stats.packetsReceived;
799
+ this.bytesSent = stats.bytesSent;
800
+ this.bytesReceived = stats.bytesReceived;
801
+ this.iceRole = stats.iceRole;
802
+ this.iceLocalUsernameFragment = stats.iceLocalUsernameFragment;
803
+ this.dtlsState = stats.dtlsState;
804
+ this.iceState = stats.iceState;
805
+ this.selectedCandidatePairId = stats.selectedCandidatePairId;
806
+ this.localCertificateId = stats.localCertificateId;
807
+ this.remoteCertificateId = stats.remoteCertificateId;
808
+ this.tlsVersion = stats.tlsVersion;
809
+ this.dtlsCipher = stats.dtlsCipher;
810
+ this.dtlsRole = stats.dtlsRole;
811
+ this.srtpCipher = stats.srtpCipher;
812
+ this.selectedCandidatePairChanges = stats.selectedCandidatePairChanges;
813
+ this.attachments = stats.attachments;
814
+ }
815
+ };
816
+
817
+ // src/ObservedMediaSource.ts
818
+ var ObservedMediaSource = class {
819
+ constructor(timestamp, id, kind, _peerConnection) {
820
+ this.timestamp = timestamp;
821
+ this.id = id;
822
+ this.kind = kind;
823
+ this._peerConnection = _peerConnection;
824
+ }
825
+ timestamp;
826
+ id;
827
+ kind;
828
+ _peerConnection;
829
+ _visited = false;
830
+ appData;
831
+ trackIdentifier;
832
+ audioLevel;
833
+ totalAudioEnergy;
834
+ totalSamplesDuration;
835
+ echoReturnLoss;
836
+ echoReturnLossEnhancement;
837
+ width;
838
+ height;
839
+ frames;
840
+ framesPerSecond;
841
+ attachments;
842
+ get visited() {
843
+ const visited = this._visited;
844
+ this._visited = false;
845
+ return visited;
846
+ }
847
+ getPeerConnection() {
848
+ return this._peerConnection;
849
+ }
850
+ getTrack() {
851
+ return this._peerConnection.observedOutboundTracks.get(this.trackIdentifier ?? "");
852
+ }
853
+ update(stats) {
854
+ this._visited = true;
855
+ this.timestamp = stats.timestamp;
856
+ this.trackIdentifier = stats.trackIdentifier;
857
+ this.audioLevel = stats.audioLevel;
858
+ this.totalAudioEnergy = stats.totalAudioEnergy;
859
+ this.totalSamplesDuration = stats.totalSamplesDuration;
860
+ this.echoReturnLoss = stats.echoReturnLoss;
861
+ this.echoReturnLossEnhancement = stats.echoReturnLossEnhancement;
862
+ this.width = stats.width;
863
+ this.height = stats.height;
864
+ this.frames = stats.frames;
865
+ this.framesPerSecond = stats.framesPerSecond;
866
+ this.attachments = stats.attachments;
867
+ }
868
+ };
869
+
870
+ // src/ObservedPeerConnectionTransport.ts
871
+ var ObservedPeerConnectionTransport = class {
872
+ constructor(timestamp, id, _peerConnection) {
873
+ this.timestamp = timestamp;
874
+ this.id = id;
875
+ this._peerConnection = _peerConnection;
876
+ }
877
+ timestamp;
878
+ id;
879
+ _peerConnection;
880
+ _visited = false;
881
+ appData;
882
+ dataChannelsOpened;
883
+ dataChannelsClosed;
884
+ attachments;
885
+ get visited() {
886
+ const visited = this._visited;
887
+ this._visited = false;
888
+ return visited;
889
+ }
890
+ getPeerConnection() {
891
+ return this._peerConnection;
892
+ }
893
+ update(stats) {
894
+ this._visited = true;
895
+ this.timestamp = stats.timestamp;
896
+ this.dataChannelsOpened = stats.dataChannelsOpened;
897
+ this.dataChannelsClosed = stats.dataChannelsClosed;
898
+ this.attachments = stats.attachments;
899
+ }
900
+ };
901
+
902
+ // src/ObservedMediaPlayout.ts
903
+ var ObservedMediaPlayout = class {
904
+ constructor(timestamp, id, kind, _peerConnection) {
905
+ this.timestamp = timestamp;
906
+ this.id = id;
907
+ this.kind = kind;
908
+ this._peerConnection = _peerConnection;
909
+ }
910
+ timestamp;
911
+ id;
912
+ kind;
913
+ _peerConnection;
914
+ _visited = false;
915
+ appData;
916
+ synthesizedSamplesDuration;
917
+ synthesizedSamplesEvents;
918
+ totalSamplesDuration;
919
+ totalPlayoutDelay;
920
+ totalSamplesCount;
921
+ attachments;
922
+ get visited() {
923
+ const visited = this._visited;
924
+ this._visited = false;
925
+ return visited;
926
+ }
927
+ getPeerConnection() {
928
+ return this._peerConnection;
929
+ }
930
+ update(stats) {
931
+ this._visited = true;
932
+ this.timestamp = stats.timestamp;
933
+ this.synthesizedSamplesDuration = stats.synthesizedSamplesDuration;
934
+ this.synthesizedSamplesEvents = stats.synthesizedSamplesEvents;
935
+ this.totalSamplesDuration = stats.totalSamplesDuration;
936
+ this.totalPlayoutDelay = stats.totalPlayoutDelay;
937
+ this.totalSamplesCount = stats.totalSamplesCount;
938
+ this.attachments = stats.attachments;
939
+ }
940
+ };
941
+
942
+ // src/ObservedRemoteInboundRtp.ts
943
+ var ObservedRemoteInboundRtp = class {
944
+ constructor(timestamp, id, ssrc, kind, _peerConnection) {
945
+ this.timestamp = timestamp;
946
+ this.id = id;
947
+ this.ssrc = ssrc;
948
+ this.kind = kind;
949
+ this._peerConnection = _peerConnection;
950
+ }
951
+ timestamp;
952
+ id;
953
+ ssrc;
954
+ kind;
955
+ _peerConnection;
956
+ _visited = false;
957
+ appData;
958
+ transportId;
959
+ codecId;
960
+ packetsReceived;
961
+ packetsLost;
962
+ jitter;
963
+ localId;
964
+ roundTripTime;
965
+ totalRoundTripTime;
966
+ fractionLost;
967
+ roundTripTimeMeasurements;
968
+ attachments;
969
+ get visited() {
970
+ const visited = this._visited;
971
+ this._visited = false;
972
+ return visited;
973
+ }
974
+ getPeerConnection() {
975
+ return this._peerConnection;
976
+ }
977
+ getOutboundRtp() {
978
+ return this._peerConnection.observedOutboundRtps.get(this.ssrc);
979
+ }
980
+ getCodec() {
981
+ return this._peerConnection.observedCodecs.get(this.codecId ?? "");
982
+ }
983
+ update(stats) {
984
+ this._visited = true;
985
+ this.timestamp = stats.timestamp;
986
+ this.transportId = stats.transportId;
987
+ this.codecId = stats.codecId;
988
+ this.packetsReceived = stats.packetsReceived;
989
+ this.packetsLost = stats.packetsLost;
990
+ this.jitter = stats.jitter;
991
+ this.localId = stats.localId;
992
+ this.roundTripTime = stats.roundTripTime;
993
+ this.totalRoundTripTime = stats.totalRoundTripTime;
994
+ this.fractionLost = stats.fractionLost;
995
+ this.roundTripTimeMeasurements = stats.roundTripTimeMeasurements;
996
+ this.attachments = stats.attachments;
997
+ }
998
+ };
999
+
1000
+ // src/ObservedRemoteOutboundRtp.ts
1001
+ var ObservedRemoteOutboundRtp = class {
1002
+ constructor(timestamp, id, ssrc, kind, _peerConnection) {
1003
+ this.timestamp = timestamp;
1004
+ this.id = id;
1005
+ this.ssrc = ssrc;
1006
+ this.kind = kind;
1007
+ this._peerConnection = _peerConnection;
1008
+ }
1009
+ timestamp;
1010
+ id;
1011
+ ssrc;
1012
+ kind;
1013
+ _peerConnection;
1014
+ _visited = false;
1015
+ appData;
1016
+ transportId;
1017
+ codecId;
1018
+ packetsSent;
1019
+ bytesSent;
1020
+ localId;
1021
+ remoteTimestamp;
1022
+ reportsSent;
1023
+ roundTripTime;
1024
+ totalRoundTripTime;
1025
+ roundTripTimeMeasurements;
1026
+ attachments;
1027
+ get visited() {
1028
+ const visited = this._visited;
1029
+ this._visited = false;
1030
+ return visited;
1031
+ }
1032
+ getPeerConnection() {
1033
+ return this._peerConnection;
1034
+ }
1035
+ getInboundRtp() {
1036
+ return this._peerConnection.observedInboundRtps.get(this.ssrc);
1037
+ }
1038
+ getCodec() {
1039
+ return this._peerConnection.observedCodecs.get(this.codecId ?? "");
1040
+ }
1041
+ update(stats) {
1042
+ this._visited = true;
1043
+ this.timestamp = stats.timestamp;
1044
+ this.transportId = stats.transportId;
1045
+ this.codecId = stats.codecId;
1046
+ this.packetsSent = stats.packetsSent;
1047
+ this.bytesSent = stats.bytesSent;
1048
+ this.localId = stats.localId;
1049
+ this.remoteTimestamp = stats.remoteTimestamp;
1050
+ this.reportsSent = stats.reportsSent;
1051
+ this.roundTripTime = stats.roundTripTime;
1052
+ this.totalRoundTripTime = stats.totalRoundTripTime;
1053
+ this.roundTripTimeMeasurements = stats.roundTripTimeMeasurements;
1054
+ this.attachments = stats.attachments;
1055
+ }
1056
+ };
1057
+
1058
+ // src/ObservedInboundTrack.ts
1059
+ var ObservedInboundTrack = class {
1060
+ constructor(timestamp, id, kind, _peerConnection, _inboundRtp, _mediaPlayout) {
1061
+ this.timestamp = timestamp;
1062
+ this.id = id;
1063
+ this.kind = kind;
1064
+ this._peerConnection = _peerConnection;
1065
+ this._inboundRtp = _inboundRtp;
1066
+ this._mediaPlayout = _mediaPlayout;
1067
+ this.report = {
1068
+ trackId: this.id,
1069
+ kind: this.kind,
1070
+ fractionLostDistribution: {
1071
+ gtOrEq050: 0,
1072
+ lt001: 0,
1073
+ lt005: 0,
1074
+ lt010: 0,
1075
+ lt020: 0,
1076
+ lt050: 0,
1077
+ count: 0,
1078
+ sum: 0
1079
+ }
1080
+ };
1081
+ }
1082
+ timestamp;
1083
+ id;
1084
+ kind;
1085
+ _peerConnection;
1086
+ _inboundRtp;
1087
+ _mediaPlayout;
1088
+ calculatedScore = {
1089
+ weight: 1,
1090
+ value: void 0
1091
+ };
1092
+ appData;
1093
+ report;
1094
+ _visited = false;
1095
+ addedAt;
1096
+ removedAt;
1097
+ muted;
1098
+ attachments;
1099
+ get score() {
1100
+ return this.calculatedScore.value;
1101
+ }
1102
+ get visited() {
1103
+ const visited = this._visited;
1104
+ this._visited = false;
1105
+ return visited;
1106
+ }
1107
+ getPeerConnection() {
1108
+ return this._peerConnection;
1109
+ }
1110
+ getInboundRtp() {
1111
+ return this._inboundRtp;
1112
+ }
1113
+ getMediaPlayout() {
1114
+ return this._mediaPlayout;
1115
+ }
1116
+ getRemoteOutboundTrack() {
1117
+ var _a;
1118
+ return (_a = this._peerConnection.client.call.remoteTrackResolver) == null ? void 0 : _a.resolveRemoteOutboundTrack(this);
1119
+ }
1120
+ update(stats) {
1121
+ var _a;
1122
+ this._visited = true;
1123
+ this.timestamp = stats.timestamp;
1124
+ this.calculatedScore.value = stats.score;
1125
+ this.attachments = stats.attachments;
1126
+ const fl = (_a = this._inboundRtp) == null ? void 0 : _a.fractionLost;
1127
+ if (fl !== void 0) {
1128
+ if (fl < 0.01) this.report.fractionLostDistribution.lt001 += 1;
1129
+ else if (fl < 0.05) this.report.fractionLostDistribution.lt005 += 1;
1130
+ else if (fl < 0.1) this.report.fractionLostDistribution.lt010 += 1;
1131
+ else if (fl < 0.2) this.report.fractionLostDistribution.lt020 += 1;
1132
+ else if (fl < 0.5) this.report.fractionLostDistribution.lt050 += 1;
1133
+ else this.report.fractionLostDistribution.gtOrEq050 += 1;
1134
+ this.report.fractionLostDistribution.count += 1;
1135
+ this.report.fractionLostDistribution.sum += fl;
1136
+ }
1137
+ }
1138
+ };
1139
+
1140
+ // src/ObservedOutboundTrack.ts
1141
+ var ObservedOutboundTrack = class {
1142
+ constructor(timestamp, id, kind, _peerConnection, _outboundRtps, _mediaSource) {
1143
+ this.timestamp = timestamp;
1144
+ this.id = id;
1145
+ this.kind = kind;
1146
+ this._peerConnection = _peerConnection;
1147
+ this._outboundRtps = _outboundRtps;
1148
+ this._mediaSource = _mediaSource;
1149
+ this.report = {
1150
+ trackId: this.id,
1151
+ kind: this.kind
1152
+ };
1153
+ }
1154
+ timestamp;
1155
+ id;
1156
+ kind;
1157
+ _peerConnection;
1158
+ _outboundRtps;
1159
+ _mediaSource;
1160
+ _visited = false;
1161
+ appData;
1162
+ report;
1163
+ calculatedScore = {
1164
+ weight: 1,
1165
+ value: void 0
1166
+ };
1167
+ addedAt;
1168
+ removedAt;
1169
+ muted;
1170
+ attachments;
1171
+ get score() {
1172
+ return this.calculatedScore.value;
1173
+ }
1174
+ get visited() {
1175
+ const visited = this._visited;
1176
+ this._visited = false;
1177
+ return visited;
1178
+ }
1179
+ getPeerConnection() {
1180
+ return this._peerConnection;
1181
+ }
1182
+ getOutboundRtps() {
1183
+ return this._outboundRtps;
1184
+ }
1185
+ getMediaSource() {
1186
+ return this._mediaSource;
1187
+ }
1188
+ getRemoteInboundTracks() {
1189
+ var _a;
1190
+ return (_a = this._peerConnection.client.call.remoteTrackResolver) == null ? void 0 : _a.resolveRemoteInboundTracks(this);
1191
+ }
1192
+ update(stats) {
1193
+ this._visited = true;
1194
+ this.timestamp = stats.timestamp;
1195
+ this.calculatedScore.value = stats.score;
1196
+ this.attachments = stats.attachments;
1197
+ }
1198
+ };
1199
+
1200
+ // src/common/utils.ts
1201
+ function getMedian(arr, copyArrayForSorting = true) {
1202
+ const sortedArr = copyArrayForSorting ? arr.slice().sort((a, b) => a - b) : arr.sort((a, b) => a - b);
1203
+ const mid = Math.floor(sortedArr.length / 2);
1204
+ if (sortedArr.length % 2 !== 0) {
1205
+ return sortedArr[mid];
1206
+ }
1207
+ return (sortedArr[mid - 1] + sortedArr[mid]) / 2;
1208
+ }
1209
+ function parseJsonAs(json) {
1210
+ if (!json) {
1211
+ return void 0;
1212
+ }
1213
+ try {
1214
+ return JSON.parse(json);
1215
+ } catch (error) {
1216
+ return void 0;
1217
+ }
1218
+ }
1219
+
1220
+ // src/ObservedPeerConnection.ts
1221
+ var logger = createLogger("ObservedPeerConnection");
1222
+ var ObservedPeerConnection = class extends EventEmitter {
1223
+ constructor(peerConnectionId, client) {
1224
+ super();
1225
+ this.peerConnectionId = peerConnectionId;
1226
+ this.client = client;
1227
+ this.setMaxListeners(Infinity);
1228
+ this.eventScope = {
1229
+ observer: client.call.observer,
1230
+ observedCall: client.call,
1231
+ observedClient: client,
1232
+ observedPeerConnection: this
1233
+ };
1234
+ }
1235
+ peerConnectionId;
1236
+ client;
1237
+ _visited = true;
1238
+ appData;
1239
+ calculatedScore = {
1240
+ weight: 1,
1241
+ value: void 0
1242
+ };
1243
+ closed = false;
1244
+ // timestamp of the PEER_CONNECTION_OPENED event
1245
+ openedAt;
1246
+ // timestamp of the PEER_CONNECTION_CLOSED event
1247
+ closedAt;
1248
+ updated = Date.now();
1249
+ connectionState;
1250
+ iceConnectionState;
1251
+ iceGatheringState;
1252
+ availableIncomingBitrate = 0;
1253
+ availableOutgoingBitrate = 0;
1254
+ totalInboundPacketsLost = 0;
1255
+ totalInboundPacketsReceived = 0;
1256
+ totalOutboundPacketsSent = 0;
1257
+ totalDataChannelBytesSent = 0;
1258
+ totalDataChannelBytesReceived = 0;
1259
+ totalDataChannelMessagesSent = 0;
1260
+ totalDataChannelMessagesReceived = 0;
1261
+ totalSentAudioBytes = 0;
1262
+ totalSentVideoBytes = 0;
1263
+ totalSentAudioPackets = 0;
1264
+ totalSentVideoPackets = 0;
1265
+ totalReceivedAudioPacktes = 0;
1266
+ totalReceivedVideoPackets = 0;
1267
+ totalReceivedAudioBytes = 0;
1268
+ totalReceivedVideoBytes = 0;
1269
+ deltaInboundPacketsLost = 0;
1270
+ deltaInboundPacketsReceived = 0;
1271
+ deltaOutboundPacketsSent = 0;
1272
+ deltaDataChannelBytesSent = 0;
1273
+ deltaDataChannelBytesReceived = 0;
1274
+ deltaDataChannelMessagesSent = 0;
1275
+ deltaDataChannelMessagesReceived = 0;
1276
+ deltaInboundReceivedBytes = 0;
1277
+ deltaOutboundSentBytes = 0;
1278
+ deltaReceivedAudioBytes = 0;
1279
+ deltaReceivedVideoBytes = 0;
1280
+ deltaReceivedAudioPackets = 0;
1281
+ deltaReceivedVideoPackets = 0;
1282
+ deltaSentAudioBytes = 0;
1283
+ deltaSentVideoBytes = 0;
1284
+ deltaSentAudioPackets = 0;
1285
+ deltaSentVideoPackets = 0;
1286
+ deltaTransportSentBytes = 0;
1287
+ deltaTransportReceivedBytes = 0;
1288
+ receivingPacketsPerSecond = 0;
1289
+ sendingPacketsPerSecond = 0;
1290
+ sendingAudioBitrate = 0;
1291
+ sendingVideoBitrate = 0;
1292
+ receivingAudioBitrate = 0;
1293
+ receivingVideoBitrate = 0;
1294
+ currentRttInMs;
1295
+ currentJitter;
1296
+ usingTCP = false;
1297
+ usingTURN = false;
1298
+ observedTurnServer;
1299
+ observedCertificates = /* @__PURE__ */ new Map();
1300
+ observedCodecs = /* @__PURE__ */ new Map();
1301
+ observedDataChannels = /* @__PURE__ */ new Map();
1302
+ observedIceCandidates = /* @__PURE__ */ new Map();
1303
+ observedIceCandidatesPair = /* @__PURE__ */ new Map();
1304
+ observedIceTransports = /* @__PURE__ */ new Map();
1305
+ observedInboundRtps = /* @__PURE__ */ new Map();
1306
+ observedInboundTracks = /* @__PURE__ */ new Map();
1307
+ observedMediaPlayouts = /* @__PURE__ */ new Map();
1308
+ observedMediaSources = /* @__PURE__ */ new Map();
1309
+ observedOutboundRtps = /* @__PURE__ */ new Map();
1310
+ observedOutboundTracks = /* @__PURE__ */ new Map();
1311
+ observedPeerConnectionTransports = /* @__PURE__ */ new Map();
1312
+ observedRemoteInboundRtps = /* @__PURE__ */ new Map();
1313
+ observedRemoteOutboundRtps = /* @__PURE__ */ new Map();
1314
+ eventScope;
1315
+ get score() {
1316
+ return this.calculatedScore.value;
1317
+ }
1318
+ get visited() {
1319
+ const visited = this._visited;
1320
+ this._visited = false;
1321
+ return visited;
1322
+ }
1323
+ get codecs() {
1324
+ return [...this.observedCodecs.values()];
1325
+ }
1326
+ get inboundRtps() {
1327
+ return [...this.observedInboundRtps.values()];
1328
+ }
1329
+ get remoteOutboundRtps() {
1330
+ return [...this.observedRemoteOutboundRtps.values()];
1331
+ }
1332
+ get outboundRtps() {
1333
+ return [...this.observedOutboundRtps.values()];
1334
+ }
1335
+ get remoteInboundRtps() {
1336
+ return [...this.observedRemoteInboundRtps.values()];
1337
+ }
1338
+ get mediaSources() {
1339
+ return [...this.observedMediaSources.values()];
1340
+ }
1341
+ get mediaPlayouts() {
1342
+ return [...this.observedMediaPlayouts.values()];
1343
+ }
1344
+ get dataChannels() {
1345
+ return [...this.observedDataChannels.values()];
1346
+ }
1347
+ get peerConnectionTransports() {
1348
+ return [...this.observedPeerConnectionTransports.values()];
1349
+ }
1350
+ get iceTransports() {
1351
+ return [...this.observedIceTransports.values()];
1352
+ }
1353
+ get iceCandidates() {
1354
+ return [...this.observedIceCandidates.values()];
1355
+ }
1356
+ get iceCandidatePairs() {
1357
+ return [...this.observedIceCandidatesPair.values()];
1358
+ }
1359
+ get certificates() {
1360
+ return [...this.observedCertificates.values()];
1361
+ }
1362
+ get selectedIceCandidatePairs() {
1363
+ return this.iceTransports.map((iceTransport) => iceTransport.getSelectedCandidatePair()).filter((pair) => pair !== void 0);
1364
+ }
1365
+ get selectedIceCandiadtePairForTurn() {
1366
+ return this.selectedIceCandidatePairs.filter(
1367
+ (pair) => {
1368
+ var _a, _b, _c;
1369
+ return ((_a = pair.getLocalCandidate()) == null ? void 0 : _a.candidateType) === "relay" && ((_c = (_b = pair.getRemoteCandidate()) == null ? void 0 : _b.url) == null ? void 0 : _c.startsWith("turn:"));
1370
+ }
1371
+ );
1372
+ }
1373
+ close() {
1374
+ if (this.closed) return;
1375
+ this.closed = true;
1376
+ this.observedCertificates.forEach((observedCertificate) => this._notify("certificate-removed", { ...this.eventScope, observedCertificate }));
1377
+ this.observedCodecs.forEach((observedCodec) => this._notify("codec-removed", { ...this.eventScope, observedCodec }));
1378
+ this.observedDataChannels.forEach((observedDataChannel) => this._notify("data-channel-removed", { ...this.eventScope, observedDataChannel }));
1379
+ this.observedIceCandidates.forEach((observedIceCandidate) => this._notify("ice-candidate-removed", { ...this.eventScope, observedIceCandidate }));
1380
+ this.observedIceCandidatesPair.forEach((pair) => this._notify("ice-candidate-pair-removed", { ...this.eventScope, observedIceCandidatePair: pair }));
1381
+ this.observedIceTransports.forEach((transport) => this._notify("ice-transport-removed", { ...this.eventScope, observedIceTransport: transport }));
1382
+ this.observedInboundRtps.forEach((rtp) => this._notify("inbound-rtp-removed", { ...this.eventScope, observedInboundRtp: rtp }));
1383
+ this.observedInboundTracks.forEach((track) => {
1384
+ this.emit("removed-inbound-track", track);
1385
+ this._notify("inbound-track-removed", { ...this.eventScope, observedInboundTrack: track });
1386
+ });
1387
+ this.observedMediaPlayouts.forEach((playout) => this._notify("media-playout-removed", { ...this.eventScope, observedMediaPlayout: playout }));
1388
+ this.observedMediaSources.forEach((source) => this._notify("media-source-removed", { ...this.eventScope, observedMediaSource: source }));
1389
+ this.observedOutboundRtps.forEach((rtp) => this._notify("outbound-rtp-removed", { ...this.eventScope, observedOutboundRtp: rtp }));
1390
+ this.observedOutboundTracks.forEach((track) => {
1391
+ this.emit("removed-outbound-track", track);
1392
+ this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack: track });
1393
+ });
1394
+ this.observedPeerConnectionTransports.forEach((transport) => this._notify("peer-connection-transport-removed", { ...this.eventScope, observedPeerConnectionTransport: transport }));
1395
+ this.observedRemoteInboundRtps.forEach((rtp) => this._notify("remote-inbound-rtp-removed", { ...this.eventScope, observedRemoteInboundRtp: rtp }));
1396
+ this.observedRemoteOutboundRtps.forEach((rtp) => this._notify("remote-outbound-rtp-removed", { ...this.eventScope, observedRemoteOutboundRtp: rtp }));
1397
+ this.observedCertificates.clear();
1398
+ this.observedCodecs.clear();
1399
+ this.observedDataChannels.clear();
1400
+ this.observedIceCandidates.clear();
1401
+ this.observedIceCandidatesPair.clear();
1402
+ this.observedIceTransports.clear();
1403
+ this.observedInboundRtps.clear();
1404
+ this.observedInboundTracks.clear();
1405
+ this.observedMediaPlayouts.clear();
1406
+ this.observedMediaSources.clear();
1407
+ this.observedOutboundRtps.clear();
1408
+ this.observedOutboundTracks.clear();
1409
+ this.observedPeerConnectionTransports.clear();
1410
+ this.observedRemoteInboundRtps.clear();
1411
+ this.observedRemoteOutboundRtps.clear();
1412
+ this.client.call.observer.observedTURN.removePeerConnection(this);
1413
+ if (!this.closedAt) this.closedAt = Date.now();
1414
+ this.emit("close");
1415
+ this._notify("peer-connection-closed", { ...this.eventScope });
1416
+ }
1417
+ accept(sample, context) {
1418
+ var _a, _b, _c, _d, _e;
1419
+ if (this.closed) return;
1420
+ this._visited = true;
1421
+ if (context) this.appData = { ...this.appData, ...context };
1422
+ this.availableIncomingBitrate = 0;
1423
+ this.availableOutgoingBitrate = 0;
1424
+ this.deltaInboundPacketsLost = 0;
1425
+ this.deltaInboundPacketsReceived = 0;
1426
+ this.deltaOutboundPacketsSent = 0;
1427
+ this.deltaDataChannelBytesSent = 0;
1428
+ this.deltaDataChannelBytesReceived = 0;
1429
+ this.deltaInboundReceivedBytes = 0;
1430
+ this.deltaOutboundSentBytes = 0;
1431
+ this.deltaReceivedAudioBytes = 0;
1432
+ this.deltaReceivedVideoBytes = 0;
1433
+ this.deltaReceivedAudioPackets = 0;
1434
+ this.deltaReceivedVideoPackets = 0;
1435
+ this.deltaSentAudioBytes = 0;
1436
+ this.deltaSentVideoBytes = 0;
1437
+ this.deltaSentAudioPackets = 0;
1438
+ this.deltaSentVideoPackets = 0;
1439
+ this.deltaTransportReceivedBytes = 0;
1440
+ this.deltaTransportSentBytes = 0;
1441
+ this.sendingAudioBitrate = 0;
1442
+ this.sendingVideoBitrate = 0;
1443
+ this.receivingAudioBitrate = 0;
1444
+ this.receivingVideoBitrate = 0;
1445
+ const now = Date.now();
1446
+ const elapsedTimeInMs = now - this.updated;
1447
+ const elapsedTimeInSec = elapsedTimeInMs / 1e3;
1448
+ const rttMeasurementsInSec = [];
1449
+ const jitterMeasurements = [];
1450
+ if (sample.certificates) {
1451
+ for (const certificate of sample.certificates) {
1452
+ this._updateCertificateStats(certificate);
1453
+ }
1454
+ }
1455
+ if (sample.codecs) {
1456
+ for (const codec of sample.codecs) {
1457
+ this._updateCodecStats(codec);
1458
+ }
1459
+ }
1460
+ if (sample.dataChannels) {
1461
+ for (const dataChannel of sample.dataChannels) {
1462
+ const observedDataChannel = this._updateDataChannelStats(dataChannel);
1463
+ if (!observedDataChannel) continue;
1464
+ this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
1465
+ this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
1466
+ this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
1467
+ this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
1468
+ }
1469
+ }
1470
+ if (sample.iceCandidates) {
1471
+ for (const iceCandidate of sample.iceCandidates) {
1472
+ this._updateIceCandidateStats(iceCandidate);
1473
+ }
1474
+ }
1475
+ if (sample.iceCandidatePairs) {
1476
+ for (const iceCandidatePair of sample.iceCandidatePairs) {
1477
+ const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
1478
+ if (!observedCandidatePair) continue;
1479
+ if (observedCandidatePair.currentRoundTripTime) {
1480
+ rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
1481
+ }
1482
+ if (observedCandidatePair.availableIncomingBitrate) {
1483
+ this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
1484
+ }
1485
+ if (observedCandidatePair.availableOutgoingBitrate) {
1486
+ this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
1487
+ }
1488
+ }
1489
+ }
1490
+ if (sample.iceTransports) {
1491
+ for (const iceTransport of sample.iceTransports) {
1492
+ const observedIceTransport = this._updateIceTransportStats(iceTransport);
1493
+ if (!observedIceTransport) continue;
1494
+ }
1495
+ }
1496
+ if (sample.inboundRtps) {
1497
+ for (const inboundRtp of sample.inboundRtps) {
1498
+ const observedInboundRtp = this._updateInboundRtpStats(inboundRtp);
1499
+ if (!observedInboundRtp) continue;
1500
+ this.deltaInboundPacketsLost += observedInboundRtp.deltaLostPackets;
1501
+ this.deltaInboundPacketsReceived += observedInboundRtp.deltaReceivedPackets;
1502
+ this.deltaInboundReceivedBytes += observedInboundRtp.deltaBytesReceived;
1503
+ switch (inboundRtp.kind) {
1504
+ case "audio":
1505
+ this.deltaReceivedAudioBytes += observedInboundRtp.deltaBytesReceived;
1506
+ this.deltaReceivedAudioPackets += observedInboundRtp.deltaReceivedPackets;
1507
+ break;
1508
+ case "video":
1509
+ this.deltaReceivedVideoBytes += observedInboundRtp.deltaBytesReceived;
1510
+ this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
1511
+ break;
1512
+ }
1513
+ if (observedInboundRtp.jitter) {
1514
+ jitterMeasurements.push(observedInboundRtp.jitter);
1515
+ }
1516
+ }
1517
+ }
1518
+ if (sample.mediaPlayouts) {
1519
+ for (const mediaPlayout of sample.mediaPlayouts) {
1520
+ this._updateMediaPlayoutStats(mediaPlayout);
1521
+ }
1522
+ }
1523
+ if (sample.mediaSources) {
1524
+ for (const mediaSource of sample.mediaSources) {
1525
+ this._updateMediaSourceStats(mediaSource);
1526
+ }
1527
+ }
1528
+ if (sample.outboundRtps) {
1529
+ for (const outboundRtp of sample.outboundRtps) {
1530
+ const observedOutboundRtp = this._updateOutboundRtpStats(outboundRtp);
1531
+ if (!observedOutboundRtp) continue;
1532
+ this.deltaOutboundPacketsSent += observedOutboundRtp.deltaPacketsSent ?? 0;
1533
+ this.deltaOutboundSentBytes += observedOutboundRtp.deltaBytesSent ?? 0;
1534
+ switch (outboundRtp.kind) {
1535
+ case "audio":
1536
+ this.deltaSentAudioBytes += observedOutboundRtp.deltaBytesSent;
1537
+ this.deltaSentAudioPackets += observedOutboundRtp.deltaPacketsSent;
1538
+ break;
1539
+ case "video":
1540
+ this.deltaSentVideoBytes += observedOutboundRtp.deltaBytesSent;
1541
+ this.deltaSentVideoPackets += observedOutboundRtp.deltaPacketsSent;
1542
+ break;
1543
+ }
1544
+ }
1545
+ }
1546
+ if (sample.peerConnectionTransports) {
1547
+ for (const peerConnectionTransport of sample.peerConnectionTransports) {
1548
+ const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
1549
+ if (!observedTransport) continue;
1550
+ }
1551
+ }
1552
+ if (sample.remoteInboundRtps) {
1553
+ for (const remoteInboundRtp of sample.remoteInboundRtps) {
1554
+ const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
1555
+ if (!observedRemoteInboundRtp) continue;
1556
+ if (observedRemoteInboundRtp.roundTripTime) {
1557
+ rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
1558
+ }
1559
+ const observedOutboundRtp = observedRemoteInboundRtp.getOutboundRtp();
1560
+ if (observedOutboundRtp) {
1561
+ if (observedRemoteInboundRtp.roundTripTime !== void 0) {
1562
+ observedOutboundRtp.remoteRttInMs = observedRemoteInboundRtp.roundTripTime * 1e3;
1563
+ }
1564
+ if (observedRemoteInboundRtp.fractionLost !== void 0) {
1565
+ observedOutboundRtp.remoteFractionLost = observedRemoteInboundRtp.fractionLost;
1566
+ }
1567
+ if (observedRemoteInboundRtp.jitter !== void 0) {
1568
+ observedOutboundRtp.remoteJitter = observedRemoteInboundRtp.jitter;
1569
+ }
1570
+ if (observedRemoteInboundRtp.packetsLost !== void 0) {
1571
+ observedOutboundRtp.remotePacketsLost = observedRemoteInboundRtp.packetsLost;
1572
+ }
1573
+ }
1574
+ }
1575
+ }
1576
+ if (sample.remoteOutboundRtps) {
1577
+ for (const remoteOutboundRtp of sample.remoteOutboundRtps) {
1578
+ const observedRemoteOutboundRtp = this._updateRemoteOutboundRtpStats(remoteOutboundRtp);
1579
+ if (!observedRemoteOutboundRtp) continue;
1580
+ const observedInboundRtp = observedRemoteOutboundRtp.getInboundRtp();
1581
+ if (observedInboundRtp) {
1582
+ if (observedRemoteOutboundRtp.roundTripTime !== void 0) {
1583
+ observedInboundRtp.remoteRttInMs = observedRemoteOutboundRtp.roundTripTime * 1e3;
1584
+ }
1585
+ if (observedRemoteOutboundRtp.bytesSent !== void 0) {
1586
+ observedInboundRtp.remoteBytesSent = observedRemoteOutboundRtp.bytesSent;
1587
+ }
1588
+ if (observedRemoteOutboundRtp.packetsSent !== void 0) {
1589
+ observedInboundRtp.remotePacketsSent = observedRemoteOutboundRtp.packetsSent;
1590
+ }
1591
+ if (observedRemoteOutboundRtp.remoteTimestamp !== void 0) {
1592
+ observedInboundRtp.remoteTimestamp = observedRemoteOutboundRtp.remoteTimestamp;
1593
+ }
1594
+ }
1595
+ }
1596
+ }
1597
+ if (sample.inboundTracks) {
1598
+ for (const inboundTrack of sample.inboundTracks) {
1599
+ this._updateInboundTrackSample(inboundTrack);
1600
+ }
1601
+ }
1602
+ if (sample.outboundTracks) {
1603
+ for (const outboundTrack of sample.outboundTracks) {
1604
+ this._updateOutboundTrackSample(outboundTrack);
1605
+ }
1606
+ }
1607
+ this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
1608
+ this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
1609
+ this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
1610
+ this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
1611
+ this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
1612
+ this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
1613
+ this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
1614
+ this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
1615
+ this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
1616
+ this.totalSentAudioBytes += this.deltaSentAudioBytes;
1617
+ this.totalSentVideoBytes += this.deltaSentVideoBytes;
1618
+ this.totalReceivedAudioPacktes += this.deltaReceivedAudioPackets;
1619
+ this.totalReceivedVideoPackets += this.deltaReceivedVideoPackets;
1620
+ this.totalSentAudioPackets += this.deltaSentAudioPackets;
1621
+ this.totalSentVideoPackets += this.deltaSentVideoPackets;
1622
+ this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
1623
+ this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / elapsedTimeInSec;
1624
+ this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedTimeInSec;
1625
+ this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedTimeInSec;
1626
+ this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedTimeInSec;
1627
+ this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedTimeInSec;
1628
+ if (rttMeasurementsInSec.length > 0) {
1629
+ this.currentRttInMs = getMedian(rttMeasurementsInSec, false) * 1e3;
1630
+ } else {
1631
+ this.currentRttInMs = void 0;
1632
+ }
1633
+ if (jitterMeasurements.length > 0) {
1634
+ this.currentJitter = getMedian(jitterMeasurements, false);
1635
+ } else {
1636
+ this.currentJitter = void 0;
1637
+ }
1638
+ const wasUsingTURN = this.usingTURN;
1639
+ const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
1640
+ const selectedCandidatePairForTurn = [];
1641
+ this.usingTCP = false;
1642
+ this.usingTURN = false;
1643
+ for (const selectedCandidatePair of selectedIceCandidatePairs) {
1644
+ if (((_a = selectedCandidatePair.getLocalCandidate()) == null ? void 0 : _a.protocol) === "tcp") {
1645
+ this.usingTCP = true;
1646
+ }
1647
+ if (((_b = selectedCandidatePair.getLocalCandidate()) == null ? void 0 : _b.candidateType) === "relay" && ((_d = (_c = selectedCandidatePair.getRemoteCandidate()) == null ? void 0 : _c.url) == null ? void 0 : _d.startsWith("turn:"))) {
1648
+ selectedCandidatePairForTurn.push(selectedCandidatePair);
1649
+ this.usingTURN = true;
1650
+ }
1651
+ this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
1652
+ this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
1653
+ }
1654
+ if (this.usingTURN) {
1655
+ if (!this.observedTurnServer) {
1656
+ this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
1657
+ }
1658
+ (_e = this.observedTurnServer) == null ? void 0 : _e.updateTurnUsage(...selectedCandidatePairForTurn);
1659
+ } else if (wasUsingTURN) {
1660
+ if (!this.usingTURN) {
1661
+ this.client.call.observer.observedTURN.removePeerConnection(this);
1662
+ }
1663
+ }
1664
+ this.calculatedScore.value = sample.score;
1665
+ this.updated = now;
1666
+ this._checkVisited();
1667
+ this._notify("peer-connection-updated", { ...this.eventScope, context });
1668
+ }
1669
+ _checkVisited() {
1670
+ for (const certificate of [...this.observedCertificates.values()]) {
1671
+ if (certificate.visited) continue;
1672
+ this.observedCertificates.delete(certificate.id);
1673
+ }
1674
+ for (const observedCodec of [...this.observedCodecs.values()]) {
1675
+ if (observedCodec.visited) continue;
1676
+ this.observedCodecs.delete(observedCodec.id);
1677
+ this._notify("codec-removed", { ...this.eventScope, observedCodec });
1678
+ }
1679
+ for (const observedDataChannel of [...this.observedDataChannels.values()]) {
1680
+ if (observedDataChannel.visited) continue;
1681
+ this.observedDataChannels.delete(observedDataChannel.id);
1682
+ this._notify("data-channel-removed", { ...this.eventScope, observedDataChannel });
1683
+ }
1684
+ for (const observedIceCandidate of [...this.observedIceCandidates.values()]) {
1685
+ if (observedIceCandidate.visited) continue;
1686
+ this.observedIceCandidates.delete(observedIceCandidate.id);
1687
+ this._notify("ice-candidate-removed", { ...this.eventScope, observedIceCandidate });
1688
+ }
1689
+ for (const observedIceCandidatePair of [...this.observedIceCandidatesPair.values()]) {
1690
+ if (observedIceCandidatePair.visited) continue;
1691
+ this.observedIceCandidatesPair.delete(observedIceCandidatePair.id);
1692
+ this._notify("ice-candidate-pair-removed", { ...this.eventScope, observedIceCandidatePair });
1693
+ }
1694
+ for (const observedIceTransport of [...this.observedIceTransports.values()]) {
1695
+ if (observedIceTransport.visited) continue;
1696
+ this.observedIceTransports.delete(observedIceTransport.id);
1697
+ this._notify("ice-transport-removed", { ...this.eventScope, observedIceTransport });
1698
+ }
1699
+ for (const observedInboundRtp of [...this.observedInboundRtps.values()]) {
1700
+ if (observedInboundRtp.visited) continue;
1701
+ this.observedInboundRtps.delete(observedInboundRtp.ssrc);
1702
+ this._notify("inbound-rtp-removed", { ...this.eventScope, observedInboundRtp });
1703
+ }
1704
+ for (const observedInboundTrack of [...this.observedInboundTracks.values()]) {
1705
+ if (observedInboundTrack.visited) continue;
1706
+ this.observedInboundTracks.delete(observedInboundTrack.id);
1707
+ this.emit("removed-inbound-track", observedInboundTrack);
1708
+ this._notify("inbound-track-removed", { ...this.eventScope, observedInboundTrack });
1709
+ }
1710
+ for (const observedMediaPlayout of [...this.observedMediaPlayouts.values()]) {
1711
+ if (observedMediaPlayout.visited) continue;
1712
+ this.observedMediaPlayouts.delete(observedMediaPlayout.id);
1713
+ this._notify("media-playout-removed", { ...this.eventScope, observedMediaPlayout });
1714
+ }
1715
+ for (const observedMediaSource of [...this.observedMediaSources.values()]) {
1716
+ if (observedMediaSource.visited) continue;
1717
+ this.observedMediaSources.delete(observedMediaSource.id);
1718
+ this._notify("media-source-removed", { ...this.eventScope, observedMediaSource });
1719
+ }
1720
+ for (const observedOutboundRtp of [...this.observedOutboundRtps.values()]) {
1721
+ if (observedOutboundRtp.visited) continue;
1722
+ this.observedOutboundRtps.delete(observedOutboundRtp.ssrc);
1723
+ this._notify("outbound-rtp-removed", { ...this.eventScope, observedOutboundRtp });
1724
+ }
1725
+ for (const observedOutboundTrack of [...this.observedOutboundTracks.values()]) {
1726
+ if (observedOutboundTrack.visited) continue;
1727
+ this.observedOutboundTracks.delete(observedOutboundTrack.id);
1728
+ this.emit("removed-outbound-track", observedOutboundTrack);
1729
+ this._notify("outbound-track-removed", { ...this.eventScope, observedOutboundTrack });
1730
+ }
1731
+ for (const observedPeerConnectionTransport of [...this.observedPeerConnectionTransports.values()]) {
1732
+ if (observedPeerConnectionTransport.visited) continue;
1733
+ this.observedPeerConnectionTransports.delete(observedPeerConnectionTransport.id);
1734
+ this._notify("peer-connection-transport-removed", { ...this.eventScope, observedPeerConnectionTransport });
1735
+ }
1736
+ for (const observedRemoteInboundRtp of [...this.observedRemoteInboundRtps.values()]) {
1737
+ if (observedRemoteInboundRtp.visited) continue;
1738
+ this.observedRemoteInboundRtps.delete(observedRemoteInboundRtp.ssrc);
1739
+ this._notify("remote-inbound-rtp-removed", { ...this.eventScope, observedRemoteInboundRtp });
1740
+ }
1741
+ for (const observedRemoteOutboundRtp of [...this.observedRemoteOutboundRtps.values()]) {
1742
+ if (observedRemoteOutboundRtp.visited) continue;
1743
+ this.observedRemoteOutboundRtps.delete(observedRemoteOutboundRtp.ssrc);
1744
+ this._notify("remote-outbound-rtp-removed", { ...this.eventScope, observedRemoteOutboundRtp });
1745
+ }
1746
+ }
1747
+ _updateCertificateStats(stats) {
1748
+ let observedCertificate = this.observedCertificates.get(stats.id);
1749
+ if (!observedCertificate) {
1750
+ if (!stats.timestamp || !stats.id || !stats.fingerprint) {
1751
+ return logger.warn(
1752
+ `ObservedPeerConnection received an invalid CertificateStats (missing timestamp OR id OR fingerprint field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1753
+ stats
1754
+ );
1755
+ }
1756
+ observedCertificate = new ObservedCertificate(stats.timestamp, stats.id, this);
1757
+ observedCertificate.update(stats);
1758
+ this.observedCertificates.set(stats.id, observedCertificate);
1759
+ this._notify("certificate-added", { ...this.eventScope, observedCertificate });
1760
+ } else {
1761
+ observedCertificate.update(stats);
1762
+ this._notify("certificate-updated", { ...this.eventScope, observedCertificate });
1763
+ }
1764
+ return observedCertificate;
1765
+ }
1766
+ _updateCodecStats(stats) {
1767
+ let observedCodec = this.observedCodecs.get(stats.id);
1768
+ if (!observedCodec) {
1769
+ if (!stats.timestamp || !stats.id || !stats.mimeType) {
1770
+ return logger.warn(
1771
+ `ObservedPeerConnection received an invalid CodecStats (missing timestamp OR id OR mimeType field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1772
+ stats
1773
+ );
1774
+ }
1775
+ observedCodec = new ObservedCodec(stats.timestamp, stats.id, stats.mimeType, this);
1776
+ observedCodec.update(stats);
1777
+ this.observedCodecs.set(stats.id, observedCodec);
1778
+ this._notify("codec-added", { ...this.eventScope, observedCodec });
1779
+ } else {
1780
+ observedCodec.update(stats);
1781
+ }
1782
+ this._notify("codec-updated", { ...this.eventScope, observedCodec });
1783
+ return observedCodec;
1784
+ }
1785
+ _updateDataChannelStats(stats) {
1786
+ let observedDataChannel = this.observedDataChannels.get(stats.id);
1787
+ if (!observedDataChannel) {
1788
+ if (!stats.timestamp || !stats.id) {
1789
+ return logger.warn(
1790
+ `ObservedPeerConnection received an invalid DataChannelStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1791
+ stats
1792
+ );
1793
+ }
1794
+ observedDataChannel = new ObservedDataChannel(stats.timestamp, stats.id, this);
1795
+ observedDataChannel.update(stats);
1796
+ this.observedDataChannels.set(stats.id, observedDataChannel);
1797
+ this._notify("data-channel-added", { ...this.eventScope, observedDataChannel });
1798
+ } else {
1799
+ observedDataChannel.update(stats);
1800
+ }
1801
+ this._notify("data-channel-updated", { ...this.eventScope, observedDataChannel });
1802
+ return observedDataChannel;
1803
+ }
1804
+ _updateIceCandidateStats(stats) {
1805
+ let observedIceCandidate = this.observedIceCandidates.get(stats.id);
1806
+ if (!observedIceCandidate) {
1807
+ if (!stats.timestamp || !stats.id) {
1808
+ return logger.warn(
1809
+ `ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1810
+ stats
1811
+ );
1812
+ }
1813
+ observedIceCandidate = new ObservedIceCandidate(stats.timestamp, stats.id, this);
1814
+ observedIceCandidate.update(stats);
1815
+ this.observedIceCandidates.set(stats.id, observedIceCandidate);
1816
+ this._notify("ice-candidate-added", { ...this.eventScope, observedIceCandidate });
1817
+ } else {
1818
+ observedIceCandidate.update(stats);
1819
+ }
1820
+ this._notify("ice-candidate-updated", { ...this.eventScope, observedIceCandidate });
1821
+ return observedIceCandidate;
1822
+ }
1823
+ _updateIceCandidatePairStats(stats) {
1824
+ let observedIceCandidatePair = this.observedIceCandidatesPair.get(stats.id);
1825
+ if (!observedIceCandidatePair) {
1826
+ if (!stats.timestamp || !stats.id) {
1827
+ return logger.warn(
1828
+ `ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1829
+ stats
1830
+ );
1831
+ }
1832
+ observedIceCandidatePair = new ObservedIceCandidatePair(stats.timestamp, stats.id, this);
1833
+ observedIceCandidatePair.update(stats);
1834
+ this.observedIceCandidatesPair.set(stats.id, observedIceCandidatePair);
1835
+ this._notify("ice-candidate-pair-added", { ...this.eventScope, observedIceCandidatePair });
1836
+ } else {
1837
+ observedIceCandidatePair.update(stats);
1838
+ }
1839
+ this._notify("ice-candidate-pair-updated", { ...this.eventScope, observedIceCandidatePair });
1840
+ return observedIceCandidatePair;
1841
+ }
1842
+ _updateIceTransportStats(stats) {
1843
+ let observedIceTransport = this.observedIceTransports.get(stats.id);
1844
+ if (!observedIceTransport) {
1845
+ if (!stats.timestamp || !stats.id) {
1846
+ return logger.warn(
1847
+ `ObservedPeerConnection received an invalid IceCandidateStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1848
+ stats
1849
+ );
1850
+ }
1851
+ observedIceTransport = new ObservedIceTransport(stats.timestamp, stats.id, this);
1852
+ observedIceTransport.update(stats);
1853
+ this.observedIceTransports.set(stats.id, observedIceTransport);
1854
+ this._notify("ice-transport-added", { ...this.eventScope, observedIceTransport });
1855
+ } else {
1856
+ observedIceTransport.update(stats);
1857
+ }
1858
+ this._notify("ice-transport-updated", { ...this.eventScope, observedIceTransport });
1859
+ return observedIceTransport;
1860
+ }
1861
+ _updateInboundRtpStats(stats) {
1862
+ let observedInboundRtp = this.observedInboundRtps.get(stats.ssrc);
1863
+ if (!observedInboundRtp) {
1864
+ if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind || !stats.trackIdentifier) {
1865
+ return logger.warn(
1866
+ `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}`,
1867
+ stats
1868
+ );
1869
+ }
1870
+ observedInboundRtp = new ObservedInboundRtp(
1871
+ stats.timestamp,
1872
+ stats.id,
1873
+ stats.ssrc,
1874
+ stats.kind,
1875
+ stats.trackIdentifier,
1876
+ this
1877
+ );
1878
+ observedInboundRtp.update(stats);
1879
+ this.observedInboundRtps.set(stats.ssrc, observedInboundRtp);
1880
+ this._notify("inbound-rtp-added", { ...this.eventScope, observedInboundRtp });
1881
+ } else {
1882
+ observedInboundRtp.update(stats);
1883
+ }
1884
+ this._notify("inbound-rtp-updated", { ...this.eventScope, observedInboundRtp });
1885
+ return observedInboundRtp;
1886
+ }
1887
+ _updateInboundTrackSample(stats) {
1888
+ let observedInboundTrack = this.observedInboundTracks.get(stats.id);
1889
+ if (!observedInboundTrack) {
1890
+ if (!stats.timestamp || !stats.id || !stats.kind) {
1891
+ return logger.warn(
1892
+ `ObservedPeerConnection received an invalid InboundTrackSample (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1893
+ stats
1894
+ );
1895
+ }
1896
+ const inboundRtp = [...this.observedInboundRtps.values()].find((inbRtp) => inbRtp.trackIdentifier === stats.id);
1897
+ const mediaPlayout = inboundRtp ? [...this.observedMediaPlayouts.values()].find((mp) => mp.id === inboundRtp.playoutId) : void 0;
1898
+ observedInboundTrack = new ObservedInboundTrack(
1899
+ stats.timestamp,
1900
+ stats.id,
1901
+ stats.kind,
1902
+ this,
1903
+ inboundRtp,
1904
+ mediaPlayout
1905
+ );
1906
+ observedInboundTrack.update(stats);
1907
+ this.observedInboundTracks.set(stats.id, observedInboundTrack);
1908
+ this._notify("inbound-track-added", { ...this.eventScope, observedInboundTrack });
1909
+ } else {
1910
+ observedInboundTrack.update(stats);
1911
+ }
1912
+ this._notify("inbound-track-updated", { ...this.eventScope, observedInboundTrack });
1913
+ return observedInboundTrack;
1914
+ }
1915
+ _updateMediaPlayoutStats(stats) {
1916
+ let observedMediaPlayout = this.observedMediaPlayouts.get(stats.id);
1917
+ if (!observedMediaPlayout) {
1918
+ if (!stats.timestamp || !stats.id || !stats.kind) {
1919
+ return logger.warn(
1920
+ `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}`,
1921
+ stats
1922
+ );
1923
+ }
1924
+ observedMediaPlayout = new ObservedMediaPlayout(
1925
+ stats.timestamp,
1926
+ stats.id,
1927
+ stats.kind,
1928
+ this
1929
+ );
1930
+ observedMediaPlayout.update(stats);
1931
+ this.observedMediaPlayouts.set(stats.id, observedMediaPlayout);
1932
+ this._notify("media-playout-added", { ...this.eventScope, observedMediaPlayout });
1933
+ } else {
1934
+ observedMediaPlayout.update(stats);
1935
+ }
1936
+ this._notify("media-playout-updated", { ...this.eventScope, observedMediaPlayout });
1937
+ return observedMediaPlayout;
1938
+ }
1939
+ _updateMediaSourceStats(stats) {
1940
+ let observedMediaSource = this.observedMediaSources.get(stats.id);
1941
+ if (!observedMediaSource) {
1942
+ if (!stats.timestamp || !stats.id || !stats.kind) {
1943
+ return logger.warn(
1944
+ `ObservedPeerConnection received an invalid InboundRtpStats (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1945
+ stats
1946
+ );
1947
+ }
1948
+ observedMediaSource = new ObservedMediaSource(
1949
+ stats.timestamp,
1950
+ stats.id,
1951
+ stats.kind,
1952
+ this
1953
+ );
1954
+ observedMediaSource.update(stats);
1955
+ this.observedMediaSources.set(stats.id, observedMediaSource);
1956
+ this._notify("media-source-added", { ...this.eventScope, observedMediaSource });
1957
+ } else {
1958
+ observedMediaSource.update(stats);
1959
+ }
1960
+ this._notify("media-source-updated", { ...this.eventScope, observedMediaSource });
1961
+ return observedMediaSource;
1962
+ }
1963
+ _updateOutboundRtpStats(stats) {
1964
+ let observedOutboundRtp = this.observedOutboundRtps.get(stats.ssrc);
1965
+ if (!observedOutboundRtp) {
1966
+ if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
1967
+ return logger.warn(
1968
+ `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}`,
1969
+ stats
1970
+ );
1971
+ }
1972
+ observedOutboundRtp = new ObservedOutboundRtp(
1973
+ stats.timestamp,
1974
+ stats.id,
1975
+ stats.ssrc,
1976
+ stats.kind,
1977
+ this
1978
+ );
1979
+ observedOutboundRtp.update(stats);
1980
+ this.observedOutboundRtps.set(stats.ssrc, observedOutboundRtp);
1981
+ this._notify("outbound-rtp-added", { ...this.eventScope, observedOutboundRtp });
1982
+ } else {
1983
+ observedOutboundRtp.update(stats);
1984
+ }
1985
+ this._notify("outbound-rtp-updated", { ...this.eventScope, observedOutboundRtp });
1986
+ return observedOutboundRtp;
1987
+ }
1988
+ _updateOutboundTrackSample(stats) {
1989
+ let observedOutboundTrack = this.observedOutboundTracks.get(stats.id);
1990
+ if (!observedOutboundTrack) {
1991
+ if (!stats.timestamp || !stats.id || !stats.kind) {
1992
+ return logger.warn(
1993
+ `ObservedPeerConnection received an invalid OutboundTrackSample (missing timestamp OR id OR kind field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
1994
+ stats
1995
+ );
1996
+ }
1997
+ const observedMediaSource = [...this.observedMediaSources.values()].find((mediaSource) => mediaSource.trackIdentifier === stats.id);
1998
+ const outboundRtps = observedMediaSource ? [...this.observedOutboundRtps.values()].filter((outboundRtp) => outboundRtp.mediaSourceId === (observedMediaSource == null ? void 0 : observedMediaSource.id)) : void 0;
1999
+ observedOutboundTrack = new ObservedOutboundTrack(
2000
+ stats.timestamp,
2001
+ stats.id,
2002
+ stats.kind,
2003
+ this,
2004
+ outboundRtps,
2005
+ observedMediaSource
2006
+ );
2007
+ observedOutboundTrack.update(stats);
2008
+ this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
2009
+ this._notify("outbound-track-added", { ...this.eventScope, observedOutboundTrack });
2010
+ } else {
2011
+ observedOutboundTrack.update(stats);
2012
+ }
2013
+ this._notify("outbound-track-updated", { ...this.eventScope, observedOutboundTrack });
2014
+ return observedOutboundTrack;
2015
+ }
2016
+ _updatePeerConnectionTransportStats(stats) {
2017
+ let observedPeerConnectionTransport = this.observedPeerConnectionTransports.get(stats.id);
2018
+ if (!observedPeerConnectionTransport) {
2019
+ if (!stats.timestamp || !stats.id) {
2020
+ return logger.warn(
2021
+ `ObservedPeerConnection received an invalid PeerConnectionTransportStats (missing timestamp OR id field). PeerConnectionId: ${this.peerConnectionId} ClientId: ${this.client.clientId}, CallId: ${this.client.call.callId}`,
2022
+ stats
2023
+ );
2024
+ }
2025
+ observedPeerConnectionTransport = new ObservedPeerConnectionTransport(stats.timestamp, stats.id, this);
2026
+ observedPeerConnectionTransport.update(stats);
2027
+ this.observedPeerConnectionTransports.set(stats.id, observedPeerConnectionTransport);
2028
+ this._notify("peer-connection-transport-added", { ...this.eventScope, observedPeerConnectionTransport });
2029
+ } else {
2030
+ observedPeerConnectionTransport.update(stats);
2031
+ }
2032
+ this._notify("peer-connection-transport-updated", { ...this.eventScope, observedPeerConnectionTransport });
2033
+ return observedPeerConnectionTransport;
2034
+ }
2035
+ _updateRemoteInboundRtpStats(stats) {
2036
+ let observedRemoteInboundRtp = this.observedRemoteInboundRtps.get(stats.ssrc);
2037
+ if (!observedRemoteInboundRtp) {
2038
+ if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
2039
+ return logger.warn(
2040
+ `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}`,
2041
+ stats
2042
+ );
2043
+ }
2044
+ observedRemoteInboundRtp = new ObservedRemoteInboundRtp(
2045
+ stats.timestamp,
2046
+ stats.id,
2047
+ stats.ssrc,
2048
+ stats.kind,
2049
+ this
2050
+ );
2051
+ observedRemoteInboundRtp.update(stats);
2052
+ this.observedRemoteInboundRtps.set(stats.ssrc, observedRemoteInboundRtp);
2053
+ this._notify("remote-inbound-rtp-added", { ...this.eventScope, observedRemoteInboundRtp });
2054
+ } else {
2055
+ observedRemoteInboundRtp.update(stats);
2056
+ }
2057
+ this._notify("remote-inbound-rtp-updated", { ...this.eventScope, observedRemoteInboundRtp });
2058
+ return observedRemoteInboundRtp;
2059
+ }
2060
+ _updateRemoteOutboundRtpStats(stats) {
2061
+ let observedRemoteOutboundRtp = this.observedRemoteOutboundRtps.get(stats.ssrc);
2062
+ if (!observedRemoteOutboundRtp) {
2063
+ if (!stats.timestamp || !stats.id || !stats.ssrc || !stats.kind) {
2064
+ return logger.warn(
2065
+ `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}`,
2066
+ stats
2067
+ );
2068
+ }
2069
+ observedRemoteOutboundRtp = new ObservedRemoteOutboundRtp(
2070
+ stats.timestamp,
2071
+ stats.id,
2072
+ stats.ssrc,
2073
+ stats.kind,
2074
+ this
2075
+ );
2076
+ observedRemoteOutboundRtp.update(stats);
2077
+ this.observedRemoteOutboundRtps.set(stats.ssrc, observedRemoteOutboundRtp);
2078
+ this._notify("remote-outbound-rtp-added", { ...this.eventScope, observedRemoteOutboundRtp });
2079
+ } else {
2080
+ observedRemoteOutboundRtp.update(stats);
2081
+ }
2082
+ this._notify("remote-outbound-rtp-updated", { ...this.eventScope, observedRemoteOutboundRtp });
2083
+ return observedRemoteOutboundRtp;
2084
+ }
2085
+ /** Emit an Observer-bus event scoped to this peer connection. */
2086
+ _notify(type, ...args) {
2087
+ this.client.call.observer.emit(type, ...args);
2088
+ }
2089
+ };
2090
+
2091
+ // src/schema/ClientEventTypes.ts
2092
+ var ClientEventTypes = /* @__PURE__ */ ((ClientEventTypes2) => {
2093
+ ClientEventTypes2["CLIENT_JOINED"] = "CLIENT_JOINED";
2094
+ ClientEventTypes2["CLIENT_LEFT"] = "CLIENT_LEFT";
2095
+ ClientEventTypes2["PEER_CONNECTION_OPENED"] = "PEER_CONNECTION_OPENED";
2096
+ ClientEventTypes2["PEER_CONNECTION_CLOSED"] = "PEER_CONNECTION_CLOSED";
2097
+ ClientEventTypes2["MEDIA_TRACK_ADDED"] = "MEDIA_TRACK_ADDED";
2098
+ ClientEventTypes2["MEDIA_TRACK_REMOVED"] = "MEDIA_TRACK_REMOVED";
2099
+ ClientEventTypes2["MEDIA_TRACK_RESUMED"] = "MEDIA_TRACK_RESUMED";
2100
+ ClientEventTypes2["MEDIA_TRACK_MUTED"] = "MEDIA_TRACK_MUTED";
2101
+ ClientEventTypes2["MEDIA_TRACK_UNMUTED"] = "MEDIA_TRACK_UNMUTED";
2102
+ ClientEventTypes2["ICE_GATHERING_STATE_CHANGED"] = "ICE_GATHERING_STATE_CHANGED";
2103
+ ClientEventTypes2["PEER_CONNECTION_STATE_CHANGED"] = "PEER_CONNECTION_STATE_CHANGED";
2104
+ ClientEventTypes2["ICE_CONNECTION_STATE_CHANGED"] = "ICE_CONNECTION_STATE_CHANGED";
2105
+ ClientEventTypes2["DATA_CHANNEL_OPEN"] = "DATA_CHANNEL_OPEN";
2106
+ ClientEventTypes2["DATA_CHANNEL_CLOSED"] = "DATA_CHANNEL_CLOSED";
2107
+ ClientEventTypes2["DATA_CHANNEL_ERROR"] = "DATA_CHANNEL_ERROR";
2108
+ ClientEventTypes2["NEGOTIATION_NEEDED"] = "NEGOTIATION_NEEDED";
2109
+ ClientEventTypes2["SIGNALING_STATE_CHANGE"] = "SIGNALING_STATE_CHANGE";
2110
+ ClientEventTypes2["ICE_CANDIDATE"] = "ICE_CANDIDATE";
2111
+ ClientEventTypes2["ICE_CANDIDATE_ERROR"] = "ICE_CANDIDATE_ERROR";
2112
+ ClientEventTypes2["PRODUCER_ADDED"] = "PRODUCER_ADDED";
2113
+ ClientEventTypes2["PRODUCER_REMOVED"] = "PRODUCER_REMOVED";
2114
+ ClientEventTypes2["PRODUCER_PAUSED"] = "PRODUCER_PAUSED";
2115
+ ClientEventTypes2["PRODUCER_RESUMED"] = "PRODUCER_RESUMED";
2116
+ ClientEventTypes2["CONSUMER_ADDED"] = "CONSUMER_ADDED";
2117
+ ClientEventTypes2["CONSUMER_REMOVED"] = "CONSUMER_REMOVED";
2118
+ ClientEventTypes2["CONSUMER_PAUSED"] = "CONSUMER_PAUSED";
2119
+ ClientEventTypes2["CONSUMER_RESUMED"] = "CONSUMER_RESUMED";
2120
+ ClientEventTypes2["DATA_PRODUCER_CREATED"] = "DATA_PRODUCER_CREATED";
2121
+ ClientEventTypes2["DATA_PRODUCER_CLOSED"] = "DATA_PRODUCER_CLOSED";
2122
+ ClientEventTypes2["DATA_CONSUMER_CREATED"] = "DATA_CONSUMER_CREATED";
2123
+ ClientEventTypes2["DATA_CONSUMER_CLOSED"] = "DATA_CONSUMER_CLOSED";
2124
+ return ClientEventTypes2;
2125
+ })(ClientEventTypes || {});
2126
+
2127
+ // src/schema/ClientMetaTypes.ts
2128
+ var ClientMetaTypes = /* @__PURE__ */ ((ClientMetaTypes2) => {
2129
+ ClientMetaTypes2["MEDIA_CONSTRAINT"] = "MEDIA_CONSTRAINT";
2130
+ ClientMetaTypes2["MEDIA_DEVICE"] = "MEDIA_DEVICE";
2131
+ ClientMetaTypes2["MEDIA_DEVICES_SUPPORTED_CONSTRAINTS"] = "MEDIA_DEVICES_SUPPORTED_CONSTRAINTS";
2132
+ ClientMetaTypes2["USER_MEDIA_ERROR"] = "USER_MEDIA_ERROR";
2133
+ ClientMetaTypes2["LOCAL_SDP"] = "LOCAL_SDP";
2134
+ ClientMetaTypes2["OPERATION_SYSTEM"] = "OPERATION_SYSTEM";
2135
+ ClientMetaTypes2["ENGINE"] = "ENGINE";
2136
+ ClientMetaTypes2["PLATFORM"] = "PLATFORM";
2137
+ ClientMetaTypes2["BROWSER"] = "BROWSER";
2138
+ return ClientMetaTypes2;
2139
+ })(ClientMetaTypes || {});
2140
+
2141
+ // src/ObservedClient.ts
2142
+ var logger2 = createLogger("ObservedClient");
2143
+ var ObservedClient = class extends EventEmitter2 {
2144
+ constructor(settings, call) {
2145
+ var _a, _b;
2146
+ super();
2147
+ this.call = call;
2148
+ this.setMaxListeners(Infinity);
2149
+ this.eventScope = { observer: call.observer, observedCall: call, observedClient: this };
2150
+ this.sink = (_b = (_a = call.observer.config).createClientSink) == null ? void 0 : _b.call(_a, { clientId: settings.clientId, observedCall: call });
2151
+ this.clientId = settings.clientId;
2152
+ this.appData = settings.appData ?? {};
2153
+ this.settings = {
2154
+ closeClientIfIdleForMs: settings.closeClientIfIdleForMs
2155
+ };
2156
+ this.report = {
2157
+ callId: this.call.callId,
2158
+ clientId: this.clientId,
2159
+ rttDistribution: {
2160
+ gtOrEq300ms: 0,
2161
+ lt50ms: 0,
2162
+ lt150ms: 0,
2163
+ lt300ms: 0,
2164
+ count: 0,
2165
+ sum: 0
2166
+ },
2167
+ scoreDistribution: {
2168
+ "0": 0,
2169
+ "1": 0,
2170
+ "2": 0,
2171
+ "3": 0,
2172
+ "4": 0,
2173
+ "5": 0,
2174
+ count: 0,
2175
+ sum: 0
2176
+ },
2177
+ issues: {},
2178
+ totalAudioBytesReceived: 0,
2179
+ totalVideoBytesReceived: 0,
2180
+ totalAudioBytesSent: 0,
2181
+ totalVideoBytesSent: 0,
2182
+ totalDataChannelBytesReceived: 0,
2183
+ totalDataChannelBytesSent: 0,
2184
+ totalDataChannelMessagesReceived: 0,
2185
+ totalDataChannelMessagesSent: 0,
2186
+ totalInboundRtpBytesReceived: 0,
2187
+ totalInboundRtpPacketsLost: 0,
2188
+ totalInboundRtpPacketsReceived: 0,
2189
+ totalOutboundRtpBytesSent: 0,
2190
+ totalOutboundRtpPacketsSent: 0,
2191
+ totalNumberOfIssues: 0
2192
+ };
2193
+ if (this.sink) {
2194
+ const onError = (err) => logger2.warn("ClientSampleSink error for client %s: %o", this.clientId, err);
2195
+ this.sink.once("close", () => {
2196
+ var _a2;
2197
+ return (_a2 = this.sink) == null ? void 0 : _a2.off("error", onError);
2198
+ });
2199
+ this.sink.on("error", onError);
2200
+ }
2201
+ }
2202
+ call;
2203
+ clientId;
2204
+ observedPeerConnections = /* @__PURE__ */ new Map();
2205
+ /** Per-client sink (from `ObserverConfig.createClientSink`), if any. */
2206
+ sink;
2207
+ /** Ancestry base shared by all Observer-bus events originating at this client. */
2208
+ eventScope;
2209
+ calculatedScore = {
2210
+ weight: 1,
2211
+ value: void 0
2212
+ };
2213
+ settings;
2214
+ appData;
2215
+ attachments;
2216
+ updated = Date.now();
2217
+ acceptedSamples = 0;
2218
+ closed = false;
2219
+ joinedAt;
2220
+ leftAt;
2221
+ closedAt;
2222
+ lastSampleTimestamp;
2223
+ // the timestamp of the CLIENT_JOINED event
2224
+ operationSystem;
2225
+ engine;
2226
+ platform;
2227
+ browser;
2228
+ mediaConstraints = [];
2229
+ usingTURN = false;
2230
+ usingTCP = false;
2231
+ availableOutgoingBitrate = 0;
2232
+ availableIncomingBitrate = 0;
2233
+ deltaReceivedAudioBytes = 0;
2234
+ deltaReceivedVideoBytes = 0;
2235
+ deltaSentAudioBytes = 0;
2236
+ deltaSentVideoBytes = 0;
2237
+ deltaDataChannelBytesSent = 0;
2238
+ deltaDataChannelBytesReceived = 0;
2239
+ deltaDataChannelMessagesSent = 0;
2240
+ deltaDataChannelMessagesReceived = 0;
2241
+ deltaInboundPacketsLost = 0;
2242
+ deltaInboundPacketsReceived = 0;
2243
+ deltaOutboundPacketsSent = 0;
2244
+ deltaTransportSentBytes = 0;
2245
+ deltaTransportReceivedBytes = 0;
2246
+ deltaRttLt50Measurements = 0;
2247
+ deltaRttLt150Measurements = 0;
2248
+ deltaRttLt300Measurements = 0;
2249
+ deltaRttGtOrEq300Measurements = 0;
2250
+ currentMaxRttInMs;
2251
+ currentMinRttInMs;
2252
+ currentAvgRttInMs;
2253
+ sendingAudioBitrate = 0;
2254
+ sendingVideoBitrate = 0;
2255
+ receivingAudioBitrate = 0;
2256
+ receivingVideoBitrate = 0;
2257
+ numberOfInboundRtpStreams = 0;
2258
+ numberOfInbundTracks = 0;
2259
+ numberOfOutboundRtpStreams = 0;
2260
+ numberOfOutboundTracks = 0;
2261
+ numberOfDataChannels = 0;
2262
+ deltaNumberOfIssues = 0;
2263
+ totalScoreSum = 0;
2264
+ numberOfScoreMeasurements = 0;
2265
+ // public totalNumberOfIssues = 0;
2266
+ report;
2267
+ mediaDevices = [];
2268
+ issues = [];
2269
+ _injections = {};
2270
+ closeTimer;
2271
+ get numberOfPeerConnections() {
2272
+ return this.observedPeerConnections.size;
2273
+ }
2274
+ get score() {
2275
+ return this.calculatedScore.value;
2276
+ }
2277
+ close() {
2278
+ var _a, _b, _c, _d, _e;
2279
+ if (this.closed) return;
2280
+ this.closed = true;
2281
+ (_a = this._injections.clientEvents) == null ? void 0 : _a.forEach((clientEvent) => this._processClientEvent(clientEvent));
2282
+ (_b = this._injections.clientIssues) == null ? void 0 : _b.forEach((clientIssue) => this.addIssue(clientIssue));
2283
+ (_c = this._injections.extensionStats) == null ? void 0 : _c.forEach((extensionStat) => this.addExtensionStats(extensionStat));
2284
+ (_d = this._injections.clientMetaItems) == null ? void 0 : _d.forEach((clientMetaItem) => this.addMetadata(clientMetaItem));
2285
+ Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
2286
+ if (!this.leftAt) {
2287
+ this.leftAt = this.lastSampleTimestamp;
2288
+ if (this.leftAt) {
2289
+ this.emit("left");
2290
+ this._notify("client-left", { ...this.eventScope });
2291
+ }
2292
+ }
2293
+ this.closedAt = Date.now();
2294
+ this.emit("close");
2295
+ this._notify("client-closed", { ...this.eventScope });
2296
+ try {
2297
+ (_e = this.sink) == null ? void 0 : _e.end();
2298
+ } catch (err) {
2299
+ logger2.warn("ClientSampleSink.end failed for client %s: %o", this.clientId, err);
2300
+ }
2301
+ }
2302
+ accept(sample, context) {
2303
+ var _a;
2304
+ if (this.closed) {
2305
+ logger2.warn("Attempted to accept a sample on a closed client %s", this.clientId);
2306
+ return;
2307
+ }
2308
+ (_a = this.sink) == null ? void 0 : _a.write(sample);
2309
+ if (this.closeTimer) {
2310
+ clearTimeout(this.closeTimer);
2311
+ this.closeTimer = void 0;
2312
+ }
2313
+ const now = Date.now();
2314
+ const elapsedInMs = now - this.updated;
2315
+ const elapsedInSeconds = elapsedInMs / 1e3;
2316
+ let sumOfRtts = 0;
2317
+ let numberOfRttMeasurements = 0;
2318
+ ++this.acceptedSamples;
2319
+ this.availableIncomingBitrate = 0;
2320
+ this.availableOutgoingBitrate = 0;
2321
+ this.deltaDataChannelBytesReceived = 0;
2322
+ this.deltaDataChannelBytesSent = 0;
2323
+ this.deltaDataChannelMessagesReceived = 0;
2324
+ this.deltaDataChannelMessagesSent = 0;
2325
+ this.deltaInboundPacketsLost = 0;
2326
+ this.deltaInboundPacketsReceived = 0;
2327
+ this.deltaOutboundPacketsSent = 0;
2328
+ this.deltaReceivedAudioBytes = 0;
2329
+ this.deltaReceivedVideoBytes = 0;
2330
+ this.deltaSentAudioBytes = 0;
2331
+ this.deltaSentVideoBytes = 0;
2332
+ this.deltaTransportReceivedBytes = 0;
2333
+ this.deltaTransportSentBytes = 0;
2334
+ this.deltaRttLt50Measurements = 0;
2335
+ this.deltaRttLt150Measurements = 0;
2336
+ this.deltaRttLt300Measurements = 0;
2337
+ this.deltaRttGtOrEq300Measurements = 0;
2338
+ this.deltaNumberOfIssues = 0;
2339
+ this.numberOfDataChannels = 0;
2340
+ this.numberOfInboundRtpStreams = 0;
2341
+ this.numberOfInbundTracks = 0;
2342
+ this.numberOfOutboundRtpStreams = 0;
2343
+ this.numberOfOutboundTracks = 0;
2344
+ this.usingTURN = false;
2345
+ this.usingTCP = false;
2346
+ this.currentMinRttInMs = void 0;
2347
+ this.currentMaxRttInMs = void 0;
2348
+ this._mergeInjections(sample);
2349
+ const clientEventsPostBuffer = [];
2350
+ for (const clientEvent of sample.clientEvents ?? []) {
2351
+ this._processClientEvent(clientEvent, clientEventsPostBuffer);
2352
+ }
2353
+ for (const metaData of sample.clientMetaItems ?? []) {
2354
+ this.addMetadata(metaData);
2355
+ }
2356
+ for (const issue of sample.clientIssues ?? []) {
2357
+ this.addIssue(issue);
2358
+ ++this.deltaNumberOfIssues;
2359
+ }
2360
+ for (const extensionStat of sample.extensionStats ?? []) {
2361
+ this.addExtensionStats(extensionStat);
2362
+ }
2363
+ for (const pcSample of sample.peerConnections ?? []) {
2364
+ const observedPeerConnection = this._updatePeerConnection(pcSample, context);
2365
+ if (!observedPeerConnection) continue;
2366
+ this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
2367
+ this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
2368
+ this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
2369
+ this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
2370
+ this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
2371
+ this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
2372
+ this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
2373
+ this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
2374
+ this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
2375
+ this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
2376
+ this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
2377
+ this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
2378
+ this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
2379
+ this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
2380
+ this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
2381
+ this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
2382
+ this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
2383
+ this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
2384
+ this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
2385
+ this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
2386
+ if (observedPeerConnection.usingTURN) {
2387
+ this.usingTURN = true;
2388
+ }
2389
+ if (observedPeerConnection.usingTCP) {
2390
+ this.usingTCP = true;
2391
+ }
2392
+ if (observedPeerConnection.currentRttInMs) {
2393
+ if (this.currentMinRttInMs === void 0 || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
2394
+ this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
2395
+ }
2396
+ if (this.currentMaxRttInMs === void 0 || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
2397
+ this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
2398
+ }
2399
+ if (observedPeerConnection.currentRttInMs < 50) {
2400
+ this.deltaRttLt50Measurements += 1;
2401
+ this.report.rttDistribution.lt50ms += 1;
2402
+ } else if (observedPeerConnection.currentRttInMs < 150) {
2403
+ this.deltaRttLt150Measurements += 1;
2404
+ this.report.rttDistribution.lt150ms += 1;
2405
+ } else if (observedPeerConnection.currentRttInMs < 300) {
2406
+ this.deltaRttLt300Measurements += 1;
2407
+ this.report.rttDistribution.lt300ms += 1;
2408
+ } else if (300 <= observedPeerConnection.currentRttInMs) {
2409
+ this.deltaRttGtOrEq300Measurements += 1;
2410
+ this.report.rttDistribution.gtOrEq300ms += 1;
2411
+ }
2412
+ this.report.rttDistribution.count += 1;
2413
+ this.report.rttDistribution.sum += observedPeerConnection.currentRttInMs;
2414
+ sumOfRtts += observedPeerConnection.currentRttInMs;
2415
+ ++numberOfRttMeasurements;
2416
+ }
2417
+ }
2418
+ for (const clientEvent of clientEventsPostBuffer) {
2419
+ this._processClientEvent(clientEvent);
2420
+ }
2421
+ this.attachments = sample.attachments;
2422
+ this.report.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
2423
+ this.report.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
2424
+ this.report.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
2425
+ this.report.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
2426
+ this.report.totalInboundRtpPacketsLost += this.deltaInboundPacketsLost;
2427
+ this.report.totalInboundRtpPacketsReceived += this.deltaInboundPacketsReceived;
2428
+ this.report.totalOutboundRtpPacketsSent += this.deltaOutboundPacketsSent;
2429
+ this.report.totalAudioBytesReceived += this.deltaReceivedAudioBytes;
2430
+ this.report.totalVideoBytesReceived += this.deltaReceivedVideoBytes;
2431
+ this.report.totalAudioBytesSent += this.deltaSentAudioBytes;
2432
+ this.report.totalVideoBytesSent += this.deltaSentVideoBytes;
2433
+ this.report.totalInboundRtpBytesReceived += this.deltaTransportReceivedBytes;
2434
+ this.report.totalOutboundRtpBytesSent += this.deltaTransportSentBytes;
2435
+ this.report.totalNumberOfIssues += this.deltaNumberOfIssues;
2436
+ this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedInSeconds;
2437
+ this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedInSeconds;
2438
+ this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedInSeconds;
2439
+ this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedInSeconds;
2440
+ this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : void 0;
2441
+ this.calculatedScore.value = sample.score;
2442
+ if (sample.score !== void 0) {
2443
+ const bucket = Math.floor(sample.score).toString();
2444
+ this.report.scoreDistribution[bucket] = (this.report.scoreDistribution[bucket] ?? 0) + 1;
2445
+ this.report.scoreDistribution.count += 1;
2446
+ this.report.scoreDistribution.sum += sample.score;
2447
+ }
2448
+ this.lastSampleTimestamp = sample.timestamp;
2449
+ const elapsedTimeInMs = now - this.updated;
2450
+ this.emit("update", sample, elapsedTimeInMs, context);
2451
+ this._notify("client-updated", { ...this.eventScope, sample, elapsedTimeInMs, context });
2452
+ this.updated = now;
2453
+ if (this.calculatedScore.value) {
2454
+ this.totalScoreSum += this.calculatedScore.value;
2455
+ ++this.numberOfScoreMeasurements;
2456
+ }
2457
+ if (this.settings.closeClientIfIdleForMs !== void 0) {
2458
+ this.closeTimer = setTimeout(() => {
2459
+ this.close();
2460
+ }, this.settings.closeClientIfIdleForMs);
2461
+ }
2462
+ }
2463
+ injectMetaData(metaData) {
2464
+ if (this.closed) return;
2465
+ if (!this._injections.clientMetaItems) this._injections.clientMetaItems = [];
2466
+ this._injections.clientMetaItems.push(metaData);
2467
+ }
2468
+ injectEvent(event) {
2469
+ if (this.closed) return;
2470
+ if (!this._injections.clientEvents) this._injections.clientEvents = [];
2471
+ this._injections.clientEvents.push(event);
2472
+ }
2473
+ injectIssue(issue) {
2474
+ if (this.closed) return;
2475
+ if (!this._injections.clientIssues) this._injections.clientIssues = [];
2476
+ this._injections.clientIssues.push(issue);
2477
+ }
2478
+ injectExtensionStat(stat) {
2479
+ if (this.closed) return;
2480
+ if (!this._injections.extensionStats) this._injections.extensionStats = [];
2481
+ this._injections.extensionStats.push(stat);
2482
+ }
2483
+ injectAttachment(key, value) {
2484
+ if (this.closed) return;
2485
+ if (!this._injections.attachments) this._injections.attachments = {};
2486
+ this._injections.attachments[key] = value;
2487
+ }
2488
+ addMetadata(metadata) {
2489
+ if (this.closed) return;
2490
+ switch (metadata.type) {
2491
+ case "BROWSER" /* BROWSER */: {
2492
+ this.browser = parseJsonAs(metadata.payload);
2493
+ break;
2494
+ }
2495
+ case "ENGINE" /* ENGINE */: {
2496
+ this.engine = parseJsonAs(metadata.payload);
2497
+ break;
2498
+ }
2499
+ case "PLATFORM" /* PLATFORM */: {
2500
+ this.platform = parseJsonAs(metadata.payload);
2501
+ break;
2502
+ }
2503
+ case "OPERATION_SYSTEM" /* OPERATION_SYSTEM */: {
2504
+ this.operationSystem = parseJsonAs(metadata.payload);
2505
+ break;
2506
+ }
2507
+ }
2508
+ this._notify("client-metadata", { ...this.eventScope, metaData: metadata });
2509
+ }
2510
+ addIssue(issue) {
2511
+ if (this.closed) return;
2512
+ this.report.issues[issue.type] = (this.report.issues[issue.type] ?? 0) + 1;
2513
+ this._notify("client-issue", { ...this.eventScope, issue });
2514
+ }
2515
+ addExtensionStats(stats) {
2516
+ this._notify("client-extension-stats", { ...this.eventScope, extensionStats: stats });
2517
+ }
2518
+ _processClientEvent(event, postBuffer) {
2519
+ switch (event.type) {
2520
+ case "CLIENT_JOINED" /* CLIENT_JOINED */: {
2521
+ if (event.timestamp) {
2522
+ if (!this.joinedAt) {
2523
+ this.joinedAt = event.timestamp;
2524
+ this.emit("joined");
2525
+ this._notify("client-joined", { ...this.eventScope });
2526
+ } else if (this.joinedAt < event.timestamp) {
2527
+ this._notify("client-rejoined", { ...this.eventScope, timestamp: event.timestamp });
2528
+ } else {
2529
+ this.joinedAt = event.timestamp;
2530
+ logger2.warn(`Client ${this.clientId} joinedAt timestamp was updated to ${event.timestamp}. the joined event will not be emitted.`);
2531
+ }
2532
+ }
2533
+ logger2.debug("Client %s joined at %o", this.clientId, event);
2534
+ break;
2535
+ }
2536
+ case "CLIENT_LEFT" /* CLIENT_LEFT */: {
2537
+ if (event.timestamp) {
2538
+ if (!this.leftAt) {
2539
+ this.leftAt = event.timestamp;
2540
+ this.emit("left");
2541
+ this._notify("client-left", { ...this.eventScope });
2542
+ } else {
2543
+ logger2.warn(`Client ${this.clientId} leftAt timestamp was already set`);
2544
+ }
2545
+ }
2546
+ logger2.debug("Client %s left at %o", this.clientId, event);
2547
+ break;
2548
+ }
2549
+ case "PEER_CONNECTION_OPENED" /* PEER_CONNECTION_OPENED */: {
2550
+ const payload = parseJsonAs(event.payload);
2551
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string") {
2552
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2553
+ if (observedPeerConnection) {
2554
+ observedPeerConnection.openedAt = event.timestamp;
2555
+ } else if (postBuffer) {
2556
+ postBuffer.push(event);
2557
+ } else {
2558
+ logger2.warn("Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection: %o", event);
2559
+ }
2560
+ }
2561
+ break;
2562
+ }
2563
+ case "PEER_CONNECTION_CLOSED" /* PEER_CONNECTION_CLOSED */: {
2564
+ const payload = parseJsonAs(event.payload);
2565
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string") {
2566
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2567
+ if (observedPeerConnection) {
2568
+ observedPeerConnection.closedAt = event.timestamp;
2569
+ } else if (postBuffer) {
2570
+ postBuffer.push(event);
2571
+ } else {
2572
+ logger2.warn("Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection: %o", event);
2573
+ }
2574
+ }
2575
+ break;
2576
+ }
2577
+ case "MEDIA_TRACK_ADDED" /* MEDIA_TRACK_ADDED */: {
2578
+ const payload = parseJsonAs(event.payload);
2579
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.trackId) && typeof payload.trackId === "string") {
2580
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2581
+ const observedTrack = (observedPeerConnection == null ? void 0 : observedPeerConnection.observedInboundTracks.get(payload.trackId)) ?? (observedPeerConnection == null ? void 0 : observedPeerConnection.observedOutboundTracks.get(payload.trackId));
2582
+ if (observedTrack) {
2583
+ observedTrack.addedAt = event.timestamp;
2584
+ } else if (postBuffer) {
2585
+ postBuffer.push(event);
2586
+ } else {
2587
+ logger2.warn("Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack: %o", event);
2588
+ }
2589
+ }
2590
+ break;
2591
+ }
2592
+ case "MEDIA_TRACK_REMOVED" /* MEDIA_TRACK_REMOVED */: {
2593
+ const payload = parseJsonAs(event.payload);
2594
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.trackId) && typeof payload.trackId === "string") {
2595
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2596
+ const observedTrack = (observedPeerConnection == null ? void 0 : observedPeerConnection.observedInboundTracks.get(payload.trackId)) ?? (observedPeerConnection == null ? void 0 : observedPeerConnection.observedOutboundTracks.get(payload.trackId));
2597
+ if (observedTrack) {
2598
+ observedTrack.removedAt = event.timestamp;
2599
+ } else if (postBuffer) {
2600
+ postBuffer.push(event);
2601
+ } else {
2602
+ logger2.warn("Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack: %o", event);
2603
+ }
2604
+ }
2605
+ break;
2606
+ }
2607
+ case "DATA_CHANNEL_OPEN" /* DATA_CHANNEL_OPEN */: {
2608
+ const payload = parseJsonAs(event.payload);
2609
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.dataChannelId) && typeof payload.dataChannelId === "string") {
2610
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2611
+ const observedDataChannel = observedPeerConnection == null ? void 0 : observedPeerConnection.observedDataChannels.get(payload.dataChannelId);
2612
+ if (observedDataChannel) {
2613
+ observedDataChannel.addedAt = event.timestamp;
2614
+ } else if (postBuffer) {
2615
+ postBuffer.push(event);
2616
+ } else {
2617
+ logger2.warn("Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel: %o", event);
2618
+ }
2619
+ }
2620
+ break;
2621
+ }
2622
+ case "DATA_CHANNEL_CLOSED" /* DATA_CHANNEL_CLOSED */: {
2623
+ const payload = parseJsonAs(event.payload);
2624
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.dataChannelId) && typeof payload.dataChannelId === "string") {
2625
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2626
+ const observedDataChannel = observedPeerConnection == null ? void 0 : observedPeerConnection.observedDataChannels.get(payload.dataChannelId);
2627
+ if (observedDataChannel) {
2628
+ observedDataChannel.removedAt = event.timestamp;
2629
+ } else if (postBuffer) {
2630
+ postBuffer.push(event);
2631
+ } else {
2632
+ logger2.warn("Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel: %o", event);
2633
+ }
2634
+ }
2635
+ break;
2636
+ }
2637
+ case "MEDIA_TRACK_MUTED" /* MEDIA_TRACK_MUTED */: {
2638
+ const payload = parseJsonAs(event.payload);
2639
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.trackId) && typeof payload.trackId === "string") {
2640
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2641
+ const observedInboundTrack = observedPeerConnection == null ? void 0 : observedPeerConnection.observedInboundTracks.get(payload.trackId);
2642
+ const observedOutboundTrack = observedPeerConnection == null ? void 0 : observedPeerConnection.observedOutboundTracks.get(payload.trackId);
2643
+ if (observedPeerConnection) {
2644
+ if (observedInboundTrack) {
2645
+ observedInboundTrack.muted = true;
2646
+ this._notify("inbound-track-muted", { ...this.eventScope, observedPeerConnection, observedInboundTrack });
2647
+ } else if (observedOutboundTrack) {
2648
+ observedOutboundTrack.muted = true;
2649
+ this._notify("outbound-track-muted", { ...this.eventScope, observedPeerConnection, observedOutboundTrack });
2650
+ }
2651
+ } else if (postBuffer) {
2652
+ postBuffer.push(event);
2653
+ } else {
2654
+ logger2.warn("Received MEDIA_TRACK_MUTED event without a corresponding observedPeerConnection or observedTrack: %o", event);
2655
+ }
2656
+ }
2657
+ break;
2658
+ }
2659
+ case "MEDIA_TRACK_UNMUTED" /* MEDIA_TRACK_UNMUTED */: {
2660
+ const payload = parseJsonAs(event.payload);
2661
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.trackId) && typeof payload.trackId === "string") {
2662
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2663
+ const observedInboundTrack = observedPeerConnection == null ? void 0 : observedPeerConnection.observedInboundTracks.get(payload.trackId);
2664
+ const observedOutboundTrack = observedPeerConnection == null ? void 0 : observedPeerConnection.observedOutboundTracks.get(payload.trackId);
2665
+ if (observedPeerConnection) {
2666
+ if (observedInboundTrack) {
2667
+ observedInboundTrack.muted = false;
2668
+ this._notify("inbound-track-unmuted", { ...this.eventScope, observedPeerConnection, observedInboundTrack });
2669
+ } else if (observedOutboundTrack) {
2670
+ observedOutboundTrack.muted = false;
2671
+ this._notify("outbound-track-unmuted", { ...this.eventScope, observedPeerConnection, observedOutboundTrack });
2672
+ }
2673
+ } else if (postBuffer) {
2674
+ postBuffer.push(event);
2675
+ } else {
2676
+ logger2.warn("Received MEDIA_TRACK_UNMUTED event without a corresponding observedPeerConnection or observedTrack: %o", event);
2677
+ }
2678
+ }
2679
+ break;
2680
+ }
2681
+ case "ICE_CONNECTION_STATE_CHANGED" /* ICE_CONNECTION_STATE_CHANGED */: {
2682
+ const payload = parseJsonAs(event.payload);
2683
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.iceConnectionState) && typeof payload.iceConnectionState === "string") {
2684
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2685
+ if (observedPeerConnection) {
2686
+ observedPeerConnection.iceConnectionState = payload.iceConnectionState;
2687
+ this._notify("ice-connection-state-changed", { ...this.eventScope, observedPeerConnection, state: payload.iceConnectionState });
2688
+ } else if (postBuffer) {
2689
+ postBuffer.push(event);
2690
+ } else {
2691
+ logger2.warn("Received ICE_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o", event);
2692
+ }
2693
+ }
2694
+ break;
2695
+ }
2696
+ case "ICE_GATHERING_STATE_CHANGED" /* ICE_GATHERING_STATE_CHANGED */: {
2697
+ const payload = parseJsonAs(event.payload);
2698
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.iceGatheringState) && typeof payload.iceGatheringState === "string") {
2699
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2700
+ if (observedPeerConnection) {
2701
+ observedPeerConnection.iceGatheringState = payload.iceGatheringState;
2702
+ this._notify("ice-gathering-state-changed", { ...this.eventScope, observedPeerConnection, state: payload.iceGatheringState });
2703
+ } else if (postBuffer) {
2704
+ postBuffer.push(event);
2705
+ } else {
2706
+ logger2.warn("Received ICE_GATHERING_STATE_CHANGED event without a corresponding observedPeerConnection: %o", event);
2707
+ }
2708
+ }
2709
+ break;
2710
+ }
2711
+ case "PEER_CONNECTION_STATE_CHANGED" /* PEER_CONNECTION_STATE_CHANGED */: {
2712
+ const payload = parseJsonAs(event.payload);
2713
+ if ((payload == null ? void 0 : payload.peerConnectionId) && typeof payload.peerConnectionId === "string" && (payload == null ? void 0 : payload.peerConnectionState) && typeof payload.peerConnectionState === "string") {
2714
+ const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
2715
+ if (observedPeerConnection) {
2716
+ observedPeerConnection.connectionState = payload.peerConnectionState;
2717
+ this._notify("connection-state-changed", { ...this.eventScope, observedPeerConnection, state: payload.peerConnectionState });
2718
+ } else if (postBuffer) {
2719
+ postBuffer.push(event);
2720
+ } else {
2721
+ logger2.warn("Received PEER_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o", event);
2722
+ }
2723
+ }
2724
+ break;
2725
+ }
2726
+ }
2727
+ this._notify("client-event", { ...this.eventScope, event });
2728
+ }
2729
+ _updatePeerConnection(sample, context) {
2730
+ let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
2731
+ if (!observedPeerConnection) {
2732
+ if (!sample.peerConnectionId) {
2733
+ return logger2.warn(
2734
+ `ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`,
2735
+ sample
2736
+ ), void 0;
2737
+ }
2738
+ const newObservedPeerConnection = new ObservedPeerConnection(sample.peerConnectionId, this);
2739
+ const onInboundTrackRemoved = (track) => {
2740
+ this._notify("client-track-report", {
2741
+ ...this.eventScope,
2742
+ report: {
2743
+ direction: "inbound",
2744
+ ...track.report
2745
+ }
2746
+ });
2747
+ };
2748
+ const onOutboundTrackRemoved = (track) => {
2749
+ this._notify("client-track-report", {
2750
+ ...this.eventScope,
2751
+ report: {
2752
+ direction: "outbound",
2753
+ ...track.report
2754
+ }
2755
+ });
2756
+ };
2757
+ newObservedPeerConnection.once("close", () => {
2758
+ newObservedPeerConnection == null ? void 0 : newObservedPeerConnection.off("removed-inbound-track", onInboundTrackRemoved);
2759
+ newObservedPeerConnection == null ? void 0 : newObservedPeerConnection.off("removed-outbound-track", onOutboundTrackRemoved);
2760
+ this.observedPeerConnections.delete(sample.peerConnectionId);
2761
+ });
2762
+ newObservedPeerConnection.on("removed-inbound-track", onInboundTrackRemoved);
2763
+ newObservedPeerConnection.on("removed-outbound-track", onOutboundTrackRemoved);
2764
+ this.observedPeerConnections.set(sample.peerConnectionId, newObservedPeerConnection);
2765
+ this._notify("peer-connection-added", { ...this.eventScope, observedPeerConnection: newObservedPeerConnection });
2766
+ observedPeerConnection = newObservedPeerConnection;
2767
+ }
2768
+ observedPeerConnection.accept(sample, context);
2769
+ return observedPeerConnection;
2770
+ }
2771
+ _mergeInjections(sample) {
2772
+ if (this.closed) return sample;
2773
+ if (this._injections.clientEvents) {
2774
+ if (!sample.clientEvents) sample.clientEvents = [];
2775
+ sample.clientEvents.push(...this._injections.clientEvents);
2776
+ this._injections.clientEvents = void 0;
2777
+ }
2778
+ if (this._injections.clientIssues) {
2779
+ if (!sample.clientIssues) sample.clientIssues = [];
2780
+ sample.clientIssues.push(...this._injections.clientIssues);
2781
+ this._injections.clientIssues = void 0;
2782
+ }
2783
+ if (this._injections.extensionStats) {
2784
+ if (!sample.extensionStats) sample.extensionStats = [];
2785
+ sample.extensionStats.push(...this._injections.extensionStats);
2786
+ this._injections.extensionStats = void 0;
2787
+ }
2788
+ if (this._injections.attachments) {
2789
+ if (!sample.attachments) sample.attachments = {};
2790
+ Object.assign(sample.attachments, this._injections.attachments);
2791
+ this._injections.attachments = void 0;
2792
+ }
2793
+ if (this._injections.clientMetaItems) {
2794
+ if (!sample.clientMetaItems) sample.clientMetaItems = [];
2795
+ sample.clientMetaItems.push(...this._injections.clientMetaItems);
2796
+ this._injections.clientMetaItems = void 0;
2797
+ }
2798
+ return sample;
2799
+ }
2800
+ /** Emit an Observer-bus event scoped to this client (or a peer connection under it). */
2801
+ _notify(type, ...args) {
2802
+ this.call.observer.emit(type, ...args);
2803
+ }
2804
+ };
2805
+
2806
+ // src/scores/DefaultCallScoreCalculator.ts
2807
+ var DefaultCallScoreCalculator = class {
2808
+ constructor(observedCall) {
2809
+ this.observedCall = observedCall;
2810
+ }
2811
+ observedCall;
2812
+ update() {
2813
+ let totalScore = 0;
2814
+ let totalWeight = 0;
2815
+ for (const client of this.observedCall.observedClients.values()) {
2816
+ if (client.score === void 0) continue;
2817
+ totalScore += client.score * client.calculatedScore.weight;
2818
+ totalWeight += client.calculatedScore.weight;
2819
+ }
2820
+ this.observedCall.calculatedScore.value = totalWeight ? totalScore / totalWeight : void 0;
2821
+ }
2822
+ };
2823
+
2824
+ // src/updaters/OnAllClientCallUpdater.ts
2825
+ var OnAllClientCallUpdater = class {
2826
+ constructor(_observedCall) {
2827
+ this._observedCall = _observedCall;
2828
+ this._onNewObservedClient = this._onNewObservedClient.bind(this);
2829
+ this._observedCall.once("close", () => {
2830
+ this._observedCall.off("newclient", this._onNewObservedClient);
2831
+ });
2832
+ this._observedCall.on("newclient", this._onNewObservedClient);
2833
+ }
2834
+ _observedCall;
2835
+ name = "OnAllClientCallUpdater";
2836
+ description = "Call the update() method of the ObservedCall once all client has been updated";
2837
+ _updatedClients = /* @__PURE__ */ new Set();
2838
+ closed = false;
2839
+ close() {
2840
+ if (this.closed) return;
2841
+ this.closed = true;
2842
+ this._updatedClients.clear();
2843
+ }
2844
+ _onNewObservedClient(observedClient) {
2845
+ if (this.closed) return;
2846
+ const onUpdate = (...args) => this._onClientUpdate(observedClient, args[2]);
2847
+ observedClient.once("close", () => {
2848
+ observedClient.off("update", onUpdate);
2849
+ this._updatedClients.delete(observedClient.clientId);
2850
+ this._updateIfEveryClientUpdated();
2851
+ });
2852
+ observedClient.on("update", onUpdate);
2853
+ }
2854
+ _onClientUpdate(observedClient, context) {
2855
+ if (observedClient.closed) return;
2856
+ this._updatedClients.add(observedClient.clientId);
2857
+ this._updateIfEveryClientUpdated(context);
2858
+ }
2859
+ _updateIfEveryClientUpdated(context) {
2860
+ if (this._updatedClients.size < this._observedCall.observedClients.size) {
2861
+ return;
2862
+ } else if (this.closed) {
2863
+ return;
2864
+ }
2865
+ this._updatedClients.clear();
2866
+ this._observedCall.update(context);
2867
+ }
2868
+ };
2869
+
2870
+ // src/updaters/OnIntervalUpdater.ts
2871
+ var OnIntervalUpdater = class {
2872
+ constructor(intervalInMs, _update) {
2873
+ this._update = _update;
2874
+ this.timer = setInterval(() => this._update(), intervalInMs);
2875
+ }
2876
+ _update;
2877
+ name = "OnIntervalUpdater";
2878
+ description = "Call the update() method given in the constructor once the interval elapsed";
2879
+ timer;
2880
+ close() {
2881
+ clearInterval(this.timer);
2882
+ }
2883
+ };
2884
+
2885
+ // src/updaters/OnAnyClientCallUpdater.ts
2886
+ var OnAnyClientCallUpdater = class {
2887
+ constructor(_observedCall) {
2888
+ this._observedCall = _observedCall;
2889
+ this._onNewObservedClient = this._onNewObservedClient.bind(this);
2890
+ this._observedCall.once("close", () => {
2891
+ this._observedCall.off("newclient", this._onNewObservedClient);
2892
+ });
2893
+ this._observedCall.on("newclient", this._onNewObservedClient);
2894
+ }
2895
+ _observedCall;
2896
+ name = "OnAnyClientCallUpdater";
2897
+ description = "Call the update() method of the ObservedCall when any of the client has been updated";
2898
+ closed = false;
2899
+ close() {
2900
+ if (this.closed) return;
2901
+ this.closed = true;
2902
+ }
2903
+ _onNewObservedClient(observedClient) {
2904
+ if (this.closed) return;
2905
+ const onUpdate = (...args) => {
2906
+ if (this.closed) return;
2907
+ this._observedCall.update(args[2]);
2908
+ };
2909
+ observedClient.once("close", () => {
2910
+ observedClient.off("update", onUpdate);
2911
+ });
2912
+ observedClient.on("update", onUpdate);
2913
+ }
2914
+ };
2915
+
2916
+ // src/detectors/Detectors.ts
2917
+ var logger3 = createLogger("Detectors");
2918
+ var Detectors = class {
2919
+ _detectors;
2920
+ constructor(...detectors) {
2921
+ this._detectors = detectors;
2922
+ }
2923
+ get listOfNames() {
2924
+ return this._detectors.map((d) => d.name);
2925
+ }
2926
+ add(detector) {
2927
+ this._detectors.push(detector);
2928
+ }
2929
+ remove(detector) {
2930
+ this._detectors = this._detectors.filter((d) => d !== detector);
2931
+ }
2932
+ update() {
2933
+ for (const detector of this._detectors) {
2934
+ try {
2935
+ detector.update();
2936
+ } catch (err) {
2937
+ logger3.warn(`Error updating detector ${detector == null ? void 0 : detector.name}`, err);
2938
+ }
2939
+ }
2940
+ }
2941
+ clear() {
2942
+ this._detectors = [];
2943
+ }
2944
+ };
2945
+
2946
+ // src/ObservedCall.ts
2947
+ var logger4 = createLogger("ObservedCall");
2948
+ var ObservedCall = class extends EventEmitter3 {
2949
+ constructor(settings, observer) {
2950
+ super();
2951
+ this.observer = observer;
2952
+ this.setMaxListeners(Infinity);
2953
+ this.eventScope = { observer: this.observer, observedCall: this };
2954
+ this.callId = settings.callId;
2955
+ this.appData = settings.appData ?? {};
2956
+ this.scoreCalculator = new DefaultCallScoreCalculator(this);
2957
+ this.detectors = new Detectors();
2958
+ if (settings.updateIntervalInMs && settings.updatePolicy !== "update-on-interval") {
2959
+ logger4.warn('updateIntervalInMs is ignored unless updatePolicy is "update-on-interval" (callId: %s)', settings.callId);
2960
+ }
2961
+ switch (settings.updatePolicy) {
2962
+ case "update-on-any-client-updated":
2963
+ this.updater = new OnAnyClientCallUpdater(this);
2964
+ break;
2965
+ case "update-when-all-client-updated":
2966
+ this.updater = new OnAllClientCallUpdater(this);
2967
+ break;
2968
+ case "update-on-interval":
2969
+ if (!settings.updateIntervalInMs) {
2970
+ logger4.warn('updateIntervalInMs must be set when updatePolicy is "update-on-interval"; falling back to "update-when-all-client-updated" (callId: %s)', settings.callId);
2971
+ this.updater = new OnAllClientCallUpdater(this);
2972
+ } else {
2973
+ this.updater = new OnIntervalUpdater(
2974
+ settings.updateIntervalInMs,
2975
+ this.update.bind(this)
2976
+ );
2977
+ }
2978
+ break;
2979
+ }
2980
+ this.settings = {
2981
+ closeCallIfEmptyForMs: settings.closeCallIfEmptyForMs
2982
+ };
2983
+ }
2984
+ observer;
2985
+ updater;
2986
+ scoreCalculator;
2987
+ detectors;
2988
+ callId;
2989
+ observedClients = /* @__PURE__ */ new Map();
2990
+ clientsUsedTurn = /* @__PURE__ */ new Set();
2991
+ calculatedScore = {
2992
+ weight: 1,
2993
+ value: void 0
2994
+ };
2995
+ remoteTrackResolver;
2996
+ totalAddedClients = 0;
2997
+ totalRemovedClients = 0;
2998
+ numberOfIssues = 0;
2999
+ numberOfPeerConnections = 0;
3000
+ numberOfInboundRtpStreams = 0;
3001
+ numberOfOutboundRtpStreams = 0;
3002
+ numberOfDataChannels = 0;
3003
+ maxNumberOfClients = 0;
3004
+ deltaNumberOfIssues = 0;
3005
+ // public deltaRttLt50Measurements = 0;
3006
+ // public deltaRttLt150Measurements = 0;
3007
+ // public deltaRttLt300Measurements = 0;
3008
+ // public deltaRttGtOrEq300Measurements = 0;
3009
+ appData;
3010
+ closed = false;
3011
+ startedAt;
3012
+ endedAt;
3013
+ closedAt;
3014
+ settings;
3015
+ /** Ancestry base shared by all Observer-bus events originating at this call. */
3016
+ eventScope;
3017
+ closeTimer;
3018
+ get numberOfClients() {
3019
+ return this.observedClients.size;
3020
+ }
3021
+ get score() {
3022
+ return this.calculatedScore.value;
3023
+ }
3024
+ /** Raise a call-level (server-side) issue; surfaced on the Observer bus as `call-issue`. */
3025
+ addIssue(issue) {
3026
+ if (this.closed) return;
3027
+ this._notify("call-issue", { ...this.eventScope, issue });
3028
+ }
3029
+ close() {
3030
+ var _a;
3031
+ if (this.closed) return;
3032
+ this.update();
3033
+ this.closed = true;
3034
+ (_a = this.updater) == null ? void 0 : _a.close();
3035
+ let minSampleTimestamps;
3036
+ let maxSampleTimestamps;
3037
+ for (const client of this.observedClients.values()) {
3038
+ client.close();
3039
+ if (client.joinedAt) minSampleTimestamps = Math.min(minSampleTimestamps ?? client.joinedAt, client.joinedAt);
3040
+ if (client.leftAt) maxSampleTimestamps = Math.max(maxSampleTimestamps ?? client.leftAt, client.leftAt);
3041
+ }
3042
+ if (this.startedAt === void 0) this.startedAt = minSampleTimestamps;
3043
+ if (this.endedAt === void 0) this.endedAt = maxSampleTimestamps;
3044
+ this.closedAt = Date.now();
3045
+ this.emit("close");
3046
+ this._notify("call-closed", { ...this.eventScope });
3047
+ }
3048
+ getObservedClient(clientId) {
3049
+ if (this.closed || !this.observedClients.has(clientId)) return;
3050
+ return this.observedClients.get(clientId);
3051
+ }
3052
+ createObservedClient(settings) {
3053
+ var _a, _b;
3054
+ if (this.closed) {
3055
+ logger4.warn("Attempted to create a client (clientId: %s) on a closed call %s", settings.clientId, this.callId);
3056
+ return void 0;
3057
+ }
3058
+ if (this.observedClients.has(settings.clientId)) {
3059
+ logger4.warn("Client with id %s already exists in call %s; returning the existing instance", settings.clientId, this.callId);
3060
+ return this.observedClients.get(settings.clientId);
3061
+ }
3062
+ if (!settings.closeClientIfIdleForMs) {
3063
+ settings.closeClientIfIdleForMs = this.observer.config.closeClientIfIdleForMs;
3064
+ }
3065
+ if (settings.appData === void 0) {
3066
+ settings.appData = (_b = (_a = this.observer.config).createClientAppData) == null ? void 0 : _b.call(_a, { clientId: settings.clientId, observedCall: this });
3067
+ }
3068
+ const result = new ObservedClient(settings, this);
3069
+ const wasEmpty = this.observedClients.size === 0;
3070
+ const onUpdate = () => this._onClientUpdate(result);
3071
+ const joined = () => this._clientJoined(result);
3072
+ const left = () => this._clientLeft(result);
3073
+ result.once("close", () => {
3074
+ result.off("update", onUpdate);
3075
+ result.off("joined", joined);
3076
+ result.off("left", left);
3077
+ this.observedClients.delete(settings.clientId);
3078
+ if (this.observedClients.size === 0) {
3079
+ this.emit("empty");
3080
+ this._notify("call-empty", { ...this.eventScope });
3081
+ if (this.settings.closeCallIfEmptyForMs) {
3082
+ this.closeTimer = setTimeout(() => {
3083
+ this.close();
3084
+ }, this.settings.closeCallIfEmptyForMs);
3085
+ }
3086
+ }
3087
+ ++this.totalRemovedClients;
3088
+ });
3089
+ result.on("update", onUpdate);
3090
+ result.on("joined", joined);
3091
+ result.on("left", left);
3092
+ ++this.totalAddedClients;
3093
+ this.observedClients.set(settings.clientId, result);
3094
+ this.maxNumberOfClients = Math.max(this.maxNumberOfClients, this.observedClients.size);
3095
+ if (this.closeTimer) {
3096
+ clearTimeout(this.closeTimer);
3097
+ this.closeTimer = void 0;
3098
+ }
3099
+ this.emit("newclient", result);
3100
+ this._notify("client-added", { ...this.eventScope, observedClient: result });
3101
+ if (result.sink) {
3102
+ this._notify("client-sink-created", { ...this.eventScope, observedClient: result, sink: result.sink });
3103
+ }
3104
+ if (wasEmpty) {
3105
+ this.emit("not-empty");
3106
+ this._notify("call-not-empty", { ...this.eventScope });
3107
+ }
3108
+ return result;
3109
+ }
3110
+ getOrCreateObservedClient(settings) {
3111
+ return this.getObservedClient(settings.clientId) ?? this.createObservedClient(settings);
3112
+ }
3113
+ update(context) {
3114
+ if (this.closed) return;
3115
+ this.numberOfInboundRtpStreams = 0;
3116
+ this.numberOfOutboundRtpStreams = 0;
3117
+ this.numberOfPeerConnections = 0;
3118
+ this.numberOfDataChannels = 0;
3119
+ for (const client of this.observedClients.values()) {
3120
+ this.numberOfInboundRtpStreams += client.numberOfInboundRtpStreams;
3121
+ this.numberOfOutboundRtpStreams += client.numberOfOutboundRtpStreams;
3122
+ this.numberOfPeerConnections += client.numberOfPeerConnections;
3123
+ this.numberOfDataChannels += client.numberOfDataChannels;
3124
+ }
3125
+ this.scoreCalculator.update();
3126
+ this.detectors.update();
3127
+ this.emit("update");
3128
+ this._notify("call-updated", { ...this.eventScope, context });
3129
+ this.deltaNumberOfIssues = 0;
3130
+ }
3131
+ _onClientUpdate(client) {
3132
+ this.deltaNumberOfIssues += client.deltaNumberOfIssues;
3133
+ this.numberOfIssues += client.deltaNumberOfIssues;
3134
+ if (client.usingTURN) {
3135
+ this.clientsUsedTurn.add(client.clientId);
3136
+ }
3137
+ }
3138
+ _clientJoined(client) {
3139
+ if (!client.joinedAt) return;
3140
+ this.startedAt = Math.min(this.startedAt ?? client.joinedAt, client.joinedAt);
3141
+ }
3142
+ _clientLeft(client) {
3143
+ if (!client.leftAt) return;
3144
+ this.endedAt = Math.max(this.endedAt ?? client.leftAt, client.leftAt);
3145
+ }
3146
+ /** Emit an Observer-bus event scoped to this call. */
3147
+ _notify(type, ...args) {
3148
+ this.observer.emit(type, ...args);
3149
+ }
3150
+ };
3151
+
3152
+ // src/Observer.ts
3153
+ import { EventEmitter as EventEmitter5 } from "events";
3154
+
3155
+ // src/ObservedTURN.ts
3156
+ import { EventEmitter as EventEmitter4 } from "events";
3157
+
3158
+ // src/ObservedTurnServer.ts
3159
+ var ObservedTurnServer = class {
3160
+ constructor(url, observedTURN) {
3161
+ this.url = url;
3162
+ this.observedTURN = observedTURN;
3163
+ }
3164
+ url;
3165
+ observedTURN;
3166
+ totalBytesSent = 0;
3167
+ totalBytesReceived = 0;
3168
+ totalPacketsSent = 0;
3169
+ totalPacketsReceived = 0;
3170
+ packetsSentPerSecond = 0;
3171
+ packetsReceivedPerSecond = 0;
3172
+ outboundBitrate = 0;
3173
+ inboundBitrate = 0;
3174
+ deltaBytesSent = 0;
3175
+ deltaBytesReceived = 0;
3176
+ deltaPacketsSent = 0;
3177
+ deltaPacketsReceived = 0;
3178
+ observedPeerConnections = /* @__PURE__ */ new Map();
3179
+ updated = Date.now();
3180
+ updateTurnUsage(...selectedcandidatepairs) {
3181
+ for (const selectedcandidatepair of selectedcandidatepairs) {
3182
+ this.deltaBytesReceived += selectedcandidatepair.deltaBytesReceived;
3183
+ this.deltaBytesSent += selectedcandidatepair.deltaBytesSent;
3184
+ this.deltaPacketsReceived += selectedcandidatepair.deltaPacketsReceived;
3185
+ this.deltaPacketsSent += selectedcandidatepair.deltaPacketsSent;
3186
+ }
3187
+ }
3188
+ update() {
3189
+ const now = Date.now();
3190
+ const deltaInS = (now - this.updated) / 1e3;
3191
+ this.packetsSentPerSecond = this.deltaPacketsSent / deltaInS;
3192
+ this.packetsReceivedPerSecond = this.deltaPacketsReceived / deltaInS;
3193
+ this.outboundBitrate = this.deltaBytesReceived * 8 / deltaInS;
3194
+ this.inboundBitrate = this.deltaBytesSent * 8 / deltaInS;
3195
+ this.totalBytesSent += this.deltaBytesSent;
3196
+ this.totalBytesReceived += this.deltaBytesReceived;
3197
+ this.totalPacketsSent += this.deltaPacketsSent;
3198
+ this.totalPacketsReceived += this.deltaPacketsReceived;
3199
+ this.observedTURN.totalBytesSent += this.deltaBytesSent;
3200
+ this.observedTURN.totalBytesReceived += this.deltaBytesReceived;
3201
+ this.observedTURN.totalPacketsSent += this.deltaPacketsSent;
3202
+ this.observedTURN.totalPacketsReceived += this.deltaPacketsReceived;
3203
+ this.observedTURN.inboundBitrate += this.inboundBitrate;
3204
+ this.observedTURN.outboundBitrate += this.outboundBitrate;
3205
+ this.observedTURN.packetsReceivedPerSecond += this.packetsReceivedPerSecond;
3206
+ this.observedTURN.packetsSentPerSecond += this.packetsSentPerSecond;
3207
+ this.deltaBytesSent = 0;
3208
+ this.deltaBytesReceived = 0;
3209
+ this.deltaPacketsSent = 0;
3210
+ this.deltaPacketsReceived = 0;
3211
+ this.updated = now;
3212
+ }
3213
+ };
3214
+
3215
+ // src/ObservedTURN.ts
3216
+ var logger5 = createLogger("ObservedTURN");
3217
+ var ObservedTURN = class extends EventEmitter4 {
3218
+ totalBytesSent = 0;
3219
+ totalBytesReceived = 0;
3220
+ totalPacketsSent = 0;
3221
+ totalPacketsReceived = 0;
3222
+ packetsSentPerSecond = 0;
3223
+ packetsReceivedPerSecond = 0;
3224
+ outboundBitrate = 0;
3225
+ inboundBitrate = 0;
3226
+ numberOfClients = 0;
3227
+ servers = /* @__PURE__ */ new Map();
3228
+ constructor() {
3229
+ super();
3230
+ }
3231
+ update() {
3232
+ const clientIds = /* @__PURE__ */ new Set();
3233
+ this.packetsReceivedPerSecond = 0;
3234
+ this.packetsSentPerSecond = 0;
3235
+ this.outboundBitrate = 0;
3236
+ this.inboundBitrate = 0;
3237
+ for (const server of this.servers.values()) {
3238
+ server.update();
3239
+ server.observedPeerConnections.forEach((pc) => clientIds.add(pc.client.clientId));
3240
+ }
3241
+ this.numberOfClients = clientIds.size;
3242
+ }
3243
+ addPeerConnection(peerConnection) {
3244
+ var _a;
3245
+ const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => {
3246
+ var _a2, _b, _c;
3247
+ return ((_a2 = pair.getLocalCandidate()) == null ? void 0 : _a2.candidateType) === "relay" && ((_c = (_b = pair.getRemoteCandidate()) == null ? void 0 : _b.url) == null ? void 0 : _c.startsWith("turn:"));
3248
+ });
3249
+ if (turnPairs.length !== 1) {
3250
+ return logger5.warn(`Expected exactly one TURN pair, but found for peerconnection ${peerConnection.peerConnectionId}`, turnPairs.length), void 0;
3251
+ }
3252
+ const candidatePair = turnPairs[0];
3253
+ const rawUrl = (_a = candidatePair.getRemoteCandidate()) == null ? void 0 : _a.url;
3254
+ if (!rawUrl) {
3255
+ return logger5.warn(`No remote candidate URL found for peerconnection ${peerConnection.peerConnectionId}`), void 0;
3256
+ }
3257
+ const turnUrl = new URL(rawUrl);
3258
+ const turnServerUrl = `${turnUrl.protocol}//${turnUrl.hostname}:${turnUrl.port}`;
3259
+ let turnServer = this.servers.get(turnServerUrl);
3260
+ if (!turnServer) {
3261
+ turnServer = new ObservedTurnServer(turnServerUrl, this);
3262
+ }
3263
+ return turnServer;
3264
+ }
3265
+ removePeerConnection(peerConnection) {
3266
+ for (const turnServer of this.servers.values()) {
3267
+ turnServer.observedPeerConnections.delete(peerConnection.peerConnectionId);
3268
+ }
3269
+ }
3270
+ };
3271
+
3272
+ // src/updaters/OnAllCallObserverUpdater.ts
3273
+ var OnAllCallObserverUpdater = class {
3274
+ constructor(observer) {
3275
+ this.observer = observer;
3276
+ this._onNewObservedCall = this._onNewObservedCall.bind(this);
3277
+ this.observer.once("observer-closed", () => {
3278
+ this.observer.off("call-added", this._onNewObservedCall);
3279
+ });
3280
+ this.observer.on("call-added", this._onNewObservedCall);
3281
+ }
3282
+ observer;
3283
+ name = "OnAllCallObserverUpdater";
3284
+ description = "Call Observer's update() method when all of the ObservedCalls are updated";
3285
+ _updatedCalls = /* @__PURE__ */ new Set();
3286
+ closed = false;
3287
+ close() {
3288
+ if (this.closed) return;
3289
+ this.closed = true;
3290
+ this._updatedCalls.clear();
3291
+ }
3292
+ _onNewObservedCall({ observedCall }) {
3293
+ if (this.closed) return;
3294
+ const onUpdate = () => this._onObservedCallUpdated(observedCall);
3295
+ observedCall.once("close", () => {
3296
+ observedCall.off("update", onUpdate);
3297
+ this._updatedCalls.delete(observedCall.callId);
3298
+ this._updateIfEveryCallUpdated();
3299
+ });
3300
+ observedCall.on("update", onUpdate);
3301
+ }
3302
+ _onObservedCallUpdated(observedCall) {
3303
+ if (observedCall.closed) return;
3304
+ this._updatedCalls.add(observedCall.callId);
3305
+ this._updateIfEveryCallUpdated();
3306
+ }
3307
+ _updateIfEveryCallUpdated() {
3308
+ if (this._updatedCalls.size < this.observer.observedCalls.size) return;
3309
+ else if (this.closed) return;
3310
+ this._updatedCalls.clear();
3311
+ this.observer.update();
3312
+ }
3313
+ };
3314
+
3315
+ // src/updaters/OnAnyCallObserverUpdater.ts
3316
+ var OnAnyCallObserverUpdater = class {
3317
+ constructor(observver) {
3318
+ this.observver = observver;
3319
+ this._onNewObservedCall = this._onNewObservedCall.bind(this);
3320
+ this.observver.once("observer-closed", () => {
3321
+ this.observver.off("call-added", this._onNewObservedCall);
3322
+ });
3323
+ this.observver.on("call-added", this._onNewObservedCall);
3324
+ }
3325
+ observver;
3326
+ name = "OnAnyCallObserverUpdater";
3327
+ description = "Call Observer's update() method on any of the ObservedCall is updated";
3328
+ closed = false;
3329
+ close() {
3330
+ if (this.closed) return;
3331
+ this.closed = true;
3332
+ }
3333
+ _onNewObservedCall({ observedCall }) {
3334
+ if (this.closed) return;
3335
+ const onUpdate = () => {
3336
+ if (this.closed) return;
3337
+ this.observver.update();
3338
+ };
3339
+ observedCall.once("close", () => {
3340
+ observedCall.off("update", onUpdate);
3341
+ });
3342
+ observedCall.on("update", onUpdate);
3343
+ }
3344
+ };
3345
+
3346
+ // src/utils/MediasoupRemoteTrackResolver.ts
3347
+ var MediasoupRemoteTrackResolver = class {
3348
+ constructor(observedCall) {
3349
+ this.observedCall = observedCall;
3350
+ const observer = observedCall.observer;
3351
+ const onInboundAdded = (p) => {
3352
+ if (p.observedCall === this.observedCall) this._addInboundTrack(p.observedInboundTrack);
3353
+ };
3354
+ const onInboundRemoved = (p) => {
3355
+ if (p.observedCall === this.observedCall) this._removeInboundTrack(p.observedInboundTrack);
3356
+ };
3357
+ const onOutboundAdded = (p) => {
3358
+ if (p.observedCall === this.observedCall) this._addOutboundTrack(p.observedOutboundTrack);
3359
+ };
3360
+ const onOutboundRemoved = (p) => {
3361
+ if (p.observedCall === this.observedCall) this._removeOutboundTrack(p.observedOutboundTrack);
3362
+ };
3363
+ observer.on("inbound-track-added", onInboundAdded);
3364
+ observer.on("inbound-track-removed", onInboundRemoved);
3365
+ observer.on("outbound-track-added", onOutboundAdded);
3366
+ observer.on("outbound-track-removed", onOutboundRemoved);
3367
+ observedCall.once("close", () => {
3368
+ observer.off("inbound-track-added", onInboundAdded);
3369
+ observer.off("inbound-track-removed", onInboundRemoved);
3370
+ observer.off("outbound-track-added", onOutboundAdded);
3371
+ observer.off("outbound-track-removed", onOutboundRemoved);
3372
+ });
3373
+ }
3374
+ observedCall;
3375
+ _consumerIdToProducerId = /* @__PURE__ */ new Map();
3376
+ _producerIdToOutboundTrack = /* @__PURE__ */ new Map();
3377
+ _consumerIdToInboundTrack = /* @__PURE__ */ new Map();
3378
+ // private _producerIdToOutboundTrack = new Map<string, ObservedOutboundTrack>();
3379
+ _inboundTrackToConsumerId = /* @__PURE__ */ new Map();
3380
+ _producerIdToConsumerIds = /* @__PURE__ */ new Map();
3381
+ _outboundTrackToProducerId = /* @__PURE__ */ new Map();
3382
+ resolveRemoteOutboundTrack(inboundTrack) {
3383
+ const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
3384
+ if (!consumerId) return;
3385
+ const producerId = this._consumerIdToProducerId.get(consumerId);
3386
+ if (!producerId) return;
3387
+ return this._producerIdToOutboundTrack.get(producerId);
3388
+ }
3389
+ resolveRemoteInboundTracks(outboundTrack) {
3390
+ const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
3391
+ if (!producerId) return;
3392
+ const consumerIds = this._producerIdToConsumerIds.get(producerId);
3393
+ if (!consumerIds) return;
3394
+ return consumerIds.map((consumerId) => this._consumerIdToInboundTrack.get(consumerId)).filter((inboundTrack) => Boolean(inboundTrack));
3395
+ }
3396
+ _addInboundTrack(inboundTrack) {
3397
+ const attachments = this._getInboundTrackAttachments(inboundTrack);
3398
+ if (!attachments) return;
3399
+ const {
3400
+ producerId,
3401
+ consumerId
3402
+ } = attachments;
3403
+ this._inboundTrackToConsumerId.set(inboundTrack.id, consumerId);
3404
+ this._consumerIdToProducerId.set(consumerId, producerId);
3405
+ this._consumerIdToInboundTrack.set(consumerId, inboundTrack);
3406
+ let producerConsumers = this._producerIdToConsumerIds.get(producerId);
3407
+ if (!producerConsumers) {
3408
+ producerConsumers = [];
3409
+ this._producerIdToConsumerIds.set(producerId, producerConsumers);
3410
+ }
3411
+ producerConsumers.push(consumerId);
3412
+ }
3413
+ _removeInboundTrack(inboundTrack) {
3414
+ const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
3415
+ if (!consumerId) return;
3416
+ this._inboundTrackToConsumerId.delete(inboundTrack.id);
3417
+ this._consumerIdToProducerId.delete(consumerId);
3418
+ this._consumerIdToInboundTrack.delete(consumerId);
3419
+ const producerConsumers = this._producerIdToConsumerIds.get(consumerId);
3420
+ if (!producerConsumers) return;
3421
+ const filteredProducerConsumers = producerConsumers.filter((id) => id !== consumerId);
3422
+ if (filteredProducerConsumers.length === 0) {
3423
+ this._producerIdToConsumerIds.delete(consumerId);
3424
+ } else {
3425
+ this._producerIdToConsumerIds.set(consumerId, filteredProducerConsumers);
3426
+ }
3427
+ }
3428
+ _addOutboundTrack(outboundTrack) {
3429
+ const attachments = this._getOutboundTrackAttachments(outboundTrack);
3430
+ if (!attachments) return;
3431
+ const {
3432
+ producerId
3433
+ } = attachments;
3434
+ this._producerIdToOutboundTrack.set(producerId, outboundTrack);
3435
+ this._outboundTrackToProducerId.set(outboundTrack.id, producerId);
3436
+ }
3437
+ _removeOutboundTrack(outboundTrack) {
3438
+ const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
3439
+ if (!producerId) return;
3440
+ this._producerIdToOutboundTrack.delete(producerId);
3441
+ this._outboundTrackToProducerId.delete(outboundTrack.id);
3442
+ }
3443
+ _getInboundTrackAttachments(inboundTrack) {
3444
+ const {
3445
+ producerId,
3446
+ consumerId
3447
+ } = inboundTrack.attachments ?? {};
3448
+ if (!producerId || !consumerId || typeof producerId !== "string" || typeof consumerId !== "string") return;
3449
+ return {
3450
+ producerId,
3451
+ consumerId
3452
+ };
3453
+ }
3454
+ _getOutboundTrackAttachments(outboundTrack) {
3455
+ const {
3456
+ producerId
3457
+ } = outboundTrack.attachments ?? {};
3458
+ if (!producerId || typeof producerId !== "string") return;
3459
+ return {
3460
+ producerId
3461
+ };
3462
+ }
3463
+ };
3464
+
3465
+ // src/Observer.ts
3466
+ var logger6 = createLogger("Observer");
3467
+ var Observer = class extends EventEmitter5 {
3468
+ constructor(config = {
3469
+ updatePolicy: "update-when-all-call-updated",
3470
+ appData: {}
3471
+ }) {
3472
+ super();
3473
+ this.config = config;
3474
+ this.setMaxListeners(Infinity);
3475
+ this.update = this.update.bind(this);
3476
+ const currentUpdatePolicy = (config == null ? void 0 : config.updatePolicy) ?? "update-when-all-call-updated";
3477
+ switch (currentUpdatePolicy) {
3478
+ case "update-on-any-call-updated":
3479
+ this.updater = new OnAnyCallObserverUpdater(this);
3480
+ break;
3481
+ case "update-when-all-call-updated":
3482
+ this.updater = new OnAllCallObserverUpdater(this);
3483
+ break;
3484
+ case "update-on-interval": {
3485
+ const interval = config == null ? void 0 : config.updateIntervalInMs;
3486
+ if (!interval) {
3487
+ logger6.warn('updateIntervalInMs must be set when updatePolicy is "update-on-interval"; falling back to "update-when-all-call-updated"');
3488
+ this.updater = new OnAllCallObserverUpdater(this);
3489
+ } else {
3490
+ this.updater = new OnIntervalUpdater(
3491
+ interval,
3492
+ this.update.bind(this)
3493
+ );
3494
+ }
3495
+ break;
3496
+ }
3497
+ }
3498
+ }
3499
+ config;
3500
+ observedTURN = new ObservedTURN();
3501
+ observedCalls = /* @__PURE__ */ new Map();
3502
+ updater;
3503
+ /** Ancestry base shared by all Observer-bus events originating at the observer. */
3504
+ eventScope = { observer: this };
3505
+ closed = false;
3506
+ totalAddedCall = 0;
3507
+ totalRemovedCall = 0;
3508
+ numberOfClientsUsingTurn = 0;
3509
+ numberOfClients = 0;
3510
+ numberOfInboundRtpStreams = 0;
3511
+ numberOfOutboundRtpStreams = 0;
3512
+ numberOfDataChannels = 0;
3513
+ numberOfPeerConnections = 0;
3514
+ _timer;
3515
+ get numberOfCalls() {
3516
+ return this.observedCalls.size;
3517
+ }
3518
+ get appData() {
3519
+ return this.config.appData;
3520
+ }
3521
+ getObservedCall(callId) {
3522
+ if (this.closed || !this.observedCalls.has(callId)) return;
3523
+ return this.observedCalls.get(callId);
3524
+ }
3525
+ createObservedCall(settings) {
3526
+ var _a, _b;
3527
+ if (this.closed) {
3528
+ logger6.warn("Attempted to create a call (callId: %s) on a closed observer", settings.callId);
3529
+ return void 0;
3530
+ }
3531
+ if (this.observedCalls.has(settings.callId)) {
3532
+ logger6.warn("Observed Call with id %s already exists; returning the existing instance", settings.callId);
3533
+ return this.observedCalls.get(settings.callId);
3534
+ }
3535
+ const callSettings = {
3536
+ ...settings,
3537
+ updatePolicy: settings.updatePolicy ?? this.config.defaultCallUpdatePolicy,
3538
+ updateIntervalInMs: settings.updateIntervalInMs ?? this.config.defaultCallUpdateIntervalInMs,
3539
+ closeCallIfEmptyForMs: settings.closeCallIfEmptyForMs ?? this.config.closeCallIfEmptyForMs,
3540
+ appData: settings.appData ?? ((_b = (_a = this.config).createCallAppData) == null ? void 0 : _b.call(_a, { callId: settings.callId, observer: this }))
3541
+ };
3542
+ const observedCall = new ObservedCall(callSettings, this);
3543
+ if (callSettings.remoteTrackResolvePolicy === "mediasoup-sfu") {
3544
+ observedCall.remoteTrackResolver = new MediasoupRemoteTrackResolver(observedCall);
3545
+ }
3546
+ observedCall.once("close", () => {
3547
+ this.observedCalls.delete(observedCall.callId);
3548
+ ++this.totalRemovedCall;
3549
+ });
3550
+ this.observedCalls.set(observedCall.callId, observedCall);
3551
+ ++this.totalAddedCall;
3552
+ this._notify("call-added", { ...this.eventScope, observedCall });
3553
+ return observedCall;
3554
+ }
3555
+ getOrCreateObservedCall(settings) {
3556
+ return this.getObservedCall(settings.callId) ?? this.createObservedCall(settings);
3557
+ }
3558
+ close() {
3559
+ if (this.closed) {
3560
+ return logger6.debug("Attempted to close twice");
3561
+ }
3562
+ this.closed = true;
3563
+ clearInterval(this._timer);
3564
+ this._timer = void 0;
3565
+ this.observedCalls.forEach((call) => call.close());
3566
+ this._notify("observer-closed", { ...this.eventScope });
3567
+ }
3568
+ accept(sample, context) {
3569
+ var _a, _b, _c, _d;
3570
+ if (this.closed) {
3571
+ this._notify("sample-rejected", { ...this.eventScope, reason: "observer-closed", sample });
3572
+ return;
3573
+ }
3574
+ if (!sample.callId) {
3575
+ this._notify("sample-rejected", { ...this.eventScope, reason: "missing-callId", sample });
3576
+ return;
3577
+ }
3578
+ if (!sample.clientId) {
3579
+ this._notify("sample-rejected", { ...this.eventScope, reason: "missing-clientId", sample });
3580
+ return;
3581
+ }
3582
+ let call = this.getObservedCall(sample.callId);
3583
+ if (!call) {
3584
+ call = this.createObservedCall({
3585
+ callId: sample.callId,
3586
+ appData: (_b = (_a = this.config).createCallAppData) == null ? void 0 : _b.call(_a, { callId: sample.callId, observer: this })
3587
+ });
3588
+ }
3589
+ if (!call) return;
3590
+ let client = call.getObservedClient(sample.clientId);
3591
+ if (!client) {
3592
+ client = call.createObservedClient({
3593
+ clientId: sample.clientId,
3594
+ appData: (_d = (_c = this.config).createClientAppData) == null ? void 0 : _d.call(_c, { clientId: sample.clientId, observedCall: call })
3595
+ });
3596
+ }
3597
+ if (!client) return;
3598
+ client.accept(sample, context);
3599
+ }
3600
+ update() {
3601
+ if (this.closed) {
3602
+ return;
3603
+ }
3604
+ this.numberOfInboundRtpStreams = 0;
3605
+ this.numberOfOutboundRtpStreams = 0;
3606
+ this.numberOfPeerConnections = 0;
3607
+ this.numberOfDataChannels = 0;
3608
+ this.numberOfClients = 0;
3609
+ this.numberOfClientsUsingTurn = 0;
3610
+ for (const call of this.observedCalls.values()) {
3611
+ this.numberOfInboundRtpStreams += call.numberOfInboundRtpStreams;
3612
+ this.numberOfOutboundRtpStreams += call.numberOfOutboundRtpStreams;
3613
+ this.numberOfPeerConnections += call.numberOfPeerConnections;
3614
+ this.numberOfDataChannels += call.numberOfDataChannels;
3615
+ this.numberOfClients += call.numberOfClients;
3616
+ this.numberOfClientsUsingTurn += call.clientsUsedTurn.size;
3617
+ }
3618
+ this.observedTURN.update();
3619
+ this._notify("observer-updated", { ...this.eventScope });
3620
+ }
3621
+ /** Emit an Observer-bus event. */
3622
+ _notify(type, ...args) {
3623
+ this.emit(type, ...args);
3624
+ }
3625
+ };
3626
+
3627
+ // src/sinks/ClientSampleSink.ts
3628
+ import { EventEmitter as EventEmitter6 } from "events";
3629
+ var ClientSampleSink = class extends EventEmitter6 {
3630
+ };
3631
+
3632
+ // src/sinks/JsonlFileSink.ts
3633
+ import * as fs from "fs";
3634
+ import * as path from "path";
3635
+ var JsonlFileSink = class extends ClientSampleSink {
3636
+ _stream;
3637
+ _serializeSample;
3638
+ constructor(options) {
3639
+ super();
3640
+ this._stream = fs.createWriteStream(options.path, { flags: "a" });
3641
+ this._stream.on("close", () => this.emit("close"));
3642
+ this._stream.on("finish", () => this.emit("finish"));
3643
+ this._stream.on("drain", () => this.emit("drain"));
3644
+ this._stream.on("error", (err) => this.emit("error", err));
3645
+ this._serializeSample = options.serializeSample ?? ((sample) => JSON.stringify(sample));
3646
+ }
3647
+ write(sample) {
3648
+ return this._stream.write(`${this._serializeSample(sample)}
3649
+ `);
3650
+ }
3651
+ end() {
3652
+ this._stream.end();
3653
+ }
3654
+ };
3655
+ function createJsonlFileSink(options) {
3656
+ return new JsonlFileSink(options);
3657
+ }
3658
+ function createJsonlFileSinkFactory(options) {
3659
+ return ({ clientId, observedCall }) => {
3660
+ var _a;
3661
+ const filename = ((_a = options.getFileName) == null ? void 0 : _a.call(options, { callId: observedCall.callId, clientId })) ?? `${observedCall.callId}__${clientId}.jsonl`;
3662
+ return createJsonlFileSink({
3663
+ path: path.join(options.directory, filename),
3664
+ serializeSample: options.serializeSample
3665
+ });
3666
+ };
3667
+ }
3668
+
3669
+ // src/sinks/InMemorySink.ts
3670
+ var InMemorySink = class extends ClientSampleSink {
3671
+ constructor(samples = []) {
3672
+ super();
3673
+ this.samples = samples;
3674
+ }
3675
+ samples;
3676
+ write(sample) {
3677
+ this.samples.push(sample);
3678
+ return true;
3679
+ }
3680
+ end() {
3681
+ this.emit("close");
3682
+ }
3683
+ };
3684
+ function createInMemorySink(samples) {
3685
+ return new InMemorySink(samples);
3686
+ }
3687
+ export {
3688
+ ClientEventTypes,
3689
+ ClientMetaTypes,
3690
+ ClientSampleSink,
3691
+ Detectors,
3692
+ InMemorySink,
3693
+ JsonlFileSink,
3694
+ ObservedCall,
3695
+ ObservedCertificate,
3696
+ ObservedClient,
3697
+ ObservedCodec,
3698
+ ObservedDataChannel,
3699
+ ObservedIceCandidate,
3700
+ ObservedIceCandidatePair,
3701
+ ObservedIceTransport,
3702
+ ObservedInboundRtp,
3703
+ ObservedInboundTrack,
3704
+ ObservedMediaPlayout,
3705
+ ObservedMediaSource,
3706
+ ObservedOutboundRtp,
3707
+ ObservedOutboundTrack,
3708
+ ObservedPeerConnection,
3709
+ ObservedPeerConnectionTransport,
3710
+ ObservedRemoteInboundRtp,
3711
+ ObservedRemoteOutboundRtp,
3712
+ Observer,
3713
+ createInMemorySink,
3714
+ createJsonlFileSink,
3715
+ createJsonlFileSinkFactory,
3716
+ createLogger,
3717
+ setObserverLogger
3718
+ };
3719
+ //# sourceMappingURL=index.mjs.map