@observertc/observer-js 1.0.1-72a904d.0 → 1.0.1-9341fcd.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/lib/ObservedCall.d.ts +4 -8
  2. package/lib/ObservedCall.d.ts.map +1 -1
  3. package/lib/ObservedCall.js +16 -72
  4. package/lib/ObservedCallEventMonitor.d.ts +104 -0
  5. package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
  6. package/lib/ObservedCallEventMonitor.js +314 -0
  7. package/lib/ObservedClient.d.ts +16 -8
  8. package/lib/ObservedClient.d.ts.map +1 -1
  9. package/lib/ObservedClient.js +257 -99
  10. package/lib/ObservedClientEventMonitor.d.ts +89 -0
  11. package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
  12. package/lib/ObservedClientEventMonitor.js +247 -0
  13. package/lib/ObservedDataChannel.d.ts +2 -0
  14. package/lib/ObservedDataChannel.d.ts.map +1 -1
  15. package/lib/ObservedDataChannel.js +2 -0
  16. package/lib/ObservedIceCandidatePair.d.ts +2 -1
  17. package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
  18. package/lib/ObservedIceCandidatePair.js +17 -1
  19. package/lib/ObservedInboundTrack.d.ts +2 -0
  20. package/lib/ObservedInboundTrack.d.ts.map +1 -1
  21. package/lib/ObservedInboundTrack.js +2 -0
  22. package/lib/ObservedOutboundTrack.d.ts +2 -0
  23. package/lib/ObservedOutboundTrack.d.ts.map +1 -1
  24. package/lib/ObservedOutboundTrack.js +2 -0
  25. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  26. package/lib/ObservedPeerConnection.js +22 -6
  27. package/lib/Observer.d.ts +9 -7
  28. package/lib/Observer.d.ts.map +1 -1
  29. package/lib/Observer.js +16 -22
  30. package/lib/ObserverEventMonitor.d.ts +106 -0
  31. package/lib/ObserverEventMonitor.d.ts.map +1 -0
  32. package/lib/ObserverEventMonitor.js +320 -0
  33. package/lib/ObserverSummary.d.ts +2 -0
  34. package/lib/ObserverSummary.d.ts.map +1 -1
  35. package/lib/common/utils.d.ts +1 -0
  36. package/lib/common/utils.d.ts.map +1 -1
  37. package/lib/common/utils.js +7 -1
  38. package/lib/index.d.ts +2 -0
  39. package/lib/index.d.ts.map +1 -1
  40. package/lib/index.js +5 -1
  41. package/lib/schema/ClientEventTypes.d.ts +60 -0
  42. package/lib/schema/ClientEventTypes.d.ts.map +1 -1
  43. package/lib/schema/ClientSample.d.ts +1 -1
  44. package/lib/schema/ClientSample.d.ts.map +1 -1
  45. package/lib/updaters/{OnAllCallObserverUpdater_.d.ts → OnAllCallObserverUpdater.d.ts} +3 -1
  46. package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
  47. package/lib/updaters/{OnAllCallObserverUpdater_.js → OnAllCallObserverUpdater.js} +13 -1
  48. package/lib/updaters/OnAllClientCallUpdater.d.ts +2 -0
  49. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -1
  50. package/lib/updaters/OnAllClientCallUpdater.js +16 -0
  51. package/lib/updaters/{OnAnyCallObserverUpdater_.d.ts → OnAnyCallObserverUpdater.d.ts} +2 -1
  52. package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
  53. package/lib/updaters/{OnAnyCallObserverUpdater_.js → OnAnyCallObserverUpdater.js} +11 -1
  54. package/lib/updaters/OnAnyClientCallUpdater.d.ts +1 -0
  55. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -1
  56. package/lib/updaters/OnAnyClientCallUpdater.js +11 -2
  57. package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
  58. package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
  59. package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
  60. package/package.json +1 -1
  61. package/src/ObservedCall.ts +56 -82
  62. package/src/ObservedCallEventMonitor.ts +392 -0
  63. package/src/ObservedClient.ts +335 -114
  64. package/src/ObservedClientEventMonitor.ts +301 -0
  65. package/src/ObservedDataChannel.ts +3 -0
  66. package/src/ObservedIceCandidatePair.ts +18 -2
  67. package/src/ObservedInboundTrack.ts +3 -0
  68. package/src/ObservedOutboundTrack.ts +3 -0
  69. package/src/ObservedPeerConnection.ts +25 -10
  70. package/src/Observer.ts +47 -29
  71. package/src/ObserverEventMonitor.ts +398 -0
  72. package/src/ObserverSummary.ts +3 -1
  73. package/src/common/utils.ts +6 -0
  74. package/src/index.ts +2 -0
  75. package/src/schema/ClientEventTypes.ts +64 -0
  76. package/src/schema/ClientSample.ts +1 -1
  77. package/src/updaters/{OnAllCallObserverUpdater_.ts → OnAllCallObserverUpdater.ts} +14 -1
  78. package/src/updaters/OnAllClientCallUpdater.ts +15 -0
  79. package/src/updaters/{OnAnyCallObserverUpdater_.ts → OnAnyCallObserverUpdater.ts} +11 -2
  80. package/src/updaters/OnAnyClientCallUpdater.ts +9 -2
  81. package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
  82. package/lib/updaters/OnAllCallObserverUpdater_.d.ts.map +0 -1
  83. package/lib/updaters/OnAnyCallObserverUpdater_.d.ts.map +0 -1
@@ -0,0 +1,301 @@
1
+ import { ObservedCertificate } from './ObservedCertificate';
2
+ import { ObservedClient } from './ObservedClient';
3
+ import { ObservedCodec } from './ObservedCodec';
4
+ import { ObservedDataChannel } from './ObservedDataChannel';
5
+ import { ObservedIceCandidate } from './ObservedIceCandidate';
6
+ import { ObservedIceCandidatePair } from './ObservedIceCandidatePair';
7
+ import { ObservedIceTransport } from './ObservedIceTransport';
8
+ import { ObservedInboundRtp } from './ObservedInboundRtp';
9
+ import { ObservedInboundTrack } from './ObservedInboundTrack';
10
+ import { ObservedMediaPlayout } from './ObservedMediaPlayout';
11
+ import { ObservedMediaSource } from './ObservedMediaSource';
12
+ import { ObservedOutboundRtp } from './ObservedOutboundRtp';
13
+ import { ObservedOutboundTrack } from './ObservedOutboundTrack';
14
+ import { ObservedPeerConnection } from './ObservedPeerConnection';
15
+ import { ClientIssue, ClientMetaData, ExtensionStat } from './schema/ClientSample';
16
+
17
+ export class ObservedClientEventMonitor<Context> {
18
+ public constructor(
19
+ public readonly observedClient: ObservedClient,
20
+ public readonly context: Context,
21
+ ) {
22
+ this._onPeerConnconnectionAdded = this._onPeerConnconnectionAdded.bind(this);
23
+ this._onPeerConnectionRemoved = this._onPeerConnectionRemoved.bind(this);
24
+ this._onCertificateAdded = this._onCertificateAdded.bind(this);
25
+ this._onCertificateRemoved = this._onCertificateRemoved.bind(this);
26
+ this._onInboundTrackAdded = this._onInboundTrackAdded.bind(this);
27
+ this._onInboundTrackRemoved = this._onInboundTrackRemoved.bind(this);
28
+ this._onOutboundTrackAdded = this._onOutboundTrackAdded.bind(this);
29
+ this._onOutboundTrackRemoved = this._onOutboundTrackRemoved.bind(this);
30
+ this._onInboundRtpAdded = this._onInboundRtpAdded.bind(this);
31
+ this._onInboundRtpRemoved = this._onInboundRtpRemoved.bind(this);
32
+ this._onOutboundRtpAdded = this._onOutboundRtpAdded.bind(this);
33
+ this._onOutboundRtpRemoved = this._onOutboundRtpRemoved.bind(this);
34
+ this._onDataChannelAdded = this._onDataChannelAdded.bind(this);
35
+ this._onDataChannelRemoved = this._onDataChannelRemoved.bind(this);
36
+ this._onAddedIceTransport = this._onAddedIceTransport.bind(this);
37
+ this._onRemovedIceTransport = this._onRemovedIceTransport.bind(this);
38
+ this._onIceCandidateAdded = this._onIceCandidateAdded.bind(this);
39
+ this._onIceCandidateRemoved = this._onIceCandidateRemoved.bind(this);
40
+ this._onAddedIceCandidatePair = this._onAddedIceCandidatePair.bind(this);
41
+ this._onRemovedIceCandidatePair = this._onRemovedIceCandidatePair.bind(this);
42
+ this._onAddedMediaCodec = this._onAddedMediaCodec.bind(this);
43
+ this._onRemovedMediaCodec = this._onRemovedMediaCodec.bind(this);
44
+ this._onAddedMediaPlayout = this._onAddedMediaPlayout.bind(this);
45
+ this._onRemovedMediaPlayout = this._onRemovedMediaPlayout.bind(this);
46
+ this._onMediaSourceAdded = this._onMediaSourceAdded.bind(this);
47
+ this._onMediaSourceRemoved = this._onMediaSourceRemoved.bind(this);
48
+ this._onClientClosed = this._onClientClosed.bind(this);
49
+ this._onClientIssue = this._onClientIssue.bind(this);
50
+ this._onClientMetadata = this._onClientMetadata.bind(this);
51
+ this._onClientJoined = this._onClientJoined.bind(this);
52
+ this._onClientLeft = this._onClientLeft.bind(this);
53
+ this._onUserMediaError = this._onUserMediaError.bind(this);
54
+ this._onUsingTurn = this._onUsingTurn.bind(this);
55
+
56
+ this.observedClient.on('newpeerconnection', this._onPeerConnconnectionAdded);
57
+ this.observedClient.on('issue', this._onClientIssue);
58
+ this.observedClient.on('metaData', this._onClientMetadata);
59
+ this.observedClient.on('joined', this._onClientJoined);
60
+ this.observedClient.on('left', this._onClientLeft);
61
+ this.observedClient.on('rejoined', this._onClientJoined);
62
+ this.observedClient.on('usermediaerror', this._onUserMediaError);
63
+ this.observedClient.on('usingturn', this._onUsingTurn);
64
+
65
+ this.observedClient.once('close', this._onClientClosed);
66
+ }
67
+
68
+ public onClientClosed?: (client: ObservedClient, ctx: Context) => void;
69
+ private _onClientClosed() {
70
+ this.onClientClosed?.(this.observedClient, this.context);
71
+
72
+ this.observedClient.off('newpeerconnection', this._onPeerConnconnectionAdded);
73
+ this.observedClient.off('issue', this._onClientIssue);
74
+ this.observedClient.off('metaData', this._onClientMetadata);
75
+ this.observedClient.off('joined', this._onClientJoined);
76
+ this.observedClient.off('left', this._onClientLeft);
77
+ this.observedClient.off('rejoined', this._onClientJoined);
78
+ this.observedClient.off('usermediaerror', this._onUserMediaError);
79
+ this.observedClient.off('usingturn', this._onUsingTurn);
80
+
81
+ }
82
+
83
+ public onPeerConnectionAdded?: (peerConnection: ObservedPeerConnection, ctx: Context) => void;
84
+ private _onPeerConnconnectionAdded(peerConnection: ObservedPeerConnection) {
85
+ this.onPeerConnectionAdded?.(peerConnection, this.context);
86
+
87
+ peerConnection.once('close', () => this._onPeerConnectionRemoved(peerConnection));
88
+
89
+ peerConnection.on('added-certificate', this._onCertificateAdded);
90
+ peerConnection.on('removed-certificate', this._onCertificateRemoved);
91
+ peerConnection.on('added-inbound-track', this._onInboundTrackAdded);
92
+ peerConnection.on('removed-inbound-track', this._onInboundTrackRemoved);
93
+ peerConnection.on('added-outbound-track', this._onOutboundTrackAdded);
94
+ peerConnection.on('removed-outbound-track', this._onOutboundTrackRemoved);
95
+ peerConnection.on('added-inbound-rtp', this._onInboundRtpAdded);
96
+ peerConnection.on('removed-inbound-rtp', this._onInboundRtpRemoved);
97
+ peerConnection.on('added-outbound-rtp', this._onOutboundRtpAdded);
98
+ peerConnection.on('removed-outbound-rtp', this._onOutboundRtpRemoved);
99
+ peerConnection.on('added-data-channel', this._onDataChannelAdded);
100
+ peerConnection.on('removed-data-channel', this._onDataChannelRemoved);
101
+ peerConnection.on('added-ice-transport', this._onAddedIceTransport);
102
+ peerConnection.on('removed-ice-transport', this._onRemovedIceTransport);
103
+ peerConnection.on('added-ice-candidate', this._onIceCandidateAdded);
104
+ peerConnection.on('removed-ice-candidate', this._onIceCandidateRemoved);
105
+ peerConnection.on('added-ice-candidate-pair', this._onAddedIceCandidatePair);
106
+ peerConnection.on('removed-ice-candidate-pair', this._onRemovedIceCandidatePair);
107
+ peerConnection.on('added-codec', this._onAddedMediaCodec);
108
+ peerConnection.on('removed-codec', this._onRemovedMediaCodec);
109
+ peerConnection.on('added-media-playout', this._onAddedMediaPlayout);
110
+ peerConnection.on('removed-media-playout', this._onRemovedMediaPlayout);
111
+ peerConnection.on('added-media-source', this._onMediaSourceAdded);
112
+ peerConnection.on('removed-media-source', this._onMediaSourceRemoved);
113
+
114
+ }
115
+
116
+ public onPeerConnectionRemoved?: (peerConnection: ObservedPeerConnection, ctx: Context) => void;
117
+ private _onPeerConnectionRemoved(peerConnection: ObservedPeerConnection) {
118
+ this.onPeerConnectionRemoved?.(peerConnection, this.context);
119
+
120
+ peerConnection.off('added-certificate', this._onCertificateAdded);
121
+ peerConnection.off('removed-certificate', this._onCertificateRemoved);
122
+ peerConnection.off('added-inbound-track', this._onInboundTrackAdded);
123
+ peerConnection.off('removed-inbound-track', this._onInboundTrackRemoved);
124
+ peerConnection.off('added-outbound-track', this._onOutboundTrackAdded);
125
+ peerConnection.off('removed-outbound-track', this._onOutboundTrackRemoved);
126
+ peerConnection.off('added-inbound-rtp', this._onInboundRtpAdded);
127
+ peerConnection.off('removed-inbound-rtp', this._onInboundRtpRemoved);
128
+ peerConnection.off('added-outbound-rtp', this._onOutboundRtpAdded);
129
+ peerConnection.off('removed-outbound-rtp', this._onOutboundRtpRemoved);
130
+ peerConnection.off('added-data-channel', this._onDataChannelAdded);
131
+ peerConnection.off('removed-data-channel', this._onDataChannelRemoved);
132
+ peerConnection.off('added-ice-transport', this._onAddedIceTransport);
133
+ peerConnection.off('removed-ice-transport', this._onRemovedIceTransport);
134
+ peerConnection.off('added-ice-candidate', this._onIceCandidateAdded);
135
+ peerConnection.off('removed-ice-candidate', this._onIceCandidateRemoved);
136
+ peerConnection.off('added-ice-candidate-pair', this._onAddedIceCandidatePair);
137
+ peerConnection.off('removed-ice-candidate-pair', this._onRemovedIceCandidatePair);
138
+ peerConnection.off('added-codec', this._onAddedMediaCodec);
139
+ peerConnection.off('removed-codec', this._onRemovedMediaCodec);
140
+ peerConnection.off('added-media-playout', this._onAddedMediaPlayout);
141
+ peerConnection.off('removed-media-playout', this._onRemovedMediaPlayout);
142
+ peerConnection.off('added-media-source', this._onMediaSourceAdded);
143
+ peerConnection.off('removed-media-source', this._onMediaSourceRemoved);
144
+
145
+ }
146
+
147
+ public onCertificateAdded?: (certificate: ObservedCertificate, ctx: Context) => void;
148
+ private _onCertificateAdded(certificate: ObservedCertificate) {
149
+ this.onCertificateAdded?.(certificate, this.context);
150
+ }
151
+
152
+ public onCertificateRemoved?: (certificate: ObservedCertificate, ctx: Context) => void;
153
+ private _onCertificateRemoved(certificate: ObservedCertificate) {
154
+ this.onCertificateRemoved?.(certificate, this.context);
155
+ }
156
+
157
+ public onInboundTrackAdded?: (inboundTrack: ObservedInboundTrack, ctx: Context) => void;
158
+ private _onInboundTrackAdded(inboundTrack: ObservedInboundTrack) {
159
+ this.onInboundTrackAdded?.(inboundTrack, this.context);
160
+ }
161
+
162
+ public onInboundTrackRemoved?: (inboundTrack: ObservedInboundTrack, ctx: Context) => void;
163
+ private _onInboundTrackRemoved(inboundTrack: ObservedInboundTrack) {
164
+ this.onInboundTrackRemoved?.(inboundTrack, this.context);
165
+ }
166
+
167
+ public onOutboundTrackAdded?: (outboundTrack: ObservedOutboundTrack, ctx: Context) => void;
168
+ private _onOutboundTrackAdded(outboundTrack: ObservedOutboundTrack) {
169
+ this.onOutboundTrackAdded?.(outboundTrack, this.context);
170
+ }
171
+
172
+ public onOutboundTrackRemoved?: (outboundTrack: ObservedOutboundTrack, ctx: Context) => void;
173
+ private _onOutboundTrackRemoved(outboundTrack: ObservedOutboundTrack) {
174
+ this.onOutboundTrackRemoved?.(outboundTrack, this.context);
175
+ }
176
+
177
+ public onInboundRtpAdded?: (inboundRtp: ObservedInboundRtp, ctx: Context) => void;
178
+ private _onInboundRtpAdded(inboundRtp: ObservedInboundRtp) {
179
+ this.onInboundRtpAdded?.(inboundRtp, this.context);
180
+ }
181
+
182
+ public onInboundRtpRemoved?: (inboundRtp: ObservedInboundRtp, ctx: Context) => void;
183
+ private _onInboundRtpRemoved(inboundRtp: ObservedInboundRtp) {
184
+ this.onInboundRtpRemoved?.(inboundRtp, this.context);
185
+ }
186
+
187
+ public onOutboundRtpAdded?: (outboundRtp: ObservedOutboundRtp, ctx: Context) => void;
188
+ private _onOutboundRtpAdded(outboundRtp: ObservedOutboundRtp) {
189
+ this.onOutboundRtpAdded?.(outboundRtp, this.context);
190
+ }
191
+
192
+ public onOutboundRtpRemoved?: (outboundRtp: ObservedOutboundRtp, ctx: Context) => void;
193
+ private _onOutboundRtpRemoved(outboundRtp: ObservedOutboundRtp) {
194
+ this.onOutboundRtpRemoved?.(outboundRtp, this.context);
195
+ }
196
+
197
+ public onDataChannelAdded?: (dataChannel: ObservedDataChannel, ctx: Context) => void;
198
+ private _onDataChannelAdded(dataChannel: ObservedDataChannel) {
199
+ this.onDataChannelAdded?.(dataChannel, this.context);
200
+ }
201
+
202
+ public onDataChannelRemoved?: (dataChannel: ObservedDataChannel, ctx: Context) => void;
203
+ private _onDataChannelRemoved(dataChannel: ObservedDataChannel) {
204
+ this.onDataChannelRemoved?.(dataChannel, this.context);
205
+ }
206
+
207
+ public onAddedIceTransport?: (iceTransport: ObservedIceTransport, ctx: Context) => void;
208
+ private _onAddedIceTransport(iceTransport: ObservedIceTransport) {
209
+ this.onAddedIceTransport?.(iceTransport, this.context);
210
+ }
211
+
212
+ public onRemovedIceTransport?: (iceTransport: ObservedIceTransport, ctx: Context) => void;
213
+ private _onRemovedIceTransport(iceTransport: ObservedIceTransport) {
214
+ this.onRemovedIceTransport?.(iceTransport, this.context);
215
+ }
216
+
217
+ public onIceCandidateAdded?: (iceCandidate: ObservedIceCandidate, ctx: Context) => void;
218
+ private _onIceCandidateAdded(iceCandidate: ObservedIceCandidate) {
219
+ this.onIceCandidateAdded?.(iceCandidate, this.context);
220
+ }
221
+
222
+ public onIceCandidateRemoved?: (iceCandidate: ObservedIceCandidate, ctx: Context) => void;
223
+ private _onIceCandidateRemoved(iceCandidate: ObservedIceCandidate) {
224
+ this.onIceCandidateRemoved?.(iceCandidate, this.context);
225
+ }
226
+
227
+ public onAddedIceCandidatePair?: (candidatePair: ObservedIceCandidatePair, ctx: Context) => void;
228
+ private _onAddedIceCandidatePair(candidatePair: ObservedIceCandidatePair) {
229
+ this.onAddedIceCandidatePair?.(candidatePair, this.context);
230
+ }
231
+
232
+ public onRemovedIceCandidatePair?: (candidatePair: ObservedIceCandidatePair, ctx: Context) => void;
233
+ private _onRemovedIceCandidatePair(candidatePair: ObservedIceCandidatePair) {
234
+ this.onRemovedIceCandidatePair?.(candidatePair, this.context);
235
+ }
236
+
237
+ public onAddedMediaCodec?: (codec: ObservedCodec, ctx: Context) => void;
238
+ private _onAddedMediaCodec(codec: ObservedCodec) {
239
+ this.onAddedMediaCodec?.(codec, this.context);
240
+ }
241
+
242
+ public onRemovedMediaCodec?: (codec: ObservedCodec, ctx: Context) => void;
243
+ private _onRemovedMediaCodec(codec: ObservedCodec) {
244
+ this.onRemovedMediaCodec?.(codec, this.context);
245
+ }
246
+
247
+ public onAddedMediaPlayout?: (mediaPlayout: ObservedMediaPlayout, ctx: Context) => void;
248
+ private _onAddedMediaPlayout(mediaPlayout: ObservedMediaPlayout) {
249
+ this.onAddedMediaPlayout?.(mediaPlayout, this.context);
250
+ }
251
+
252
+ public onRemovedMediaPlayout?: (mediaPlayout: ObservedMediaPlayout, ctx: Context) => void;
253
+ private _onRemovedMediaPlayout(mediaPlayout: ObservedMediaPlayout) {
254
+ this.onRemovedMediaPlayout?.(mediaPlayout, this.context);
255
+ }
256
+
257
+ public onMediaSourceAdded?: (mediaSource: ObservedMediaSource, ctx: Context) => void;
258
+ private _onMediaSourceAdded(mediaSource: ObservedMediaSource) {
259
+ this.onMediaSourceAdded?.(mediaSource, this.context);
260
+ }
261
+
262
+ public onMediaSourceRemoved?: (mediaSource: ObservedMediaSource, ctx: Context) => void;
263
+ private _onMediaSourceRemoved(mediaSource: ObservedMediaSource) {
264
+ this.onMediaSourceRemoved?.(mediaSource, this.context);
265
+ }
266
+
267
+ public onClientIssue?: (issue: ClientIssue, ctx: Context) => void;
268
+ private _onClientIssue(issue: ClientIssue) {
269
+ this.onClientIssue?.(issue, this.context);
270
+ }
271
+
272
+ public onClientMetadata?: (metadata: ClientMetaData, ctx: Context) => void;
273
+ private _onClientMetadata(metadata: ClientMetaData) {
274
+ this.onClientMetadata?.(metadata, this.context);
275
+ }
276
+
277
+ public onClientExtensionStats?: (extensionStats: ExtensionStat, ctx: Context) => void;
278
+ private _onClientExtensionStats(extensionStats: ExtensionStat) {
279
+ this.onClientExtensionStats?.(extensionStats, this.context);
280
+ }
281
+
282
+ public onClientJoined?: (client: ObservedClient, ctx: Context) => void;
283
+ private _onClientJoined() {
284
+ this.onClientJoined?.(this.observedClient, this.context);
285
+ }
286
+
287
+ public onClientLeft?: (client: ObservedClient, ctx: Context) => void;
288
+ private _onClientLeft() {
289
+ this.onClientLeft?.(this.observedClient, this.context);
290
+ }
291
+
292
+ public onUserMediaError?: (error: string, observedClient: ObservedClient, ctx: Context) => void;
293
+ private _onUserMediaError(error: string) {
294
+ this.onUserMediaError?.(error, this.observedClient, this.context);
295
+ }
296
+
297
+ public onUsingTurn?: (client: ObservedClient, ctx: Context) => void;
298
+ private _onUsingTurn() {
299
+ this.onUsingTurn?.(this.observedClient, this.context);
300
+ }
301
+ }
@@ -16,6 +16,9 @@ export class ObservedDataChannel implements DataChannelStats {
16
16
  bytesReceived?: number | undefined;
17
17
  attachments?: Record<string, unknown> | undefined;
18
18
 
19
+ public addedAt?: number | undefined;
20
+ public removedAt?: number | undefined;
21
+
19
22
  public deltaBytesSent = 0;
20
23
  public deltaBytesReceived = 0;
21
24
  public deltaMessagesSent = 0;
@@ -8,7 +8,7 @@ export class ObservedIceCandidatePair implements IceCandidatePairStats {
8
8
  transportId?: string | undefined;
9
9
  localCandidateId?: string | undefined;
10
10
  remoteCandidateId?: string | undefined;
11
- state?: 'new' | 'inProgress' | 'failed' | 'succeeded' | undefined;
11
+ state?: 'new' | 'in-progress' | 'waiting' | 'failed' | 'succeeded' | undefined;
12
12
  nominated?: boolean | undefined;
13
13
  packetsSent?: number | undefined;
14
14
  packetsReceived?: number | undefined;
@@ -93,7 +93,7 @@ export class ObservedIceCandidatePair implements IceCandidatePairStats {
93
93
  this.transportId = stats.transportId;
94
94
  this.localCandidateId = stats.localCandidateId;
95
95
  this.remoteCandidateId = stats.remoteCandidateId;
96
- this.state = stats.state;
96
+ this.state = this._convertState(stats.state);
97
97
  this.nominated = stats.nominated;
98
98
  this.packetsSent = stats.packetsSent;
99
99
  this.packetsReceived = stats.packetsReceived;
@@ -115,4 +115,20 @@ export class ObservedIceCandidatePair implements IceCandidatePairStats {
115
115
  this.attachments = stats.attachments;
116
116
  }
117
117
 
118
+ private _convertState(state: string | undefined) {
119
+ switch (state) {
120
+ case 'new':
121
+ case 'in-progress':
122
+ case 'waiting':
123
+ case 'failed':
124
+ case 'succeeded':
125
+ return state;
126
+ case 'cancelled':
127
+ return 'failed';
128
+ case 'inprogress':
129
+ return 'in-progress';
130
+ default:
131
+ return undefined;
132
+ }
133
+ }
118
134
  }
@@ -16,6 +16,9 @@ export class ObservedInboundTrack implements InboundTrackSample {
16
16
 
17
17
  private _visited = false;
18
18
 
19
+ public addedAt?: number | undefined;
20
+ public removedAt?: number | undefined;
21
+
19
22
  attachments?: Record<string, unknown> | undefined;
20
23
 
21
24
  constructor(
@@ -15,6 +15,9 @@ export class ObservedOutboundTrack implements OutboundTrackSample {
15
15
  value: undefined,
16
16
  };
17
17
 
18
+ public addedAt?: number | undefined;
19
+ public removedAt?: number | undefined;
20
+
18
21
  attachments?: Record<string, unknown> | undefined;
19
22
 
20
23
  constructor(
@@ -280,6 +280,8 @@ export class ObservedPeerConnection extends EventEmitter {
280
280
 
281
281
  this.client.call.observer.observedTURN.removePeerConnection(this);
282
282
 
283
+ if (!this.closedAt) this.closedAt = Date.now();
284
+
283
285
  this.emit('close');
284
286
  }
285
287
 
@@ -302,7 +304,9 @@ export class ObservedPeerConnection extends EventEmitter {
302
304
  this.deltaReceivedVideoPackets = 0;
303
305
  this.deltaSentAudioBytes = 0;
304
306
  this.deltaSentVideoBytes = 0;
305
-
307
+ this.deltaTransportReceivedBytes = 0;
308
+ this.deltaTransportSentBytes = 0;
309
+
306
310
  this.sendingAudioBitrate = 0;
307
311
  this.sendingVideoBitrate = 0;
308
312
  this.receivingAudioBitrate = 0;
@@ -428,7 +432,10 @@ export class ObservedPeerConnection extends EventEmitter {
428
432
  }
429
433
  if (sample.peerConnectionTransports) {
430
434
  for (const peerConnectionTransport of sample.peerConnectionTransports) {
431
- this._updatePeerConnectionTransportStats(peerConnectionTransport);
435
+ const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
436
+
437
+ if (!observedTransport) continue;
438
+
432
439
  }
433
440
  }
434
441
  if (sample.remoteInboundRtps) {
@@ -496,16 +503,24 @@ export class ObservedPeerConnection extends EventEmitter {
496
503
  } else {
497
504
  this.currentJitter = undefined;
498
505
  }
499
-
500
- const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
501
- const selectedCandidatePairForTurn = selectedIceCandidatePairs.filter((pair) =>
502
- pair.getLocalCandidate()?.candidateType === 'relay' &&
503
- pair.getRemoteCandidate()?.url?.startsWith('turn:')
504
- );
505
506
  const wasUsingTURN = this.usingTURN;
507
+ const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
508
+ const selectedCandidatePairForTurn: ObservedIceCandidatePair[] = [];
509
+
510
+ this.usingTCP = false;
511
+ this.usingTURN = false;
506
512
 
507
- this.usingTCP = selectedIceCandidatePairs.some((pair) => pair.getLocalCandidate()?.protocol === 'tcp');
508
- this.usingTURN = 0 < selectedCandidatePairForTurn.length;
513
+ for (const selectedCandidatePair of selectedIceCandidatePairs) {
514
+ if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
515
+ this.usingTCP = true;
516
+ }
517
+ if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
518
+ selectedCandidatePairForTurn.push(selectedCandidatePair);
519
+ this.usingTURN = true;
520
+ }
521
+ this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
522
+ this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
523
+ }
509
524
 
510
525
  if (this.usingTURN) {
511
526
  if (!this.observedTurnServer) {
package/src/Observer.ts CHANGED
@@ -7,9 +7,10 @@ import { ObservedTURN } from './ObservedTURN';
7
7
  import { Detectors } from './detectors/Detectors';
8
8
  import { Updater } from './updaters/Updater';
9
9
  import { OnIntervalUpdater } from './updaters/OnIntervalUpdater';
10
- import { OnAllCallObserverUpdater } from './updaters/OnAllCallObserverUpdater_';
11
- import { OnAnyCallObserverUpdater } from './updaters/OnAnyCallObserverUpdater_';
12
- import { ObserverSummary } from './ObserverSummary';
10
+ import { OnAllCallObserverUpdater } from './updaters/OnAllCallObserverUpdater';
11
+ import { OnAnyCallObserverUpdater } from './updaters/OnAnyCallObserverUpdater';
12
+ import { ObserverEventMonitor } from './ObserverEventMonitor';
13
+ import { MediasoupRemoteTrackResolver } from './utils/MediasoupRemoteTrackResolver';
13
14
 
14
15
  const logger = createLogger('Observer');
15
16
 
@@ -24,11 +25,12 @@ export type ObserverEvents = {
24
25
  'close': [],
25
26
  }
26
27
 
27
- export type ObserverConfig = {
28
+ export type ObserverConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = {
28
29
  updatePolicy?: 'update-on-any-call-updated' | 'update-when-all-call-updated' | 'update-on-interval',
29
30
  updateIntervalInMs?: number,
30
31
  defaultCallUpdatePolicy?: ObservedCallSettings['updatePolicy'],
31
32
  defaultCallUpdateIntervalInMs?: number,
33
+ appData?: AppData,
32
34
  }
33
35
 
34
36
  export declare interface Observer {
@@ -38,7 +40,7 @@ export declare interface Observer {
38
40
  emit<U extends keyof ObserverEvents>(event: U, ...args: ObserverEvents[U]): boolean;
39
41
  }
40
42
 
41
- export class Observer extends EventEmitter {
43
+ export class Observer<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
42
44
  public readonly detectors: Detectors;
43
45
 
44
46
  public readonly observedTURN = new ObservedTURN();
@@ -55,6 +57,7 @@ export class Observer extends EventEmitter {
55
57
  public totalRttGtOrEq300Measurements = 0;
56
58
  public totalClientIssues = 0;
57
59
 
60
+ public numberOfClientsUsingTurn = 0;
58
61
  public numberOfClients = 0;
59
62
  public numberOfInboundRtpStreams = 0;
60
63
  public numberOfOutboundRtpStreams = 0;
@@ -67,9 +70,10 @@ export class Observer extends EventEmitter {
67
70
 
68
71
  private _timer?: ReturnType<typeof setInterval>;
69
72
 
70
- public constructor(public readonly config: ObserverConfig = {
73
+ public constructor(public readonly config: ObserverConfig<AppData> = {
71
74
  updatePolicy: 'update-when-all-call-updated',
72
75
  updateIntervalInMs: undefined,
76
+ appData: {} as AppData,
73
77
  }) {
74
78
  super();
75
79
  this.setMaxListeners(Infinity);
@@ -108,6 +112,10 @@ export class Observer extends EventEmitter {
108
112
  this.detectors = new Detectors();
109
113
  }
110
114
 
115
+ public get appData() {
116
+ return this.config.appData;
117
+ }
118
+
111
119
  public getObservedCall<T extends Record<string, unknown> = Record<string, unknown>>(callId: string): ObservedCall<T> | undefined {
112
120
  if (this.closed || !this.observedCalls.has(callId)) return;
113
121
 
@@ -124,12 +132,15 @@ export class Observer extends EventEmitter {
124
132
  settings.updatePolicy = this.config.defaultCallUpdatePolicy;
125
133
  settings.updateIntervalInMs = this.config.defaultCallUpdateIntervalInMs;
126
134
  }
127
-
128
135
  const observedCall = new ObservedCall(settings, this);
129
136
  const onCallUpdated = () => this._onObservedCallUpdated(observedCall);
130
137
 
131
138
  if (this.observedCalls.has(observedCall.callId)) throw new Error(`Observed Call with id ${observedCall.callId} already exists`);
132
139
 
140
+ if (settings.remoteTrackResolvePolicy === 'mediasoup-sfu') {
141
+ observedCall.remoteTrackResolver = new MediasoupRemoteTrackResolver(observedCall);
142
+ }
143
+
133
144
  observedCall.once('close', () => {
134
145
  this.observedCalls.delete(observedCall.callId);
135
146
  observedCall.off('update', onCallUpdated);
@@ -186,6 +197,7 @@ export class Observer extends EventEmitter {
186
197
  this.numberOfPeerConnections = 0;
187
198
  this.numberOfDataChannels = 0;
188
199
  this.numberOfClients = 0;
200
+ this.numberOfClientsUsingTurn = 0;
189
201
 
190
202
  for (const call of this.observedCalls.values()) {
191
203
  this.numberOfInboundRtpStreams += call.numberOfInboundRtpStreams;
@@ -193,6 +205,7 @@ export class Observer extends EventEmitter {
193
205
  this.numberOfPeerConnections += call.numberOfPeerConnections;
194
206
  this.numberOfDataChannels += call.numberOfDataChannels;
195
207
  this.numberOfClients += call.numberOfClients;
208
+ this.numberOfClientsUsingTurn += call.clientsUsedTurn.size;
196
209
  }
197
210
 
198
211
  this.observedTURN.update();
@@ -208,29 +221,34 @@ export class Observer extends EventEmitter {
208
221
  this.totalClientIssues += call.deltaNumberOfIssues;
209
222
  }
210
223
 
211
- public resetSummaryMetrics() {
212
- this.totalAddedCall = 0;
213
- this.totalRemovedCall = 0;
214
- this.totalRttLt50Measurements = 0;
215
- this.totalRttLt150Measurements = 0;
216
- this.totalRttLt300Measurements = 0;
217
- this.totalRttGtOrEq300Measurements = 0;
218
- this.totalClientIssues = 0;
224
+ public createEventMonitor<CTX = unknown>(ctx?: CTX): ObserverEventMonitor<CTX> {
225
+ return new ObserverEventMonitor<CTX>(this, ctx ?? {} as CTX);
219
226
  }
220
227
 
221
- public createSummary(): ObserverSummary {
222
- return {
223
- totalAddedCall: this.totalAddedCall,
224
- totalRemovedCall: this.totalRemovedCall,
225
- totalRttLt50Measurements: this.totalRttLt50Measurements,
226
- totalRttLt150Measurements: this.totalRttLt150Measurements,
227
- totalRttLt300Measurements: this.totalRttLt300Measurements,
228
- totalRttGtOrEq300Measurements: this.totalRttGtOrEq300Measurements,
229
-
230
- totalClientIssues: this.totalClientIssues,
231
- currentActiveCalls: this.observedCalls.size,
232
-
233
- };
234
- }
228
+ // public resetSummaryMetrics() {
229
+ // this.totalAddedCall = 0;
230
+ // this.totalRemovedCall = 0;
231
+ // this.totalRttLt50Measurements = 0;
232
+ // this.totalRttLt150Measurements = 0;
233
+ // this.totalRttLt300Measurements = 0;
234
+ // this.totalRttGtOrEq300Measurements = 0;
235
+ // this.totalClientIssues = 0;
236
+ // }
237
+
238
+ // public createSummary(): ObserverSummary {
239
+ // return {
240
+ // totalAddedCall: this.totalAddedCall,
241
+ // totalRemovedCall: this.totalRemovedCall,
242
+ // totalRttLt50Measurements: this.totalRttLt50Measurements,
243
+ // totalRttLt150Measurements: this.totalRttLt150Measurements,
244
+ // totalRttLt300Measurements: this.totalRttLt300Measurements,
245
+ // totalRttGtOrEq300Measurements: this.totalRttGtOrEq300Measurements,
246
+
247
+ // totalClientIssues: this.totalClientIssues,
248
+ // currentActiveCalls: this.observedCalls.size,
249
+ // currentNumberOfClients: this.numberOfClients,
250
+ // currentNumberOfClientsUsingTURN: this.numberOfClientsUsedTurn,
251
+ // };
252
+ // }
235
253
 
236
254
  }