@observertc/observer-js 0.41.6 → 0.42.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 (61) hide show
  1. package/lib/ObservedCall.d.ts +10 -3
  2. package/lib/ObservedCall.d.ts.map +1 -1
  3. package/lib/ObservedCall.js +28 -0
  4. package/lib/ObservedClient.d.ts +4 -0
  5. package/lib/ObservedClient.d.ts.map +1 -1
  6. package/lib/ObservedClient.js +81 -32
  7. package/lib/ObservedInboundAudioTrack.d.ts +94 -0
  8. package/lib/ObservedInboundAudioTrack.d.ts.map +1 -0
  9. package/lib/ObservedInboundAudioTrack.js +215 -0
  10. package/lib/ObservedInboundVideoTrack.d.ts +98 -0
  11. package/lib/ObservedInboundVideoTrack.d.ts.map +1 -0
  12. package/lib/{ObservedInboundTrack.js → ObservedInboundVideoTrack.js} +53 -44
  13. package/lib/ObservedOutboundAudioTrack.d.ts +85 -0
  14. package/lib/ObservedOutboundAudioTrack.d.ts.map +1 -0
  15. package/lib/{ObservedOutboundTrack.js → ObservedOutboundAudioTrack.js} +35 -58
  16. package/lib/ObservedOutboundVideoTrack.d.ts +88 -0
  17. package/lib/ObservedOutboundVideoTrack.d.ts.map +1 -0
  18. package/lib/ObservedOutboundVideoTrack.js +204 -0
  19. package/lib/ObservedPeerConnection.d.ts +26 -16
  20. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  21. package/lib/ObservedPeerConnection.js +157 -86
  22. package/lib/RemoteTrackAssigner.d.ts +14 -0
  23. package/lib/RemoteTrackAssigner.d.ts.map +1 -0
  24. package/lib/RemoteTrackAssigner.js +52 -0
  25. package/lib/common/CalculatedScore.d.ts +79 -0
  26. package/lib/common/CalculatedScore.d.ts.map +1 -0
  27. package/lib/common/CalculatedScore.js +155 -0
  28. package/lib/common/CallEventType.d.ts +13 -1
  29. package/lib/common/CallEventType.d.ts.map +1 -1
  30. package/lib/common/CallEventType.js +12 -0
  31. package/lib/common/QualityScoreUtils.d.ts +1 -0
  32. package/lib/common/QualityScoreUtils.d.ts.map +1 -0
  33. package/lib/common/QualityScoreUtils.js +1 -0
  34. package/lib/common/utils.d.ts +1 -0
  35. package/lib/common/utils.d.ts.map +1 -1
  36. package/lib/common/utils.js +14 -1
  37. package/lib/index.d.ts +4 -2
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/monitors/ClientQualityMonitor.d.ts +1 -0
  40. package/lib/monitors/ClientQualityMonitor.d.ts.map +1 -0
  41. package/lib/monitors/ClientQualityMonitor.js +1 -0
  42. package/package.json +1 -1
  43. package/src/ObservedCall.ts +40 -4
  44. package/src/ObservedClient.ts +77 -17
  45. package/src/ObservedInboundAudioTrack.ts +336 -0
  46. package/src/{ObservedInboundTrack.ts → ObservedInboundVideoTrack.ts} +85 -66
  47. package/src/{ObservedOutboundTrack.ts → ObservedOutboundAudioTrack.ts} +59 -74
  48. package/src/ObservedOutboundVideoTrack.ts +326 -0
  49. package/src/ObservedPeerConnection.ts +205 -131
  50. package/src/RemoteTrackAssigner.ts +68 -0
  51. package/src/common/CalculatedScore.ts +180 -0
  52. package/src/common/CallEventType.ts +14 -1
  53. package/src/common/QualityScoreUtils.ts +0 -0
  54. package/src/common/utils.ts +17 -1
  55. package/src/index.ts +4 -2
  56. package/src/monitors/CallSummaryMonitor.ts +3 -3
  57. package/src/monitors/ClientQualityMonitor.ts +0 -0
  58. package/lib/ObservedInboundTrack.d.ts +0 -96
  59. package/lib/ObservedInboundTrack.d.ts.map +0 -1
  60. package/lib/ObservedOutboundTrack.d.ts +0 -84
  61. package/lib/ObservedOutboundTrack.d.ts.map +0 -1
@@ -2,10 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ObservedPeerConnection = void 0;
4
4
  const events_1 = require("events");
5
- const ObservedInboundTrack_1 = require("./ObservedInboundTrack");
6
- const ObservedOutboundTrack_1 = require("./ObservedOutboundTrack");
7
5
  const ObservedICE_1 = require("./ObservedICE");
8
6
  const ObservedDataChannel_1 = require("./ObservedDataChannel");
7
+ const ObservedInboundAudioTrack_1 = require("./ObservedInboundAudioTrack");
8
+ const ObservedInboundVideoTrack_1 = require("./ObservedInboundVideoTrack");
9
+ const ObservedOutboundAudioTrack_1 = require("./ObservedOutboundAudioTrack");
10
+ const ObservedOutboundVideoTrack_1 = require("./ObservedOutboundVideoTrack");
11
+ const CalculatedScore_1 = require("./common/CalculatedScore");
9
12
  class ObservedPeerConnection extends events_1.EventEmitter {
10
13
  constructor(_model, client) {
11
14
  super();
@@ -13,6 +16,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
13
16
  this.client = client;
14
17
  this.created = Date.now();
15
18
  this.visited = true;
19
+ this.ωpendingIssuesForScores = [];
16
20
  this.totalInboundPacketsLost = 0;
17
21
  this.totalInboundPacketsReceived = 0;
18
22
  this.totalOutboundPacketsSent = 0;
@@ -143,8 +147,16 @@ class ObservedPeerConnection extends events_1.EventEmitter {
143
147
  this._closed = true;
144
148
  Array.from(this._inboundAudioTracks.values()).forEach((track) => track.close());
145
149
  Array.from(this._inboundVideoTracks.values()).forEach((track) => track.close());
146
- Array.from(this._outboundAudioTracks.values()).forEach((track) => track.close());
147
- Array.from(this._outboundVideoTracks.values()).forEach((track) => track.close());
150
+ Array.from(this._outboundAudioTracks.values()).forEach((track) => {
151
+ var _a;
152
+ this.client.call.sfuStreamIdToOutboundAudioTrack.delete((_a = track.sfuStreamId) !== null && _a !== void 0 ? _a : '');
153
+ track.close();
154
+ });
155
+ Array.from(this._outboundVideoTracks.values()).forEach((track) => {
156
+ var _a;
157
+ this.client.call.sfuStreamIdToOutboundVideoTrack.delete((_a = track.sfuStreamId) !== null && _a !== void 0 ? _a : '');
158
+ track.close();
159
+ });
148
160
  this.emit('close');
149
161
  }
150
162
  getTrack(trackId) {
@@ -171,84 +183,6 @@ class ObservedPeerConnection extends events_1.EventEmitter {
171
183
  this.receivingVideoBitrate = 0;
172
184
  this.ICE.resetMetrics();
173
185
  }
174
- updateMetrics() {
175
- var _a;
176
- let sumRttInMs = 0;
177
- this._inboundAudioTracks.forEach((track) => {
178
- var _a;
179
- track.updateMetrics();
180
- this.deltaInboundPacketsLost += track.deltaLostPackets;
181
- this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
182
- this.deltaInboundReceivedBytes += track.deltaBytesReceived;
183
- this.deltaReceivedAudioBytes += track.deltaBytesReceived;
184
- this.deltaReceivedAudioPackets += track.deltaReceivedPackets;
185
- this.receivingAudioBitrate += track.bitrate;
186
- sumRttInMs = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
187
- });
188
- this._inboundVideoTracks.forEach((track) => {
189
- var _a;
190
- track.updateMetrics();
191
- this.deltaInboundPacketsLost += track.deltaLostPackets;
192
- this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
193
- this.deltaInboundReceivedBytes += track.deltaBytesReceived;
194
- this.deltaReceivedVideoBytes += track.deltaBytesReceived;
195
- this.deltaReceivedVideoPackets += track.deltaReceivedPackets;
196
- this.receivingVideoBitrate += track.bitrate;
197
- sumRttInMs = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
198
- });
199
- this._outboundAudioTracks.forEach((track) => {
200
- var _a;
201
- track.updateMetrics();
202
- this.deltaOutboundPacketsSent += track.deltaSentPackets;
203
- this.deltaOutboundSentBytes += track.deltaSentBytes;
204
- this.deltaSentAudioBytes += track.deltaSentBytes;
205
- this.deltaSentAudioBytes += track.deltaSentPackets;
206
- this.sendingAudioBitrate += track.bitrate;
207
- sumRttInMs = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
208
- });
209
- this._outboundVideoTracks.forEach((track) => {
210
- var _a;
211
- track.updateMetrics();
212
- this.deltaOutboundPacketsSent += track.deltaSentPackets;
213
- this.deltaOutboundSentBytes += track.deltaSentBytes;
214
- this.deltaSentVideoBytes += track.deltaSentBytes;
215
- this.deltaSentVideoBytes += track.deltaSentPackets;
216
- this.sendingVideoBitrate += track.bitrate;
217
- sumRttInMs = ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
218
- });
219
- this._dataChannels.forEach((channel) => {
220
- this.deltaDataChannelBytesSent += channel.deltaBytesSent;
221
- this.deltaDataChannelBytesReceived += channel.deltaBytesReceived;
222
- });
223
- const iceRttInMs = (_a = this.ICE.stats) === null || _a === void 0 ? void 0 : _a.currentRoundTripTime;
224
- let nrOfBelongings = this._inboundAudioTracks.size + this._inboundVideoTracks.size + this._outboundAudioTracks.size + this._outboundVideoTracks.size;
225
- if (iceRttInMs) {
226
- sumRttInMs += iceRttInMs;
227
- nrOfBelongings += 1;
228
- }
229
- this.avgRttInMs = 0 < nrOfBelongings ? sumRttInMs / nrOfBelongings : undefined;
230
- this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
231
- this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
232
- this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
233
- this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
234
- this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
235
- this.totalSentAudioBytes += this.deltaSentAudioBytes;
236
- this.totalSentVideoBytes += this.deltaSentVideoBytes;
237
- this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
238
- this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
239
- this.totalReceivedAudioPacktes += this.deltaReceivedAudioPackets;
240
- this.totalReceivedVideoPackets += this.deltaReceivedVideoPackets;
241
- this.totalSentAudioPackets += this.deltaSentAudioBytes;
242
- this.totalSentVideoPackets += this.deltaSentVideoBytes;
243
- if (this._elapsedTimeSinceLastUpdate && 0 < this._elapsedTimeSinceLastUpdate) {
244
- this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / (this._elapsedTimeSinceLastUpdate / 1000);
245
- this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / (this._elapsedTimeSinceLastUpdate / 1000);
246
- }
247
- else {
248
- this.sendingPacketsPerSecond = 0;
249
- this.receivingPacketsPerSecond = 0;
250
- }
251
- }
252
186
  update(sample, timestamp) {
253
187
  if (this._closed)
254
188
  return;
@@ -264,6 +198,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
264
198
  this._elapsedTimeSinceLastUpdate = now - this._updated;
265
199
  this.visited = true;
266
200
  this._updated = now;
201
+ this._statsTimestamp = timestamp;
267
202
  this.emit('update', {
268
203
  elapsedTimeInMs: this._elapsedTimeSinceLastUpdate,
269
204
  });
@@ -271,7 +206,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
271
206
  createInboundAudioTrack(config) {
272
207
  if (this._closed)
273
208
  throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
274
- const result = new ObservedInboundTrack_1.ObservedInboundTrack(Object.assign({ kind: 'audio' }, config), this);
209
+ const result = new ObservedInboundAudioTrack_1.ObservedInboundAudioTrack(config, this);
275
210
  result.on('close', () => {
276
211
  this._inboundAudioTracks.delete(result.trackId);
277
212
  });
@@ -282,7 +217,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
282
217
  createInboundVideoTrack(config) {
283
218
  if (this._closed)
284
219
  throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
285
- const result = new ObservedInboundTrack_1.ObservedInboundTrack(Object.assign({ kind: 'video' }, config), this);
220
+ const result = new ObservedInboundVideoTrack_1.ObservedInboundVideoTrack(config, this);
286
221
  result.on('close', () => {
287
222
  this._inboundVideoTracks.delete(result.trackId);
288
223
  });
@@ -293,7 +228,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
293
228
  createOutboundAudioTrack(config) {
294
229
  if (this._closed)
295
230
  throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
296
- const result = new ObservedOutboundTrack_1.ObservedOutboundTrack(Object.assign({ kind: 'audio' }, config), this);
231
+ const result = new ObservedOutboundAudioTrack_1.ObservedOutboundAudioTrack(config, this);
297
232
  result.on('close', () => {
298
233
  this._outboundAudioTracks.delete(result.trackId);
299
234
  });
@@ -304,7 +239,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
304
239
  createOutboundVideoTrack(config) {
305
240
  if (this._closed)
306
241
  throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
307
- const result = new ObservedOutboundTrack_1.ObservedOutboundTrack(Object.assign({ kind: 'video' }, config), this);
242
+ const result = new ObservedOutboundVideoTrack_1.ObservedOutboundVideoTrack(config, this);
308
243
  result.on('close', () => {
309
244
  this._outboundVideoTracks.delete(result.trackId);
310
245
  });
@@ -325,5 +260,141 @@ class ObservedPeerConnection extends events_1.EventEmitter {
325
260
  this.emit('newdatachannel', result);
326
261
  return result;
327
262
  }
263
+ updateMetrics() {
264
+ var _a;
265
+ let sumRttInMs = 0;
266
+ let sumJitter = 0;
267
+ const trackScores = [];
268
+ this._inboundAudioTracks.forEach((track) => {
269
+ var _a, _b;
270
+ track.updateMetrics();
271
+ this.deltaInboundPacketsLost += track.deltaLostPackets;
272
+ this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
273
+ this.deltaInboundReceivedBytes += track.deltaBytesReceived;
274
+ this.deltaReceivedAudioBytes += track.deltaBytesReceived;
275
+ this.deltaReceivedAudioPackets += track.deltaReceivedPackets;
276
+ this.receivingAudioBitrate += track.bitrate;
277
+ sumRttInMs += ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
278
+ sumJitter += ((_b = track.jitter) !== null && _b !== void 0 ? _b : 0);
279
+ track.score && trackScores.push(track.score);
280
+ });
281
+ this._inboundVideoTracks.forEach((track) => {
282
+ var _a, _b;
283
+ track.updateMetrics();
284
+ this.deltaInboundPacketsLost += track.deltaLostPackets;
285
+ this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
286
+ this.deltaInboundReceivedBytes += track.deltaBytesReceived;
287
+ this.deltaReceivedVideoBytes += track.deltaBytesReceived;
288
+ this.deltaReceivedVideoPackets += track.deltaReceivedPackets;
289
+ this.receivingVideoBitrate += track.bitrate;
290
+ sumRttInMs += ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
291
+ sumJitter += ((_b = track.jitter) !== null && _b !== void 0 ? _b : 0);
292
+ track.score && trackScores.push(track.score);
293
+ });
294
+ this._outboundAudioTracks.forEach((track) => {
295
+ var _a, _b;
296
+ track.updateMetrics();
297
+ this.deltaOutboundPacketsSent += track.deltaSentPackets;
298
+ this.deltaOutboundSentBytes += track.deltaSentBytes;
299
+ this.deltaSentAudioBytes += track.deltaSentBytes;
300
+ this.deltaSentAudioBytes += track.deltaSentPackets;
301
+ this.sendingAudioBitrate += track.bitrate;
302
+ sumRttInMs += ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
303
+ sumJitter += ((_b = track.jitter) !== null && _b !== void 0 ? _b : 0);
304
+ track.score && trackScores.push(track.score);
305
+ });
306
+ this._outboundVideoTracks.forEach((track) => {
307
+ var _a, _b;
308
+ track.updateMetrics();
309
+ this.deltaOutboundPacketsSent += track.deltaSentPackets;
310
+ this.deltaOutboundSentBytes += track.deltaSentBytes;
311
+ this.deltaSentVideoBytes += track.deltaSentBytes;
312
+ this.deltaSentVideoBytes += track.deltaSentPackets;
313
+ this.sendingVideoBitrate += track.bitrate;
314
+ sumRttInMs += ((_a = track.rttInMs) !== null && _a !== void 0 ? _a : 0);
315
+ sumJitter += ((_b = track.jitter) !== null && _b !== void 0 ? _b : 0);
316
+ track.score && trackScores.push(track.score);
317
+ });
318
+ this._dataChannels.forEach((channel) => {
319
+ this.deltaDataChannelBytesSent += channel.deltaBytesSent;
320
+ this.deltaDataChannelBytesReceived += channel.deltaBytesReceived;
321
+ });
322
+ const iceRttInMs = (_a = this.ICE.stats) === null || _a === void 0 ? void 0 : _a.currentRoundTripTime;
323
+ let nrOfBelongings = this._inboundAudioTracks.size + this._inboundVideoTracks.size + this._outboundAudioTracks.size + this._outboundVideoTracks.size;
324
+ this.avgJitter = 0 < nrOfBelongings ? sumJitter / nrOfBelongings : undefined;
325
+ if (iceRttInMs) {
326
+ sumRttInMs += iceRttInMs;
327
+ nrOfBelongings += 1;
328
+ }
329
+ this.avgRttInMs = 0 < nrOfBelongings ? sumRttInMs / nrOfBelongings : undefined;
330
+ this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
331
+ this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
332
+ this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
333
+ this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
334
+ this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
335
+ this.totalSentAudioBytes += this.deltaSentAudioBytes;
336
+ this.totalSentVideoBytes += this.deltaSentVideoBytes;
337
+ this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
338
+ this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
339
+ this.totalReceivedAudioPacktes += this.deltaReceivedAudioPackets;
340
+ this.totalReceivedVideoPackets += this.deltaReceivedVideoPackets;
341
+ this.totalSentAudioPackets += this.deltaSentAudioBytes;
342
+ this.totalSentVideoPackets += this.deltaSentVideoBytes;
343
+ if (this._elapsedTimeSinceLastUpdate && 0 < this._elapsedTimeSinceLastUpdate) {
344
+ this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / (this._elapsedTimeSinceLastUpdate / 1000);
345
+ this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / (this._elapsedTimeSinceLastUpdate / 1000);
346
+ }
347
+ else {
348
+ this.sendingPacketsPerSecond = 0;
349
+ this.receivingPacketsPerSecond = 0;
350
+ }
351
+ // calculate quality score
352
+ this._updateQualityScore(trackScores);
353
+ }
354
+ _updateQualityScore(trackScores) {
355
+ var _a, _b, _c, _d;
356
+ const mosScore = (0, CalculatedScore_1.calculateLatencyMOS)({
357
+ avgJitter: (_a = this.avgJitter) !== null && _a !== void 0 ? _a : 0,
358
+ rttInMs: (_b = this.avgRttInMs) !== null && _b !== void 0 ? _b : 0,
359
+ packetsLoss: this.deltaInboundPacketsLost,
360
+ });
361
+ const score = {
362
+ remarks: [{
363
+ severity: 'none',
364
+ text: `MOS score: ${mosScore}`,
365
+ }],
366
+ score: mosScore / 10.0,
367
+ timestamp: (_c = this._statsTimestamp) !== null && _c !== void 0 ? _c : Date.now(),
368
+ };
369
+ let sumTrackScores = 0;
370
+ for (const trackScore of trackScores) {
371
+ sumTrackScores += trackScore.score;
372
+ }
373
+ score.score += sumTrackScores / trackScores.length;
374
+ score.remarks.push({
375
+ severity: 'none',
376
+ text: `Track scores: ${sumTrackScores / trackScores.length}`,
377
+ });
378
+ for (const pendingScore of this.ωpendingIssuesForScores) {
379
+ switch (pendingScore.severity) {
380
+ case 'critical':
381
+ score.score = 0.0;
382
+ break;
383
+ case 'major':
384
+ score.score *= 0.5;
385
+ break;
386
+ case 'minor':
387
+ score.score *= 0.8;
388
+ break;
389
+ }
390
+ score.remarks.push({
391
+ severity: pendingScore.severity,
392
+ text: (_d = pendingScore.description) !== null && _d !== void 0 ? _d : 'Issue occurred',
393
+ });
394
+ }
395
+ this.ωpendingIssuesForScores = [];
396
+ this.score = score;
397
+ this.emit('score', score);
398
+ }
328
399
  }
329
400
  exports.ObservedPeerConnection = ObservedPeerConnection;
@@ -0,0 +1,14 @@
1
+ import { ObservedInboundAudioTrack } from './ObservedInboundAudioTrack';
2
+ import { ObservedInboundVideoTrack } from './ObservedInboundVideoTrack';
3
+ import { ObservedOutboundAudioTrack } from './ObservedOutboundAudioTrack';
4
+ import { ObservedOutboundVideoTrack } from './ObservedOutboundVideoTrack';
5
+ export declare class RemoteTrackAssigner {
6
+ readonly sfuStreamIdToOutboundVideoTracks: Map<string, ObservedOutboundVideoTrack>;
7
+ readonly sfuStreamIdToOutboundAudioTracks: Map<string, ObservedOutboundAudioTrack>;
8
+ readonly pendingInboundVideoTracks: Map<string, ObservedInboundVideoTrack[]>;
9
+ readonly pendingInboundAudioTracks: Map<string, ObservedInboundAudioTrack[]>;
10
+ addOutboundAudioTrack(track: ObservedOutboundAudioTrack): void;
11
+ addOutboundVideoTrack(track: ObservedOutboundVideoTrack): void;
12
+ addInboundAudioTrack(track: ObservedInboundAudioTrack): void;
13
+ }
14
+ //# sourceMappingURL=RemoteTrackAssigner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoteTrackAssigner.d.ts","sourceRoot":"","sources":["../src/RemoteTrackAssigner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAE1E,qBAAa,mBAAmB;IAC/B,SAAgB,gCAAgC,0CAAiD;IACjG,SAAgB,gCAAgC,0CAAiD;IACjG,SAAgB,yBAAyB,2CAAkD;IAC3F,SAAgB,yBAAyB,2CAAkD;IAEpF,qBAAqB,CAAC,KAAK,EAAE,0BAA0B;IAcvD,qBAAqB,CAAC,KAAK,EAAE,0BAA0B;IAcvD,oBAAoB,CAAC,KAAK,EAAE,yBAAyB;CA4B5D"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RemoteTrackAssigner = void 0;
4
+ class RemoteTrackAssigner {
5
+ constructor() {
6
+ this.sfuStreamIdToOutboundVideoTracks = new Map();
7
+ this.sfuStreamIdToOutboundAudioTracks = new Map();
8
+ this.pendingInboundVideoTracks = new Map();
9
+ this.pendingInboundAudioTracks = new Map();
10
+ }
11
+ addOutboundAudioTrack(track) {
12
+ const untilSfuStreamIdListener = () => {
13
+ if (!track.sfuStreamId)
14
+ return;
15
+ this.sfuStreamIdToOutboundAudioTracks.set(track.sfuStreamId, track);
16
+ track.off('update', untilSfuStreamIdListener);
17
+ // we need to assign to the pending inbound tracks
18
+ };
19
+ track.on('update', untilSfuStreamIdListener);
20
+ untilSfuStreamIdListener();
21
+ }
22
+ addOutboundVideoTrack(track) {
23
+ const untilSfuStreamIdListener = () => {
24
+ if (!track.sfuStreamId)
25
+ return;
26
+ this.sfuStreamIdToOutboundVideoTracks.set(track.sfuStreamId, track);
27
+ track.off('update', untilSfuStreamIdListener);
28
+ // we need to assign to the pending inbound tracks
29
+ };
30
+ track.on('update', untilSfuStreamIdListener);
31
+ untilSfuStreamIdListener();
32
+ }
33
+ addInboundAudioTrack(track) {
34
+ const untilSfuStreamIdListener = () => {
35
+ if (!track.sfuStreamId)
36
+ return;
37
+ const outboundTrack = this.sfuStreamIdToOutboundAudioTracks.get(track.sfuStreamId);
38
+ if (!outboundTrack) {
39
+ this.pendingInboundAudioTracks.set(track.sfuStreamId, (this.pendingInboundAudioTracks.get(track.sfuStreamId) || []).concat(track));
40
+ return;
41
+ }
42
+ if (outboundTrack) {
43
+ track.remoteOutboundTrack = outboundTrack;
44
+ }
45
+ else {
46
+ this.pendingInboundAudioTracks.set(track.sfuStreamId, (this.pendingInboundAudioTracks.get(track.sfuStreamId) || []).concat(track));
47
+ }
48
+ };
49
+ track.on('update', untilSfuStreamIdListener);
50
+ }
51
+ }
52
+ exports.RemoteTrackAssigner = RemoteTrackAssigner;
@@ -0,0 +1,79 @@
1
+ import { ClientIssue } from '../monitors/CallSummary';
2
+ import { ObservedInboundVideoTrack } from '../ObservedInboundVideoTrack';
3
+ import { ObservedInboundAudioTrack } from '../ObservedInboundAudioTrack';
4
+ import { ObservedOutboundVideoTrack } from '../ObservedOutboundVideoTrack';
5
+ import { ObservedOutboundAudioTrack } from '../ObservedOutboundAudioTrack';
6
+ export type CalculationRemark = {
7
+ severity: 'none' | 'minor' | 'major' | 'critical';
8
+ text: string;
9
+ };
10
+ export type CalculatedScore = {
11
+ score: number;
12
+ timestamp: number;
13
+ remarks: CalculationRemark[];
14
+ debugText?: string;
15
+ };
16
+ export declare const BPP_RANGES: {
17
+ lowmotion: {
18
+ h264: {
19
+ low: number;
20
+ high: number;
21
+ };
22
+ h265: {
23
+ low: number;
24
+ high: number;
25
+ };
26
+ vp8: {
27
+ low: number;
28
+ high: number;
29
+ };
30
+ vp9: {
31
+ low: number;
32
+ high: number;
33
+ };
34
+ };
35
+ standard: {
36
+ h264: {
37
+ low: number;
38
+ high: number;
39
+ };
40
+ h265: {
41
+ low: number;
42
+ high: number;
43
+ };
44
+ vp8: {
45
+ low: number;
46
+ high: number;
47
+ };
48
+ vp9: {
49
+ low: number;
50
+ high: number;
51
+ };
52
+ };
53
+ highmotion: {
54
+ h264: {
55
+ low: number;
56
+ high: number;
57
+ };
58
+ h265: {
59
+ low: number;
60
+ high: number;
61
+ };
62
+ vp8: {
63
+ low: number;
64
+ high: number;
65
+ };
66
+ vp9: {
67
+ low: number;
68
+ high: number;
69
+ };
70
+ };
71
+ };
72
+ export declare function calculateBaseVideoScore(track: ObservedInboundVideoTrack | ObservedOutboundVideoTrack, newIssues: ClientIssue[]): CalculatedScore | undefined;
73
+ export declare function calculateBaseAudioScore(track: ObservedInboundAudioTrack | ObservedOutboundAudioTrack, newIssues: ClientIssue[]): CalculatedScore | undefined;
74
+ export declare function calculateLatencyMOS({ avgJitter, rttInMs, packetsLoss }: {
75
+ avgJitter: number;
76
+ rttInMs: number;
77
+ packetsLoss: number;
78
+ }): number;
79
+ //# sourceMappingURL=CalculatedScore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CalculatedScore.d.ts","sourceRoot":"","sources":["../../src/common/CalculatedScore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;CACb,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAmBD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmBtB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,yBAAyB,GAAG,0BAA0B,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,eAAe,GAAG,SAAS,CAiE5J;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,yBAAyB,GAAG,0BAA0B,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,eAAe,GAAG,SAAS,CA0C5J;AAED,wBAAgB,mBAAmB,CAClC,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,EACnC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACzD,MAAM,CASR"}
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateLatencyMOS = exports.calculateBaseAudioScore = exports.calculateBaseVideoScore = exports.BPP_RANGES = void 0;
4
+ // every track calculates its own score and stores
5
+ // the latest CalculatedScore in a score property also emits as an event 'score'
6
+ // every peer connection collects the scores and calculates its own score based on RTT, and stores it in the score property similar to track
7
+ // every client collects the scores and calculates its own score based on the peer connection scores, and stores it in the score property similar to track
8
+ // every call collects the scores and calculates its own score based on the client scores, and stores it in the score property similar to track, but
9
+ // but calls only recalculate it after a configured amount of time passed from the last recalculation, and it does not trigger automatically
10
+ /*
11
+ Recommended bpp Ranges for Good Quality
12
+
13
+ | Content Type | H.264 (AVC) bpp Range | H.265 (HEVC) bpp Range | VP8 bpp Range | VP9 bpp Range |
14
+ |--------------------|-----------------------|-----------------------|---------------|---------------|
15
+ | Low Motion | 0.1 - 0.2 | 0.05 - 0.15 | 0.1 - 0.2 | 0.05 - 0.15 |
16
+ | Standard Motion | 0.15 - 0.25 | 0.1 - 0.2 | 0.15 - 0.25 | 0.1 - 0.2 |
17
+ | High Motion | 0.25 - 0.4 | 0.15 - 0.3 | 0.25 - 0.4 | 0.15 - 0.3 |
18
+
19
+ */
20
+ exports.BPP_RANGES = {
21
+ 'lowmotion': {
22
+ 'h264': { low: 0.1, high: 0.2 },
23
+ 'h265': { low: 0.05, high: 0.15 },
24
+ 'vp8': { low: 0.1, high: 0.2 },
25
+ 'vp9': { low: 0.05, high: 0.15 },
26
+ },
27
+ 'standard': {
28
+ 'h264': { low: 0.15, high: 0.25 },
29
+ 'h265': { low: 0.1, high: 0.2 },
30
+ 'vp8': { low: 0.15, high: 0.25 },
31
+ 'vp9': { low: 0.1, high: 0.2 },
32
+ },
33
+ 'highmotion': {
34
+ 'h264': { low: 0.25, high: 0.4 },
35
+ 'h265': { low: 0.15, high: 0.3 },
36
+ 'vp8': { low: 0.25, high: 0.4 },
37
+ 'vp9': { low: 0.15, high: 0.3 },
38
+ },
39
+ };
40
+ function calculateBaseVideoScore(track, newIssues) {
41
+ var _a;
42
+ if (!track.highestLayer) {
43
+ return;
44
+ }
45
+ const { frameHeight, frameWidth, framesPerSecond, bitrate, } = track.highestLayer;
46
+ const score = {
47
+ remarks: [],
48
+ score: 0.0,
49
+ timestamp: track.statsTimestamp,
50
+ };
51
+ if (!frameHeight || !frameWidth || !bitrate || !framesPerSecond) {
52
+ score.score = 0.0;
53
+ score.remarks.push({
54
+ severity: 'major',
55
+ text: 'Missing data for score calculation',
56
+ });
57
+ return score;
58
+ }
59
+ const bpp = bitrate / (frameHeight * frameWidth * framesPerSecond);
60
+ // let's assume vp8 for now
61
+ const bppRange = exports.BPP_RANGES[track.contentType][track.codec];
62
+ if (bpp / 2 < bppRange.low) {
63
+ score.score = 1.0;
64
+ score.remarks.push({
65
+ severity: 'major',
66
+ text: `Bitrate per pixel is too low for ${track.contentType} content`,
67
+ });
68
+ }
69
+ else if (bppRange.low < bpp) {
70
+ score.score = 1.0;
71
+ score.remarks.push({
72
+ severity: 'minor',
73
+ text: `Bitrate per pixel is good for ${track.contentType} content`,
74
+ });
75
+ }
76
+ else {
77
+ score.score = Math.min(3.0, 2.0 + ((bpp - bppRange.low) / (bppRange.high - bppRange.low)));
78
+ score.remarks.push({
79
+ severity: 'none',
80
+ text: `Bitrate per pixel is good for ${track.contentType} content`,
81
+ });
82
+ }
83
+ for (const issue of newIssues) {
84
+ if (issue.severity === 'critical') {
85
+ score.score = 0.0;
86
+ }
87
+ else if (issue.severity === 'major') {
88
+ score.score *= 0.5;
89
+ }
90
+ else if (issue.severity === 'minor') {
91
+ score.score *= 0.8;
92
+ }
93
+ score.remarks.push({
94
+ severity: issue.severity,
95
+ text: (_a = issue.description) !== null && _a !== void 0 ? _a : 'Issue occurred',
96
+ });
97
+ }
98
+ return score;
99
+ }
100
+ exports.calculateBaseVideoScore = calculateBaseVideoScore;
101
+ function calculateBaseAudioScore(track, newIssues) {
102
+ var _a;
103
+ const score = {
104
+ remarks: [],
105
+ score: 0.0,
106
+ timestamp: track.statsTimestamp,
107
+ };
108
+ if (track.bitrate < 8000) {
109
+ score.score = 1.0;
110
+ score.remarks.push({
111
+ severity: 'none',
112
+ text: 'Bitrate is too low for audio',
113
+ });
114
+ }
115
+ else if (track.bitrate < 16000) {
116
+ score.score = 2.8;
117
+ score.remarks.push({
118
+ severity: 'none',
119
+ text: 'Bitrate is low for audio',
120
+ });
121
+ }
122
+ else {
123
+ score.score = 3.0;
124
+ score.remarks.push({
125
+ severity: 'none',
126
+ text: 'Bitrate is good for audio',
127
+ });
128
+ }
129
+ for (const issues of newIssues) {
130
+ if (issues.severity === 'critical') {
131
+ score.score = 0.0;
132
+ }
133
+ else if (issues.severity === 'major') {
134
+ score.score *= 0.5;
135
+ }
136
+ else if (issues.severity === 'minor') {
137
+ score.score *= 0.8;
138
+ }
139
+ score.remarks.push({
140
+ severity: issues.severity,
141
+ text: (_a = issues.description) !== null && _a !== void 0 ? _a : 'Issue occurred',
142
+ });
143
+ }
144
+ return score;
145
+ }
146
+ exports.calculateBaseAudioScore = calculateBaseAudioScore;
147
+ function calculateLatencyMOS({ avgJitter, rttInMs, packetsLoss }) {
148
+ const effectiveLatency = rttInMs + (avgJitter * 2) + 10;
149
+ let rFactor = effectiveLatency < 160
150
+ ? 93.2 - (effectiveLatency / 40)
151
+ : 93.2 - (effectiveLatency / 120) - 10;
152
+ rFactor -= (packetsLoss * 2.5);
153
+ return 1 + ((0.035) * rFactor) + ((0.000007) * rFactor * (rFactor - 60) * (100 - rFactor));
154
+ }
155
+ exports.calculateLatencyMOS = calculateLatencyMOS;
@@ -18,7 +18,19 @@ export declare enum CallEventType {
18
18
  DATA_CHANNEL_ERROR = "DATA_CHANNEL_ERROR",
19
19
  NEGOTIATION_NEEDED = "NEGOTIATION_NEEDED",
20
20
  SIGNALING_STATE_CHANGE = "SIGNALING_STATE_CHANGE",
21
- CLIENT_ISSUE = "CLIENT_ISSUE"
21
+ CLIENT_ISSUE = "CLIENT_ISSUE",
22
+ PRODUCER_ADDED = "PRODUCER_ADDED",
23
+ PRODUCER_PAUSED = "PRODUCER_PAUSED",
24
+ PRODUCER_RESUMED = "PRODUCER_RESUMED",
25
+ PRODUCER_REMOVED = "PRODUCER_REMOVED",
26
+ CONSUMER_ADDED = "CONSUMER_ADDED",
27
+ CONSUMER_PAUSED = "CONSUMER_PAUSED",
28
+ CONSUMER_RESUMED = "CONSUMER_RESUMED",
29
+ CONSUMER_REMOVED = "CONSUMER_REMOVED",
30
+ DATA_PRODUCER_OPENED = "DATA_PRODUCER_OPENED",
31
+ DATA_PRODUCER_CLOSED = "DATA_PRODUCER_CLOSED",
32
+ DATA_CONSUMER_OPENED = "DATA_CONSUMER_OPENED",
33
+ DATA_CONSUMER_CLOSED = "DATA_CONSUMER_CLOSED"
22
34
  }
23
35
  export type CallEventReportType = {
24
36
  name: CallEventType.MEDIA_TRACK_ADDED;
@@ -1 +1 @@
1
- {"version":3,"file":"CallEventType.d.ts","sourceRoot":"","sources":["../../src/common/CallEventType.ts"],"names":[],"mappings":"AACA,oBAAY,aAAa;IACxB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;IAC3B,sBAAsB,2BAA2B;IACjD,sBAAsB,2BAA2B;IACjD,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,mBAAmB,wBAAwB;IAC3C,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,2BAA2B,gCAAgC;IAC3D,6BAA6B,kCAAkC;IAC/D,4BAA4B,iCAAiC;IAC7D,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,kBAAkB,uBAAuB;IACzC,kBAAkB,uBAAuB;IACzC,sBAAsB,2BAA2B;IACjD,YAAY,iBAAiB;CAC7B;AAED,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,aAAa,CAAC,iBAAiB,CAAC;IACtC,UAAU,EAAE,yBAAyB,CAAC;CACtC,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,6BAA6B,CAAC;IAClD,UAAU,EAAE,oCAAoC,CAAC;CACjD,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,4BAA4B,CAAC;IACjD,UAAU,EAAE,mCAAmC,CAAC;CAChD,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,2BAA2B,CAAC;IAChD,UAAU,EAAE,kCAAkC,CAAC;CAC/C,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAED,MAAM,MAAM,oCAAoC,GAAG;IAClD,kBAAkB,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC/F,CAAA;AAED,MAAM,MAAM,mCAAmC,GAAG;IACjD,kBAAkB,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;CAC3G,CAAA;AAED,MAAM,MAAM,kCAAkC,GAAG;IAChD,iBAAiB,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;CACrD,CAAA"}
1
+ {"version":3,"file":"CallEventType.d.ts","sourceRoot":"","sources":["../../src/common/CallEventType.ts"],"names":[],"mappings":"AACA,oBAAY,aAAa;IACxB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,WAAW,gBAAgB;IAC3B,sBAAsB,2BAA2B;IACjD,sBAAsB,2BAA2B;IACjD,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,mBAAmB,wBAAwB;IAC3C,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,2BAA2B,gCAAgC;IAC3D,6BAA6B,kCAAkC;IAC/D,4BAA4B,iCAAiC;IAC7D,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,kBAAkB,uBAAuB;IACzC,kBAAkB,uBAAuB;IACzC,sBAAsB,2BAA2B;IACjD,YAAY,iBAAiB;IAE7B,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,gBAAgB,qBAAqB;IACrC,gBAAgB,qBAAqB;IACrC,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,gBAAgB,qBAAqB;IACrC,gBAAgB,qBAAqB;IACrC,oBAAoB,yBAAyB;IAC7C,oBAAoB,yBAAyB;IAC7C,oBAAoB,yBAAyB;IAC7C,oBAAoB,yBAAyB;CAC7C;AAED,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,aAAa,CAAC,iBAAiB,CAAC;IACtC,UAAU,EAAE,yBAAyB,CAAC;CACtC,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,6BAA6B,CAAC;IAClD,UAAU,EAAE,oCAAoC,CAAC;CACjD,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,4BAA4B,CAAC;IACjD,UAAU,EAAE,mCAAmC,CAAC;CAChD,GAAG;IACH,IAAI,EAAE,aAAa,CAAC,2BAA2B,CAAC;IAChD,UAAU,EAAE,kCAAkC,CAAC;CAC/C,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAED,MAAM,MAAM,oCAAoC,GAAG;IAClD,kBAAkB,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC/F,CAAA;AAED,MAAM,MAAM,mCAAmC,GAAG;IACjD,kBAAkB,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;CAC3G,CAAA;AAED,MAAM,MAAM,kCAAkC,GAAG;IAChD,iBAAiB,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;CACrD,CAAA"}
@@ -24,4 +24,16 @@ var CallEventType;
24
24
  CallEventType["NEGOTIATION_NEEDED"] = "NEGOTIATION_NEEDED";
25
25
  CallEventType["SIGNALING_STATE_CHANGE"] = "SIGNALING_STATE_CHANGE";
26
26
  CallEventType["CLIENT_ISSUE"] = "CLIENT_ISSUE";
27
+ CallEventType["PRODUCER_ADDED"] = "PRODUCER_ADDED";
28
+ CallEventType["PRODUCER_PAUSED"] = "PRODUCER_PAUSED";
29
+ CallEventType["PRODUCER_RESUMED"] = "PRODUCER_RESUMED";
30
+ CallEventType["PRODUCER_REMOVED"] = "PRODUCER_REMOVED";
31
+ CallEventType["CONSUMER_ADDED"] = "CONSUMER_ADDED";
32
+ CallEventType["CONSUMER_PAUSED"] = "CONSUMER_PAUSED";
33
+ CallEventType["CONSUMER_RESUMED"] = "CONSUMER_RESUMED";
34
+ CallEventType["CONSUMER_REMOVED"] = "CONSUMER_REMOVED";
35
+ CallEventType["DATA_PRODUCER_OPENED"] = "DATA_PRODUCER_OPENED";
36
+ CallEventType["DATA_PRODUCER_CLOSED"] = "DATA_PRODUCER_CLOSED";
37
+ CallEventType["DATA_CONSUMER_OPENED"] = "DATA_CONSUMER_OPENED";
38
+ CallEventType["DATA_CONSUMER_CLOSED"] = "DATA_CONSUMER_CLOSED";
27
39
  })(CallEventType = exports.CallEventType || (exports.CallEventType = {}));