@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-c9e7581.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 (140) hide show
  1. package/lib/ObservedCall.d.ts +43 -7
  2. package/lib/ObservedCall.d.ts.map +1 -1
  3. package/lib/ObservedCall.js +142 -14
  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/ObservedCallSummary.d.ts +18 -0
  8. package/lib/ObservedCallSummary.d.ts.map +1 -0
  9. package/lib/ObservedClient.d.ts +71 -11
  10. package/lib/ObservedClient.d.ts.map +1 -1
  11. package/lib/ObservedClient.js +509 -72
  12. package/lib/ObservedClientEventMonitor.d.ts +89 -0
  13. package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
  14. package/lib/ObservedClientEventMonitor.js +247 -0
  15. package/lib/ObservedClientSummary.d.ts +23 -0
  16. package/lib/ObservedClientSummary.d.ts.map +1 -0
  17. package/lib/ObservedClientSummary.js +2 -0
  18. package/lib/ObservedDataChannel.d.ts +6 -0
  19. package/lib/ObservedDataChannel.d.ts.map +1 -1
  20. package/lib/ObservedDataChannel.js +30 -0
  21. package/lib/ObservedIceCandidatePair.d.ts +6 -1
  22. package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
  23. package/lib/ObservedIceCandidatePair.js +45 -1
  24. package/lib/ObservedIceTransport.d.ts +4 -0
  25. package/lib/ObservedIceTransport.d.ts.map +1 -1
  26. package/lib/ObservedIceTransport.js +28 -0
  27. package/lib/ObservedInboundTrack.d.ts +3 -0
  28. package/lib/ObservedInboundTrack.d.ts.map +1 -1
  29. package/lib/ObservedInboundTrack.js +3 -0
  30. package/lib/ObservedOutboundTrack.d.ts +3 -0
  31. package/lib/ObservedOutboundTrack.d.ts.map +1 -1
  32. package/lib/ObservedOutboundTrack.js +3 -0
  33. package/lib/ObservedPeerConnection.d.ts +36 -2
  34. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  35. package/lib/ObservedPeerConnection.js +184 -29
  36. package/lib/ObservedTURN.d.ts +31 -0
  37. package/lib/ObservedTURN.d.ts.map +1 -0
  38. package/lib/ObservedTURN.js +58 -0
  39. package/lib/ObservedTurnServer.d.ts +25 -0
  40. package/lib/ObservedTurnServer.d.ts.map +1 -0
  41. package/lib/ObservedTurnServer.js +59 -0
  42. package/lib/Observer.d.ts +43 -22
  43. package/lib/Observer.d.ts.map +1 -1
  44. package/lib/Observer.js +126 -40
  45. package/lib/ObserverEventMonitor.d.ts +138 -0
  46. package/lib/ObserverEventMonitor.d.ts.map +1 -0
  47. package/lib/ObserverEventMonitor.js +433 -0
  48. package/lib/ObserverSummary.d.ts +13 -0
  49. package/lib/ObserverSummary.d.ts.map +1 -0
  50. package/lib/ObserverSummary.js +2 -0
  51. package/lib/common/utils.d.ts +2 -1
  52. package/lib/common/utils.d.ts.map +1 -1
  53. package/lib/common/utils.js +11 -3
  54. package/lib/index.d.ts +6 -0
  55. package/lib/index.d.ts.map +1 -1
  56. package/lib/index.js +9 -1
  57. package/lib/schema/ClientEventTypes.d.ts +228 -0
  58. package/lib/schema/ClientEventTypes.d.ts.map +1 -0
  59. package/lib/schema/ClientEventTypes.js +41 -0
  60. package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
  61. package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
  62. package/lib/schema/ClientMetaTypes.js +16 -0
  63. package/lib/schema/ClientSample.d.ts +1 -1
  64. package/lib/schema/ClientSample.d.ts.map +1 -1
  65. package/lib/updaters/CallUpdater.d.ts.map +1 -0
  66. package/lib/updaters/CallUpdater.js +2 -0
  67. package/lib/updaters/ObserverUpdater.d.ts +5 -0
  68. package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
  69. package/lib/updaters/ObserverUpdater.js +2 -0
  70. package/lib/updaters/OnAllCallObserverUpdater.d.ts +15 -0
  71. package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
  72. package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
  73. package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
  74. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
  75. package/lib/updaters/OnAllClientCallUpdater.js +53 -0
  76. package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
  77. package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
  78. package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
  79. package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
  80. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
  81. package/lib/updaters/OnAnyClientCallUpdater.js +36 -0
  82. package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
  83. package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
  84. package/lib/updaters/OnIntervalUpdater.js +17 -0
  85. package/lib/updaters/Updater.d.ts +6 -0
  86. package/lib/updaters/Updater.d.ts.map +1 -0
  87. package/lib/updaters/Updater.js +2 -0
  88. package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
  89. package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
  90. package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
  91. package/package.json +1 -1
  92. package/src/ObservedCall.ts +222 -17
  93. package/src/ObservedCallEventMonitor.ts +392 -0
  94. package/src/ObservedCallSummary.ts +22 -0
  95. package/src/ObservedClient.ts +608 -79
  96. package/src/ObservedClientEventMonitor.ts +301 -0
  97. package/src/ObservedClientSummary.ts +24 -0
  98. package/src/ObservedDataChannel.ts +32 -0
  99. package/src/ObservedIceCandidatePair.ts +44 -2
  100. package/src/ObservedIceTransport.ts +29 -0
  101. package/src/ObservedInboundTrack.ts +5 -0
  102. package/src/ObservedOutboundTrack.ts +5 -0
  103. package/src/ObservedPeerConnection.ts +219 -46
  104. package/src/ObservedTURN.ts +86 -0
  105. package/src/ObservedTurnServer.ts +72 -0
  106. package/src/Observer.ts +179 -64
  107. package/src/ObserverEventMonitor.ts +551 -0
  108. package/src/ObserverSummary.ts +15 -0
  109. package/src/common/utils.ts +12 -2
  110. package/src/index.ts +6 -1
  111. package/src/schema/ClientEventTypes.ts +280 -0
  112. package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
  113. package/src/schema/ClientSample.ts +1 -1
  114. package/src/updaters/ObserverUpdater.ts +5 -0
  115. package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
  116. package/src/updaters/OnAllClientCallUpdater.ts +61 -0
  117. package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
  118. package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
  119. package/src/updaters/OnIntervalUpdater.ts +19 -0
  120. package/src/updaters/Updater.ts +5 -0
  121. package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
  122. package/tsconfig.json +1 -1
  123. package/lib/schema/eventTypes.d.ts +0 -33
  124. package/lib/schema/eventTypes.d.ts.map +0 -1
  125. package/lib/schema/eventTypes.js +0 -38
  126. package/lib/schema/metaTypes.d.ts.map +0 -1
  127. package/lib/schema/metaTypes.js +0 -16
  128. package/lib/utils/CallUpdater.d.ts.map +0 -1
  129. package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
  130. package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
  131. package/lib/utils/OnAllClientCallUpdater.js +0 -58
  132. package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
  133. package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
  134. package/lib/utils/onAnyClientCallUpdater.js +0 -51
  135. package/src/schema/eventTypes.ts +0 -36
  136. package/src/utils/OnAllClientCallUpdater.ts +0 -68
  137. package/src/utils/onAnyClientCallUpdater.ts +0 -59
  138. /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
  139. /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
  140. /package/src/{utils → updaters}/CallUpdater.ts +0 -0
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnAnyClientCallUpdater = void 0;
4
+ class OnAnyClientCallUpdater {
5
+ _observedCall;
6
+ name = 'OnAnyClientCallUpdater';
7
+ description = 'Call the update() method of the ObservedCall when any of the client has been updated';
8
+ closed = false;
9
+ constructor(_observedCall) {
10
+ this._observedCall = _observedCall;
11
+ this._onNewObservedClient = this._onNewObservedClient.bind(this);
12
+ this._observedCall.once('close', () => {
13
+ this._observedCall.off('newclient', this._onNewObservedClient);
14
+ });
15
+ this._observedCall.on('newclient', this._onNewObservedClient);
16
+ }
17
+ close() {
18
+ if (this.closed)
19
+ return;
20
+ this.closed = true;
21
+ }
22
+ _onNewObservedClient(observedClient) {
23
+ if (this.closed)
24
+ return;
25
+ const onUpdate = () => {
26
+ if (this.closed)
27
+ return;
28
+ this._observedCall.update();
29
+ };
30
+ observedClient.once('close', () => {
31
+ observedClient.off('update', onUpdate);
32
+ });
33
+ observedClient.on('update', onUpdate);
34
+ }
35
+ }
36
+ exports.OnAnyClientCallUpdater = OnAnyClientCallUpdater;
@@ -0,0 +1,10 @@
1
+ import { Updater } from './Updater';
2
+ export declare class OnIntervalUpdater implements Updater {
3
+ private readonly _update;
4
+ readonly name = "OnIntervalUpdater";
5
+ readonly description = "Call the update() method given in the constructor once the interval elapsed";
6
+ timer: ReturnType<typeof setInterval>;
7
+ constructor(intervalInMs: number, _update: () => void);
8
+ close(): void;
9
+ }
10
+ //# sourceMappingURL=OnIntervalUpdater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OnIntervalUpdater.d.ts","sourceRoot":"","sources":["../../src/updaters/OnIntervalUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,qBAAa,iBAAkB,YAAW,OAAO;IAQ/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPzB,QAAQ,CAAC,IAAI,uBAAuB;IACpC,QAAQ,CAAC,WAAW,iFAAiF;IAE9F,KAAK,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;gBAG5C,YAAY,EAAE,MAAM,EACH,OAAO,EAAE,MAAM,IAAI;IAK9B,KAAK,IAAI,IAAI;CAGpB"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OnIntervalUpdater = void 0;
4
+ class OnIntervalUpdater {
5
+ _update;
6
+ name = 'OnIntervalUpdater';
7
+ description = 'Call the update() method given in the constructor once the interval elapsed';
8
+ timer;
9
+ constructor(intervalInMs, _update) {
10
+ this._update = _update;
11
+ this.timer = setInterval(() => this._update(), intervalInMs);
12
+ }
13
+ close() {
14
+ clearInterval(this.timer);
15
+ }
16
+ }
17
+ exports.OnIntervalUpdater = OnIntervalUpdater;
@@ -0,0 +1,6 @@
1
+ export interface Updater {
2
+ readonly name: string;
3
+ readonly description?: string;
4
+ close(): void;
5
+ }
6
+ //# sourceMappingURL=Updater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Updater.d.ts","sourceRoot":"","sources":["../../src/updaters/Updater.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,KAAK,IAAI,IAAI,CAAC;CACd"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,25 @@
1
+ import { ObservedCall } from '../ObservedCall';
2
+ import { ObservedCallEventMonitor } from '../ObservedCallEventMonitor';
3
+ import { ObservedInboundTrack } from '../ObservedInboundTrack';
4
+ import { ObservedOutboundTrack } from '../ObservedOutboundTrack';
5
+ import { RemoteTrackResolver } from './RemoteTrackResolver';
6
+ export declare class MediasoupRemoteTrackResolver implements RemoteTrackResolver {
7
+ readonly observedCall: ObservedCall;
8
+ readonly eventMonitor: ObservedCallEventMonitor<{}>;
9
+ private _consumerIdToProducerId;
10
+ private _producerIdToOutboundTrack;
11
+ private _consumerIdToInboundTrack;
12
+ private _inboundTrackToConsumerId;
13
+ private _producerIdToConsumerIds;
14
+ private _outboundTrackToProducerId;
15
+ constructor(observedCall: ObservedCall);
16
+ resolveRemoteOutboundTrack(inboundTrack: ObservedInboundTrack): ObservedOutboundTrack | undefined;
17
+ resolveRemoteInboundTracks(outboundTrack: ObservedOutboundTrack): ObservedInboundTrack[] | undefined;
18
+ private _addInboundTrack;
19
+ private _removeInboundTrack;
20
+ private _addOutboundTrack;
21
+ private _removeOutboundTrack;
22
+ private _getInboundTrackAttachments;
23
+ private _getOutboundTrackAttachments;
24
+ }
25
+ //# sourceMappingURL=MediasoupRemoteTrackResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediasoupRemoteTrackResolver.d.ts","sourceRoot":"","sources":["../../src/utils/MediasoupRemoteTrackResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,4BAA6B,YAAW,mBAAmB;aAetD,YAAY,EAAE,YAAY;IAd3C,SAAgB,YAAY,EAAE,wBAAwB,CAAC,EAEtD,CAAC,CAAC;IAEH,OAAO,CAAC,uBAAuB,CAA6B;IAC5D,OAAO,CAAC,0BAA0B,CAA4C;IAC9E,OAAO,CAAC,yBAAyB,CAA2C;IAG5E,OAAO,CAAC,yBAAyB,CAA6B;IAC9D,OAAO,CAAC,wBAAwB,CAA+B;IAC/D,OAAO,CAAC,0BAA0B,CAA6B;gBAG9C,YAAY,EAAE,YAAY;IAcpC,0BAA0B,CAAC,YAAY,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,SAAS;IAYjG,0BAA0B,CAAC,aAAa,EAAE,qBAAqB,GAAG,oBAAoB,EAAE,GAAG,SAAS;IAe3G,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,2BAA2B;IAcnC,OAAO,CAAC,4BAA4B;CAWpC"}
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MediasoupRemoteTrackResolver = void 0;
4
+ class MediasoupRemoteTrackResolver {
5
+ observedCall;
6
+ eventMonitor;
7
+ _consumerIdToProducerId = new Map();
8
+ _producerIdToOutboundTrack = new Map();
9
+ _consumerIdToInboundTrack = new Map();
10
+ // private _producerIdToOutboundTrack = new Map<string, ObservedOutboundTrack>();
11
+ _inboundTrackToConsumerId = new Map();
12
+ _producerIdToConsumerIds = new Map();
13
+ _outboundTrackToProducerId = new Map();
14
+ constructor(observedCall) {
15
+ this.observedCall = observedCall;
16
+ this.eventMonitor = this.observedCall.createEventMonitor({});
17
+ this.eventMonitor.onInboundTrackAdded = this._addInboundTrack.bind(this);
18
+ this.eventMonitor.onInboundTrackRemoved = this._removeInboundTrack.bind(this);
19
+ this.eventMonitor.onOutboundTrackAdded = this._addOutboundTrack.bind(this);
20
+ this.eventMonitor.onOutboundTrackRemoved = this._removeOutboundTrack.bind(this);
21
+ // this.eventMonitor.onClientEvent = (client, event) => {
22
+ // };
23
+ }
24
+ resolveRemoteOutboundTrack(inboundTrack) {
25
+ const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
26
+ if (!consumerId)
27
+ return;
28
+ const producerId = this._consumerIdToProducerId.get(consumerId);
29
+ if (!producerId)
30
+ return;
31
+ return this._producerIdToOutboundTrack.get(producerId);
32
+ }
33
+ resolveRemoteInboundTracks(outboundTrack) {
34
+ const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
35
+ if (!producerId)
36
+ return;
37
+ const consumerIds = this._producerIdToConsumerIds.get(producerId);
38
+ if (!consumerIds)
39
+ return;
40
+ return consumerIds
41
+ .map((consumerId) => this._consumerIdToInboundTrack.get(consumerId))
42
+ .filter((inboundTrack) => Boolean(inboundTrack));
43
+ }
44
+ _addInboundTrack(inboundTrack) {
45
+ const attachments = this._getInboundTrackAttachments(inboundTrack);
46
+ if (!attachments)
47
+ return;
48
+ const { producerId, consumerId } = attachments;
49
+ this._inboundTrackToConsumerId.set(inboundTrack.id, consumerId);
50
+ this._consumerIdToProducerId.set(consumerId, producerId);
51
+ this._consumerIdToInboundTrack.set(consumerId, inboundTrack);
52
+ let producerConsumers = this._producerIdToConsumerIds.get(producerId);
53
+ if (!producerConsumers) {
54
+ producerConsumers = [];
55
+ this._producerIdToConsumerIds.set(producerId, producerConsumers);
56
+ }
57
+ producerConsumers.push(consumerId);
58
+ }
59
+ _removeInboundTrack(inboundTrack) {
60
+ const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
61
+ if (!consumerId)
62
+ return;
63
+ this._inboundTrackToConsumerId.delete(inboundTrack.id);
64
+ this._consumerIdToProducerId.delete(consumerId);
65
+ this._consumerIdToInboundTrack.delete(consumerId);
66
+ const producerConsumers = this._producerIdToConsumerIds.get(consumerId);
67
+ if (!producerConsumers)
68
+ return;
69
+ const filteredProducerConsumers = producerConsumers.filter((id) => id !== consumerId);
70
+ if (filteredProducerConsumers.length === 0) {
71
+ this._producerIdToConsumerIds.delete(consumerId);
72
+ }
73
+ else {
74
+ this._producerIdToConsumerIds.set(consumerId, filteredProducerConsumers);
75
+ }
76
+ }
77
+ _addOutboundTrack(outboundTrack) {
78
+ const attachments = this._getOutboundTrackAttachments(outboundTrack);
79
+ if (!attachments)
80
+ return;
81
+ const { producerId, } = attachments;
82
+ this._producerIdToOutboundTrack.set(producerId, outboundTrack);
83
+ this._outboundTrackToProducerId.set(outboundTrack.id, producerId);
84
+ }
85
+ _removeOutboundTrack(outboundTrack) {
86
+ const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
87
+ if (!producerId)
88
+ return;
89
+ this._producerIdToOutboundTrack.delete(producerId);
90
+ this._outboundTrackToProducerId.delete(outboundTrack.id);
91
+ }
92
+ _getInboundTrackAttachments(inboundTrack) {
93
+ const { producerId, consumerId } = inboundTrack.attachments ?? {};
94
+ if (!producerId || !consumerId || typeof producerId !== 'string' || typeof consumerId !== 'string')
95
+ return;
96
+ return {
97
+ producerId,
98
+ consumerId
99
+ };
100
+ }
101
+ _getOutboundTrackAttachments(outboundTrack) {
102
+ const { producerId, } = outboundTrack.attachments ?? {};
103
+ if (!producerId || typeof producerId !== 'string')
104
+ return;
105
+ return {
106
+ producerId,
107
+ };
108
+ }
109
+ }
110
+ exports.MediasoupRemoteTrackResolver = MediasoupRemoteTrackResolver;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@observertc/observer-js",
3
- "version": "1.0.1-c3edea3.0",
3
+ "version": "1.0.1-c9e7581.0",
4
4
  "description": "Server Side NodeJS Library for processing ObserveRTC Samples",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -6,15 +6,18 @@ import { CalculatedScore } from './scores/CalculatedScore';
6
6
  import { DefaultCallScoreCalculator } from './scores/DefaultCallScoreCalculator';
7
7
  import { Detectors } from './detectors/Detectors';
8
8
  import { RemoteTrackResolver } from './utils/RemoteTrackResolver';
9
- import { CallUpdater } from './utils/CallUpdater';
10
- import { OnAllClientCallUpdater } from './utils/OnAllClientCallUpdater';
11
- import { OnAnyClientCallUpdater } from './utils/onAnyClientCallUpdater';
9
+ import { OnAllClientCallUpdater } from './updaters/OnAllClientCallUpdater';
10
+ import { Updater } from './updaters/Updater';
11
+ import { OnIntervalUpdater } from './updaters/OnIntervalUpdater';
12
+ import { OnAnyClientCallUpdater } from './updaters/OnAnyClientCallUpdater';
13
+ import { ObservedCallEventMonitor } from './ObservedCallEventMonitor';
12
14
 
13
15
  export type ObservedCallSettings<AppData extends Record<string, unknown> = Record<string, unknown>> = {
14
16
  callId: string;
15
17
  appData?: AppData;
16
18
  remoteTrackResolvePolicy?: 'p2p' | 'mediasoup-sfu',
17
- callUpdaterPolicy?: 'onAnyClientUpdate' | 'onAllClientsUpdate',
19
+ updatePolicy?: 'update-on-any-client-updated' | 'update-when-all-client-updated' | 'update-on-interval',
20
+ updateIntervalInMs?: number,
18
21
  };
19
22
 
20
23
  export type ObservedCallEvents = {
@@ -34,20 +37,62 @@ export declare interface ObservedCall {
34
37
 
35
38
  export class ObservedCall<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
36
39
  public readonly detectors: Detectors;
40
+ public updater?: Updater;
41
+ public scoreCalculator: ScoreCalculator;
37
42
  public readonly callId: string;
38
43
  public readonly observedClients = new Map<string, ObservedClient>();
44
+ public readonly clientsUsedTurn = new Set<string>();
39
45
  public readonly calculatedScore: CalculatedScore = {
40
46
  weight: 1,
41
47
  value: undefined,
42
48
  };
43
49
  public remoteTrackResolver?: RemoteTrackResolver;
44
- public callUpdater?: CallUpdater;
45
50
 
46
- public appData?: AppData;
51
+ public totalAddedClients = 0;
52
+ public totalRemovedClients = 0;
53
+
54
+ public totalClientsReceivedAudioBytes = 0;
55
+ public totalClientsReceivedVideoBytes = 0;
56
+ public totalClientsReceivedDataChannelBytes = 0;
57
+ public totalClientsReceivedBytes = 0;
58
+
59
+ public totalClientsSentAudioBytes = 0;
60
+ public totalClientsSentDataChannelBytes = 0;
61
+ public totalClientsSentVideoBytes = 0;
62
+ public totalClientsSentBytes = 0;
63
+
64
+ public totalRttLt50Measurements = 0;
65
+ public totalRttLt150Measurements = 0;
66
+ public totalRttLt300Measurements = 0;
67
+ public totalRttGtOrEq300Measurements = 0;
68
+
69
+ public numberOfIssues = 0;
70
+ public numberOfPeerConnections = 0;
71
+ public numberOfInboundRtpStreams = 0;
72
+ public numberOfOutboundRtpStreams = 0;
73
+ public numberOfDataChannels = 0;
74
+
75
+ public maxNumberOfClients = 0;
76
+ public deltaNumberOfIssues = 0;
77
+
78
+ public deltaRttLt50Measurements = 0;
79
+ public deltaRttLt150Measurements = 0;
80
+ public deltaRttLt300Measurements = 0;
81
+ public deltaRttGtOrEq300Measurements = 0;
82
+
83
+ public appData: AppData;
47
84
  public closed = false;
48
- public started?: number;
49
- public ended?: number;
50
- public scoreCalculator: ScoreCalculator;
85
+ public startedAt?: number;
86
+ public endedAt?: number;
87
+ public closedAt?: number;
88
+
89
+ private _callStartedEvent: {
90
+ emitted: boolean,
91
+ timer?: ReturnType<typeof setTimeout>,
92
+ };
93
+ private _callEndedEvent: {
94
+ emitted: boolean
95
+ };
51
96
 
52
97
  public constructor(
53
98
  settings: ObservedCallSettings<AppData>,
@@ -57,16 +102,30 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
57
102
  this.setMaxListeners(Infinity);
58
103
 
59
104
  this.callId = settings.callId;
60
- this.appData = settings.appData;
105
+ this.appData = settings.appData ?? {} as AppData;
61
106
  this.scoreCalculator = new DefaultCallScoreCalculator(this);
62
107
  this.detectors = new Detectors();
63
108
 
64
- switch (settings.callUpdaterPolicy) {
65
- case 'onAllClientsUpdate':
66
- this.callUpdater = new OnAllClientCallUpdater(this);
109
+ if (settings.updateIntervalInMs) {
110
+ if (settings.updatePolicy !== 'update-on-interval') {
111
+ throw new Error('updatePolicy must be update-on-interval if updateIntervalInMs is set in config');
112
+ }
113
+ }
114
+ switch (settings.updatePolicy) {
115
+ case 'update-on-any-client-updated':
116
+ this.updater = new OnAllClientCallUpdater(this);
67
117
  break;
68
- case 'onAnyClientUpdate':
69
- this.callUpdater = new OnAnyClientCallUpdater(this);
118
+ case 'update-when-all-client-updated':
119
+ this.updater = new OnAnyClientCallUpdater(this);
120
+ break;
121
+ case 'update-on-interval':
122
+ if (!settings.updateIntervalInMs) {
123
+ throw new Error('updateIntervalInMs setting in config must be set if updatePolicy is update-on-interval');
124
+ }
125
+ this.updater = new OnIntervalUpdater(
126
+ settings.updateIntervalInMs,
127
+ this.update.bind(this),
128
+ );
70
129
  break;
71
130
  }
72
131
 
@@ -74,6 +133,17 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
74
133
  case 'mediasoup-sfu':
75
134
  break;
76
135
  }
136
+
137
+ this._callStartedEvent = {
138
+ emitted: false,
139
+ };
140
+ this._callEndedEvent = {
141
+ emitted: false,
142
+ };
143
+ }
144
+
145
+ public get numberOfClients() {
146
+ return this.observedClients.size;
77
147
  }
78
148
 
79
149
  public get score() {
@@ -82,10 +152,25 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
82
152
 
83
153
  public close() {
84
154
  if (this.closed) return;
155
+ this.update(); // last update before closing
85
156
  this.closed = true;
86
157
 
87
- [ ...this.observedClients.values() ].forEach((client) => client.close());
158
+ this.updater?.close();
159
+
160
+ let minSampleTimestamps: number | undefined;
161
+ let maxSampleTimestamps: number | undefined;
162
+
163
+ for (const client of this.observedClients.values()) {
164
+ client.close();
165
+
166
+ if (client.joinedAt) minSampleTimestamps = Math.min(minSampleTimestamps ?? client.joinedAt, client.joinedAt);
167
+ if (client.leftAt) maxSampleTimestamps = Math.max(maxSampleTimestamps ?? client.leftAt, client.leftAt);
168
+ }
169
+
170
+ if (this.startedAt === undefined) this.startedAt = minSampleTimestamps;
171
+ if (this.endedAt === undefined) this.endedAt = maxSampleTimestamps;
88
172
 
173
+ this.closedAt = Date.now();
89
174
  this.emit('close');
90
175
  }
91
176
 
@@ -101,19 +186,28 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
101
186
 
102
187
  const result = new ObservedClient<ClientAppData>(settings, this);
103
188
  const wasEmpty = this.observedClients.size === 0;
104
- const onUpdate = () => this.callUpdater?.onClientUpdate(result);
189
+ const onUpdate = () => this._onClientUpdate(result);
190
+ const joined = () => this._clientJoined(result);
191
+ const left = () => this._clientLeft(result);
105
192
 
106
193
  result.once('close', () => {
107
194
  result.off('update', onUpdate);
195
+ result.off('joined', joined);
196
+ result.off('left', left);
108
197
  this.observedClients.delete(settings.clientId);
109
198
 
110
199
  if (this.observedClients.size === 0) {
111
200
  this.emit('empty');
112
201
  }
202
+ ++this.totalRemovedClients;
113
203
  });
114
204
  result.on('update', onUpdate);
205
+ result.on('joined', joined);
206
+ result.on('left', left);
207
+ ++this.totalAddedClients;
115
208
 
116
209
  this.observedClients.set(settings.clientId, result);
210
+ this.maxNumberOfClients = Math.max(this.maxNumberOfClients, this.observedClients.size);
117
211
 
118
212
  this.emit('newclient', result);
119
213
 
@@ -124,10 +218,121 @@ export class ObservedCall<AppData extends Record<string, unknown> = Record<strin
124
218
  return result;
125
219
  }
126
220
 
221
+ public createEventMonitor<CTX>(context: CTX): ObservedCallEventMonitor<CTX> {
222
+ return new ObservedCallEventMonitor(this, context);
223
+ }
224
+
127
225
  public update() {
226
+ if (this.closed) return;
227
+
228
+ this.numberOfInboundRtpStreams = 0;
229
+ this.numberOfOutboundRtpStreams = 0;
230
+ this.numberOfPeerConnections = 0;
231
+ this.numberOfDataChannels = 0;
232
+
233
+ for (const client of this.observedClients.values()) {
234
+ this.numberOfInboundRtpStreams += client.numberOfInboundRtpStreams;
235
+ this.numberOfOutboundRtpStreams += client.numberOfOutboundRtpStreams;
236
+ this.numberOfPeerConnections += client.numberOfPeerConnections;
237
+ this.numberOfDataChannels += client.numberOfDataChannels;
238
+ }
239
+
128
240
  this.detectors.update();
129
241
  this.scoreCalculator.update();
130
242
 
131
243
  this.emit('update');
244
+
245
+ this.deltaNumberOfIssues = 0;
246
+ this.deltaRttLt50Measurements = 0;
247
+ this.deltaRttLt150Measurements = 0;
248
+ this.deltaRttLt300Measurements = 0;
249
+ this.deltaRttGtOrEq300Measurements = 0;
250
+ }
251
+
252
+ private _onClientUpdate(client: ObservedClient) {
253
+ this.totalClientsReceivedAudioBytes += client.deltaReceivedAudioBytes;
254
+ this.totalClientsReceivedVideoBytes += client.deltaReceivedVideoBytes;
255
+ this.totalClientsReceivedDataChannelBytes += client.deltaDataChannelBytesReceived;
256
+ this.totalClientsReceivedBytes += client.deltaTransportReceivedBytes;
257
+ this.totalClientsSentAudioBytes += client.deltaSentAudioBytes;
258
+ this.totalClientsSentVideoBytes += client.deltaSentVideoBytes;
259
+ this.totalClientsSentDataChannelBytes += client.deltaDataChannelBytesSent;
260
+ this.totalClientsSentBytes += client.deltaTransportSentBytes;
261
+
262
+ this.deltaRttLt50Measurements += client.deltaRttLt50Measurements;
263
+ this.deltaRttLt150Measurements += client.deltaRttLt150Measurements;
264
+ this.deltaRttLt300Measurements += client.deltaRttLt300Measurements;
265
+ this.deltaRttGtOrEq300Measurements += client.deltaRttGtOrEq300Measurements;
266
+
267
+ this.totalRttLt50Measurements += client.deltaRttLt50Measurements;
268
+ this.totalRttLt150Measurements += client.deltaRttLt150Measurements;
269
+ this.totalRttLt300Measurements += client.deltaRttLt300Measurements;
270
+ this.totalRttGtOrEq300Measurements += client.deltaRttGtOrEq300Measurements;
271
+
272
+ this.deltaNumberOfIssues += client.deltaNumberOfIssues;
273
+ this.numberOfIssues += client.deltaNumberOfIssues;
274
+
275
+ if (client.usingTURN) {
276
+ this.clientsUsedTurn.add(client.clientId);
277
+ }
132
278
  }
279
+
280
+ private _clientJoined(client: ObservedClient) {
281
+ if (!client.joinedAt) return;
282
+
283
+ this.startedAt = Math.min(this.startedAt ?? client.joinedAt, client.joinedAt);
284
+ }
285
+
286
+ private _clientLeft(client: ObservedClient) {
287
+ if (!client.leftAt) return;
288
+
289
+ this.endedAt = Math.max(this.endedAt ?? client.leftAt, client.leftAt);
290
+ }
291
+
292
+ // public resetSummaryMetrics() {
293
+ // this.totalAddedClients = 0;
294
+ // this.totalRemovedClients = 0;
295
+
296
+ // this.totalClientsReceivedAudioBytes = 0;
297
+ // this.totalClientsReceivedVideoBytes = 0;
298
+ // this.totalClientsReceivedBytes = 0;
299
+
300
+ // this.totalClientsSentAudioBytes = 0;
301
+ // this.totalClientsSentVideoBytes = 0;
302
+ // this.totalClientsSentBytes = 0;
303
+
304
+ // this.totalRttLt50Measurements = 0;
305
+ // this.totalRttLt150Measurements = 0;
306
+ // this.totalRttLt300Measurements = 0;
307
+ // this.totalRttGtOrEq300Measurements = 0;
308
+
309
+ // this.numberOfIssues = 0;
310
+
311
+ // this.clientsUsedTurn.clear();
312
+
313
+ // }
314
+
315
+ // public createSummary(): ObservedCallSummary {
316
+ // return {
317
+ // currentActiveClients: this.observedClients.size,
318
+ // totalAddedClients: this.totalAddedClients,
319
+ // totalRemovedClients: this.totalRemovedClients,
320
+
321
+ // totalClientsReceivedAudioBytes: this.totalClientsReceivedBytes,
322
+ // totalClientsReceivedVideoBytes: this.totalClientsReceivedVideoBytes,
323
+ // totalClientsReceivedBytes: this.totalClientsReceivedBytes,
324
+
325
+ // totalClientsSentAudioBytes: this.totalClientsSentAudioBytes,
326
+ // totalClientsSentVideoBytes: this.totalClientsSentVideoBytes,
327
+ // totalClientsSentBytes: this.totalClientsSentBytes,
328
+
329
+ // totalRttLt50Measurements: this.totalRttLt50Measurements,
330
+ // totalRttLt150Measurements: this.totalRttLt150Measurements,
331
+ // totalRttLt300Measurements: this.totalRttLt300Measurements,
332
+ // totalRttGtOrEq300Measurements: this.totalRttGtOrEq300Measurements,
333
+
334
+ // numberOfIssues: this.numberOfIssues,
335
+ // numberOfClientsUsedTurn: this.clientsUsedTurn.size,
336
+ // };
337
+ // }
133
338
  }