@webex/plugin-meetings 3.0.0-beta.405 → 3.0.0-beta.406

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.
@@ -209,7 +209,7 @@ var Breakout = _webexCore.WebexPlugin.extend({
209
209
  sessionId: this.sessionId
210
210
  });
211
211
  },
212
- version: "3.0.0-beta.405"
212
+ version: "3.0.0-beta.406"
213
213
  });
214
214
  var _default = Breakout;
215
215
  exports.default = _default;
@@ -1041,7 +1041,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
1041
1041
  this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1042
1042
  }
1043
1043
  },
1044
- version: "3.0.0-beta.405"
1044
+ version: "3.0.0-beta.406"
1045
1045
  });
1046
1046
  var _default = Breakouts;
1047
1047
  exports.default = _default;
@@ -373,7 +373,7 @@ var SimultaneousInterpretation = _webexCore.WebexPlugin.extend({
373
373
  throw error;
374
374
  });
375
375
  },
376
- version: "3.0.0-beta.405"
376
+ version: "3.0.0-beta.406"
377
377
  });
378
378
  var _default = SimultaneousInterpretation;
379
379
  exports.default = _default;
@@ -18,7 +18,7 @@ var SILanguage = _webexCore.WebexPlugin.extend({
18
18
  languageCode: 'number',
19
19
  languageName: 'string'
20
20
  },
21
- version: "3.0.0-beta.405"
21
+ version: "3.0.0-beta.406"
22
22
  });
23
23
  var _default = SILanguage;
24
24
  exports.default = _default;
@@ -356,7 +356,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
356
356
 
357
357
  // Add stats for individual streams
358
358
  (0, _keys.default)(this.statsResults).forEach(function (mediaType) {
359
- if (mediaType.includes('audio-send')) {
359
+ if (mediaType.startsWith('audio-send')) {
360
360
  var audioSenderStream = (0, _cloneDeep2.default)(_config.emptyAudioTransmitStream);
361
361
  (0, _mqaUtil.getAudioSenderStreamMqa)({
362
362
  audioSenderStream: audioSenderStream,
@@ -366,7 +366,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
366
366
  });
367
367
  newMqa.audioTransmit[0].streams.push(audioSenderStream);
368
368
  _this3.lastMqaDataSent[mediaType].send = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].send);
369
- } else if (mediaType.includes('audio-share-send')) {
369
+ } else if (mediaType.startsWith('audio-share-send')) {
370
370
  var _audioSenderStream = (0, _cloneDeep2.default)(_config.emptyAudioTransmitStream);
371
371
  (0, _mqaUtil.getAudioSenderStreamMqa)({
372
372
  audioSenderStream: _audioSenderStream,
@@ -376,7 +376,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
376
376
  });
377
377
  newMqa.audioTransmit[1].streams.push(_audioSenderStream);
378
378
  _this3.lastMqaDataSent[mediaType].send = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].send);
379
- } else if (mediaType.includes('audio-recv')) {
379
+ } else if (mediaType.startsWith('audio-recv')) {
380
380
  var audioReceiverStream = (0, _cloneDeep2.default)(_config.emptyAudioReceiveStream);
381
381
  (0, _mqaUtil.getAudioReceiverStreamMqa)({
382
382
  audioReceiverStream: audioReceiverStream,
@@ -386,7 +386,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
386
386
  });
387
387
  newMqa.audioReceive[0].streams.push(audioReceiverStream);
388
388
  _this3.lastMqaDataSent[mediaType].recv = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].recv);
389
- } else if (mediaType.includes('audio-share-recv')) {
389
+ } else if (mediaType.startsWith('audio-share-recv')) {
390
390
  var _audioReceiverStream = (0, _cloneDeep2.default)(_config.emptyAudioReceiveStream);
391
391
  (0, _mqaUtil.getAudioReceiverStreamMqa)({
392
392
  audioReceiverStream: _audioReceiverStream,
@@ -396,7 +396,8 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
396
396
  });
397
397
  newMqa.audioReceive[1].streams.push(_audioReceiverStream);
398
398
  _this3.lastMqaDataSent[mediaType].recv = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].recv);
399
- } else if (mediaType.includes('video-send')) {
399
+ } else if (mediaType.startsWith('video-send-layer')) {
400
+ // We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.
400
401
  var videoSenderStream = (0, _cloneDeep2.default)(_config.emptyVideoTransmitStream);
401
402
  (0, _mqaUtil.getVideoSenderStreamMqa)({
402
403
  videoSenderStream: videoSenderStream,
@@ -406,7 +407,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
406
407
  });
407
408
  newMqa.videoTransmit[0].streams.push(videoSenderStream);
408
409
  _this3.lastMqaDataSent[mediaType].send = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].send);
409
- } else if (mediaType.includes('video-share-send')) {
410
+ } else if (mediaType.startsWith('video-share-send')) {
410
411
  var _videoSenderStream = (0, _cloneDeep2.default)(_config.emptyVideoTransmitStream);
411
412
  (0, _mqaUtil.getVideoSenderStreamMqa)({
412
413
  videoSenderStream: _videoSenderStream,
@@ -416,7 +417,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
416
417
  });
417
418
  newMqa.videoTransmit[1].streams.push(_videoSenderStream);
418
419
  _this3.lastMqaDataSent[mediaType].send = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].send);
419
- } else if (mediaType.includes('video-recv')) {
420
+ } else if (mediaType.startsWith('video-recv')) {
420
421
  var videoReceiverStream = (0, _cloneDeep2.default)(_config.emptyVideoReceiveStream);
421
422
  (0, _mqaUtil.getVideoReceiverStreamMqa)({
422
423
  videoReceiverStream: videoReceiverStream,
@@ -426,7 +427,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
426
427
  });
427
428
  newMqa.videoReceive[0].streams.push(videoReceiverStream);
428
429
  _this3.lastMqaDataSent[mediaType].recv = (0, _cloneDeep2.default)(_this3.statsResults[mediaType].recv);
429
- } else if (mediaType.includes('video-share-recv')) {
430
+ } else if (mediaType.startsWith('video-share-recv')) {
430
431
  var _videoReceiverStream = (0, _cloneDeep2.default)(_config.emptyVideoReceiveStream);
431
432
  (0, _mqaUtil.getVideoReceiverStreamMqa)({
432
433
  videoReceiverStream: _videoReceiverStream,
@@ -451,9 +452,12 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
451
452
  name: _constants.MEDIA_DEVICES.MICROPHONE
452
453
  });
453
454
  }
454
- if (this.statsResults['video-send']) {
455
+ var existingVideoSender = (0, _keys.default)(this.statsResults).find(function (item) {
456
+ return item.includes('video-send');
457
+ });
458
+ if (existingVideoSender) {
455
459
  newMqa.intervalMetadata.peripherals.push({
456
- information: this.statsResults['video-send'].trackLabel || _constants._UNKNOWN_,
460
+ information: this.statsResults[existingVideoSender].trackLabel || _constants._UNKNOWN_,
457
461
  name: _constants.MEDIA_DEVICES.CAMERA
458
462
  });
459
463
  }
@@ -627,9 +631,20 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
627
631
  _this6.successfulCandidatePair = report;
628
632
  }
629
633
  });
634
+ var videoSenderIndex = 0;
630
635
  statsItem.report.forEach(function (result) {
631
636
  if (types.includes(result.type)) {
632
- _this6.parseGetStatsResult(result, type, isSender);
637
+ // if the video sender has multiple streams in the report, it is a new stream object.
638
+ if (type === 'video-send' && result.type === 'outbound-rtp') {
639
+ var newType = "video-send-layer-".concat(videoSenderIndex);
640
+ _this6.parseGetStatsResult(result, newType, isSender);
641
+ videoSenderIndex += 1;
642
+ _this6.statsResults[newType].direction = statsItem.currentDirection;
643
+ _this6.statsResults[newType].trackLabel = statsItem.localTrackLabel;
644
+ _this6.statsResults[newType].csi = statsItem.csi;
645
+ } else {
646
+ _this6.parseGetStatsResult(result, type, isSender);
647
+ }
633
648
  }
634
649
  });
635
650
  if (this.statsResults[type]) {
@@ -693,7 +708,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
693
708
  return key.startsWith(keyPrefix);
694
709
  }).reduce(function (prev, cur) {
695
710
  var _this7$statsResults$c;
696
- return prev + (((_this7$statsResults$c = _this7.statsResults[cur]) === null || _this7$statsResults$c === void 0 ? void 0 : _this7$statsResults$c.recv[value]) || 0);
711
+ return prev + (((_this7$statsResults$c = _this7.statsResults[cur]) === null || _this7$statsResults$c === void 0 ? void 0 : _this7$statsResults$c[keyPrefix.includes('send') ? 'send' : 'recv'][value]) || 0);
697
712
  }, 0);
698
713
  };
699
714
  var getPreviousStatsTotals = function getPreviousStatsTotals(keyPrefix, value) {
@@ -701,7 +716,7 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
701
716
  return key.startsWith(keyPrefix);
702
717
  }).reduce(function (prev, cur) {
703
718
  var _this7$lastStatsResul;
704
- return prev + (((_this7$lastStatsResul = _this7.lastStatsResults[cur]) === null || _this7$lastStatsResul === void 0 ? void 0 : _this7$lastStatsResul.recv[value]) || 0);
719
+ return prev + (((_this7$lastStatsResul = _this7.lastStatsResults[cur]) === null || _this7$lastStatsResul === void 0 ? void 0 : _this7$lastStatsResul[keyPrefix.includes('send') ? 'send' : 'recv'][value]) || 0);
705
720
  }, 0);
706
721
  };
707
722
 
@@ -728,23 +743,31 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
728
743
  var currentAudioPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
729
744
  var previousAudioPacketsReceived = getPreviousStatsTotals('audio-recv', 'totalPacketsReceived');
730
745
  this.emitStartStopEvents('audio', previousAudioPacketsReceived, currentAudioPacketsReceived, false);
746
+ var currentTotalPacketsSent = getCurrentStatsTotals('video-send', 'totalPacketsSent');
747
+ var previousTotalPacketsSent = getPreviousStatsTotals('video-send', 'totalPacketsSent');
748
+ var currentFramesEncoded = getCurrentStatsTotals('video-send', 'framesEncoded');
749
+ var previousFramesEncoded = getPreviousStatsTotals('video-send', 'framesEncoded');
750
+ var currentFramesSent = getCurrentStatsTotals('video-send', 'framesSent');
751
+ var previousFramesSent = getPreviousStatsTotals('video-send', 'framesSent');
752
+ var doesVideoSendExist = (0, _keys.default)(this.lastStatsResults).some(function (item) {
753
+ return item.includes('video-send');
754
+ });
731
755
 
732
756
  // Video Transmit
733
- if (this.lastStatsResults['video-send']) {
757
+ if (doesVideoSendExist) {
734
758
  // compare video stats sent
735
- var _currentStats = this.statsResults['video-send'].send;
736
- var _previousStats = this.lastStatsResults['video-send'].send;
737
- if (this.meetingMediaStatus.expected.sendVideo && (_currentStats.totalPacketsSent === _previousStats.totalPacketsSent || _currentStats.totalPacketsSent === 0)) {
738
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent", _currentStats.totalPacketsSent);
759
+
760
+ if (this.meetingMediaStatus.expected.sendVideo && (currentTotalPacketsSent === previousTotalPacketsSent || currentTotalPacketsSent === 0)) {
761
+ _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent", currentTotalPacketsSent);
739
762
  } else {
740
- if (this.meetingMediaStatus.expected.sendVideo && (_currentStats.framesEncoded === _previousStats.framesEncoded || _currentStats.framesEncoded === 0)) {
741
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded", _currentStats.framesEncoded);
763
+ if (this.meetingMediaStatus.expected.sendVideo && (currentFramesEncoded === previousFramesEncoded || currentFramesEncoded === 0)) {
764
+ _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded", currentFramesEncoded);
742
765
  }
743
- if (this.meetingMediaStatus.expected.sendVideo && (this.statsResults['video-send'].send.framesSent === this.lastStatsResults['video-send'].send.framesSent || this.statsResults['video-send'].send.framesSent === 0)) {
744
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent", this.statsResults['video-send'].send.framesSent);
766
+ if (this.meetingMediaStatus.expected.sendVideo && (currentFramesSent === previousFramesSent || currentFramesSent === 0)) {
767
+ _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent", currentFramesSent);
745
768
  }
746
769
  }
747
- this.emitStartStopEvents('video', _previousStats.framesSent, _currentStats.framesSent, true);
770
+ this.emitStartStopEvents('video', previousFramesSent, currentFramesSent, true);
748
771
  }
749
772
 
750
773
  // Video Receive
@@ -756,19 +779,19 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
756
779
  if (this.lastStatsResults['video-share-send']) {
757
780
  // compare share stats sent
758
781
 
759
- var _currentStats2 = this.statsResults['video-share-send'].send;
760
- var _previousStats2 = this.lastStatsResults['video-share-send'].send;
761
- if (this.meetingMediaStatus.expected.sendShare && (_currentStats2.totalPacketsSent === _previousStats2.totalPacketsSent || _currentStats2.totalPacketsSent === 0)) {
762
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent", _currentStats2.totalPacketsSent);
782
+ var _currentStats = this.statsResults['video-share-send'].send;
783
+ var _previousStats = this.lastStatsResults['video-share-send'].send;
784
+ if (this.meetingMediaStatus.expected.sendShare && (_currentStats.totalPacketsSent === _previousStats.totalPacketsSent || _currentStats.totalPacketsSent === 0)) {
785
+ _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent", _currentStats.totalPacketsSent);
763
786
  } else {
764
- if (this.meetingMediaStatus.expected.sendShare && (_currentStats2.framesEncoded === _previousStats2.framesEncoded || _currentStats2.framesEncoded === 0)) {
765
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded", _currentStats2.framesEncoded);
787
+ if (this.meetingMediaStatus.expected.sendShare && (_currentStats.framesEncoded === _previousStats.framesEncoded || _currentStats.framesEncoded === 0)) {
788
+ _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded", _currentStats.framesEncoded);
766
789
  }
767
790
  if (this.meetingMediaStatus.expected.sendShare && (this.statsResults['video-share-send'].send.framesSent === this.lastStatsResults['video-share-send'].send.framesSent || this.statsResults['video-share-send'].send.framesSent === 0)) {
768
791
  _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames sent", this.statsResults['video-share-send'].send.framesSent);
769
792
  }
770
793
  }
771
- this.emitStartStopEvents('share', _previousStats2.framesSent, _currentStats2.framesSent, true);
794
+ this.emitStartStopEvents('share', _previousStats.framesSent, _currentStats.framesSent, true);
772
795
  }
773
796
 
774
797
  // Share receive
@@ -1 +1 @@
1
- {"version":3,"names":["EVENTS","MEDIA_QUALITY","LOCAL_MEDIA_STARTED","LOCAL_MEDIA_STOPPED","REMOTE_MEDIA_STARTED","REMOTE_MEDIA_STOPPED","emptySender","trackLabel","maxPacketLossRatio","availableBandwidth","bytesSent","meanRemoteJitter","meanRoundTripTime","emptyReceiver","bytesReceived","meanRtpJitter","StatsAnalyzer","config","receiveSlotCallback","undefined","networkQualityMonitor","statsResults","defaultStats","mediaType","previousValue","currentValue","isLocal","Error","lastEmittedStartStopEvent","lastEmittedEvent","local","remote","newEvent","emit","file","function","type","successfulCandidatePairId","candidates","newIpAddress","localCandidate","candidateType","address","relayProtocol","relatedAddress","localIpAddress","result","isSender","isRemote","id","successfulCandidatePair","localCandidateId","transport","toUpperCase","protocol","sendRecvType","STATS","SEND_DIRECTION","RECEIVE_DIRECTION","ipType","REMOTE","LOCAL","ipAddress","ip","relatedPort","portNumber","port","networkType","priority","timestamp","time","connectionType","NETWORK_TYPE","VPN","UNKNOWN","totalRoundTripTime","statsStarted","lastStatsResults","correlationId","mqaSentCount","lastMqaDataSent","forEach","includes","recv","send","status","meetingMediaStatus","actual","expected","newMqa","emptyMqaInterval","audioSender","emptyAudioTransmit","audioShareSender","audioReceiver","emptyAudioReceive","audioShareReceiver","videoSender","emptyVideoTransmit","videoShareSender","videoReceiver","emptyVideoReceive","videoShareReceiver","getAudioSenderMqa","baseMediaType","audioTransmit","push","getAudioReceiverMqa","audioReceive","getVideoSenderMqa","videoTransmit","getVideoReceiverMqa","videoReceive","audioSenderStream","emptyAudioTransmitStream","getAudioSenderStreamMqa","streams","audioReceiverStream","emptyAudioReceiveStream","getAudioReceiverStreamMqa","videoSenderStream","emptyVideoTransmitStream","getVideoSenderStreamMqa","videoReceiverStream","emptyVideoReceiveStream","getVideoReceiverStreamMqa","intervalMetadata","peerReflexiveIP","peripherals","information","_UNKNOWN_","name","MEDIA_DEVICES","SPEAKER","MICROPHONE","CAMERA","intervalNumber","resetStatsResults","data","mediaConnection","getStatsAndParse","then","statsInterval","setInterval","analyzerInterval","sendMqaData","mqaInterval","MQA_INTERVAL","resolve","sendOneLastMqa","clearInterval","getStatsResult","processOutboundRTPResult","processInboundRTPResult","compareSentAndReceived","parseCandidate","parseAudioSource","statsItem","types","DEFAULT_GET_STATS_FILTER","report","state","parseGetStatsResult","direction","currentDirection","localTrackLabel","csi","extractAndSetLocalIpAddressInfoForDiagnostics","audioLevel","totalAudioEnergy","getCurrentStatsTotals","keyPrefix","value","filter","key","startsWith","reduce","prev","cur","getPreviousStatsTotals","currentStats","previousStats","sendAudio","totalPacketsSent","LoggerProxy","logger","info","emitStartStopEvents","currentAudioPacketsReceived","previousAudioPacketsReceived","sendVideo","framesEncoded","framesSent","currentVideoFramesDecoded","previousVideoFramesDecoded","sendShare","currentShareFramesDecoded","previousShareFramesDecoded","getConnectionState","ConnectionState","Failed","trace","getTransceiverStats","transceiverStats","video","receivers","receiver","i","filterAndParseGetStatsResults","audio","screenShareVideo","screenShareAudio","senders","sender","compareLastStatsResult","JSON","parse","sendrecvType","kilobytes","frameWidth","frameHeight","width","height","hugeFramesSent","toFixed","keyFramesEncoded","packetsSent","totalKeyFramesEncoded","totalNackCount","nackCount","totalPliCount","pliCount","totalFirCount","firCount","encoderImplementation","qualityLimitationReason","qualityLimitationResolutionChanges","retransmittedPacketsSent","totalBytesSent","headerBytesSent","retransmittedBytesSent","receiveSlot","ssrc","sourceState","idAndCsi","bytes","totalBytesReceived","currentPacketsLost","packetsLost","totalPacketsLost","packetsReceivedDiff","packetsReceived","totalPacketsReceived","videoFramesReceivedDiff","framesReceived","videoFramesDecodedDiff","framesDecoded","videoFramesDroppedDiff","framesDropped","currentPacketLossRatio","lastPacketReceivedTimestamp","keyFramesDecoded","decoderImplementation","fecPacketsDiscarded","fecPacketsReceived","headerBytesReceived","jitter","totalSamplesReceived","totalSamplesDecoded","concealedSamples","currentPacketLoss","totalPacketsLostOnReceiver","packetsLostOnReceiver","roundTripTime","reportsReceived","overAllPacketLossRatio","determineUplinkNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","EventsScope"],"sources":["index.ts"],"sourcesContent":["/* eslint-disable prefer-destructuring */\n\nimport {cloneDeep, isEmpty} from 'lodash';\nimport {ConnectionState} from '@webex/internal-media-core';\n\nimport EventsScope from '../common/events/events-scope';\nimport {\n DEFAULT_GET_STATS_FILTER,\n STATS,\n MQA_INTERVAL,\n NETWORK_TYPE,\n MEDIA_DEVICES,\n _UNKNOWN_,\n} from '../constants';\nimport {\n emptyAudioReceive,\n emptyAudioTransmit,\n emptyMqaInterval,\n emptyVideoReceive,\n emptyVideoTransmit,\n emptyAudioReceiveStream,\n emptyAudioTransmitStream,\n emptyVideoReceiveStream,\n emptyVideoTransmitStream,\n} from '../mediaQualityMetrics/config';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport defaultStats from './global';\nimport {\n getAudioSenderMqa,\n getAudioReceiverMqa,\n getVideoSenderMqa,\n getVideoReceiverMqa,\n getAudioSenderStreamMqa,\n getAudioReceiverStreamMqa,\n getVideoSenderStreamMqa,\n getVideoReceiverStreamMqa,\n} from './mqaUtil';\nimport {ReceiveSlot} from '../multistream/receiveSlot';\n\nexport const EVENTS = {\n MEDIA_QUALITY: 'MEDIA_QUALITY',\n LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',\n LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',\n REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',\n REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',\n};\n\nconst emptySender = {\n trackLabel: '',\n maxPacketLossRatio: 0,\n availableBandwidth: 0,\n bytesSent: 0,\n meanRemoteJitter: [],\n meanRoundTripTime: [],\n};\n\nconst emptyReceiver = {\n availableBandwidth: 0,\n bytesReceived: 0,\n meanRtpJitter: [],\n meanRoundTripTime: [],\n};\n\ntype ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;\ntype MediaStatus = {\n actual?: any;\n expected?: any;\n};\n/**\n * Stats Analyzer class that will emit events based on detected quality\n *\n * @export\n * @class StatsAnalyzer\n * @extends {EventsScope}\n */\nexport class StatsAnalyzer extends EventsScope {\n config: any;\n correlationId: any;\n lastEmittedStartStopEvent: any;\n lastMqaDataSent: any;\n lastStatsResults: any;\n meetingMediaStatus: any;\n mqaInterval: NodeJS.Timeout;\n mqaSentCount: any;\n networkQualityMonitor: any;\n mediaConnection: any;\n statsInterval: NodeJS.Timeout;\n statsResults: any;\n statsStarted: any;\n successfulCandidatePair: any;\n localIpAddress: string; // Returns the local IP address for diagnostics. this is the local IP of the interface used for the current media connection a host can have many local Ip Addresses\n receiveSlotCallback: ReceiveSlotCallback;\n\n /**\n * Creates a new instance of StatsAnalyzer\n * @constructor\n * @public\n * @param {Object} config SDK Configuration Object\n * @param {Function} receiveSlotCallback Callback used to access receive slots.\n * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)\n * @param {Object} statsResults Default properties for stats\n */\n constructor(\n config: any,\n receiveSlotCallback: ReceiveSlotCallback = () => undefined,\n networkQualityMonitor: object = {},\n statsResults: object = defaultStats\n ) {\n super();\n this.statsStarted = false;\n this.statsResults = statsResults;\n this.lastStatsResults = null;\n this.config = config;\n this.networkQualityMonitor = networkQualityMonitor;\n this.correlationId = config.correlationId;\n this.mqaSentCount = -1;\n this.lastMqaDataSent = {};\n this.lastEmittedStartStopEvent = {};\n this.receiveSlotCallback = receiveSlotCallback;\n this.successfulCandidatePair = {};\n this.localIpAddress = '';\n }\n\n /**\n * Resets cumulative stats arrays.\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n resetStatsResults() {\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('recv')) {\n this.statsResults[mediaType].recv.meanRtpJitter = [];\n }\n\n if (mediaType.includes('send')) {\n this.statsResults[mediaType].send.meanRemoteJitter = [];\n this.statsResults[mediaType].send.meanRoundTripTime = [];\n }\n });\n }\n\n /**\n * sets mediaStatus status for analyzing metrics\n *\n * @public\n * @param {Object} status for the audio and video\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public updateMediaStatus(status: MediaStatus) {\n this.meetingMediaStatus = {\n actual: {\n ...this.meetingMediaStatus?.actual,\n ...status?.actual,\n },\n expected: {\n ...this.meetingMediaStatus?.expected,\n ...status?.expected,\n },\n };\n }\n\n /**\n * captures MQA data from media connection\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n sendMqaData() {\n const newMqa = cloneDeep(emptyMqaInterval);\n\n // Fill in empty stats items for lastMqaDataSent\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (!this.lastMqaDataSent[mediaType]) {\n this.lastMqaDataSent[mediaType] = {};\n }\n\n if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {\n this.lastMqaDataSent[mediaType].send = {};\n }\n\n if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {\n this.lastMqaDataSent[mediaType].recv = {};\n }\n });\n\n // Create stats the first level, totals for senders and receivers\n const audioSender = cloneDeep(emptyAudioTransmit);\n const audioShareSender = cloneDeep(emptyAudioTransmit);\n const audioReceiver = cloneDeep(emptyAudioReceive);\n const audioShareReceiver = cloneDeep(emptyAudioReceive);\n const videoSender = cloneDeep(emptyVideoTransmit);\n const videoShareSender = cloneDeep(emptyVideoTransmit);\n const videoReceiver = cloneDeep(emptyVideoReceive);\n const videoShareReceiver = cloneDeep(emptyVideoReceive);\n\n getAudioSenderMqa({\n audioSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-send',\n });\n newMqa.audioTransmit.push(audioSender);\n\n getAudioSenderMqa({\n audioSender: audioShareSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-share-send',\n });\n newMqa.audioTransmit.push(audioShareSender);\n\n getAudioReceiverMqa({\n audioReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-recv',\n });\n newMqa.audioReceive.push(audioReceiver);\n\n getAudioReceiverMqa({\n audioReceiver: audioShareReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-share-recv',\n });\n newMqa.audioReceive.push(audioShareReceiver);\n\n getVideoSenderMqa({\n videoSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-send',\n });\n newMqa.videoTransmit.push(videoSender);\n\n getVideoSenderMqa({\n videoSender: videoShareSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-share-send',\n });\n newMqa.videoTransmit.push(videoShareSender);\n\n getVideoReceiverMqa({\n videoReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-recv',\n });\n newMqa.videoReceive.push(videoReceiver);\n\n getVideoReceiverMqa({\n videoReceiver: videoShareReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-share-recv',\n });\n newMqa.videoReceive.push(videoShareReceiver);\n\n // Add stats for individual streams\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('audio-send')) {\n const audioSenderStream = cloneDeep(emptyAudioTransmitStream);\n\n getAudioSenderStreamMqa({\n audioSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit[0].streams.push(audioSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.includes('audio-share-send')) {\n const audioSenderStream = cloneDeep(emptyAudioTransmitStream);\n\n getAudioSenderStreamMqa({\n audioSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit[1].streams.push(audioSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.includes('audio-recv')) {\n const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);\n\n getAudioReceiverStreamMqa({\n audioReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive[0].streams.push(audioReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.includes('audio-share-recv')) {\n const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);\n\n getAudioReceiverStreamMqa({\n audioReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive[1].streams.push(audioReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.includes('video-send')) {\n const videoSenderStream = cloneDeep(emptyVideoTransmitStream);\n\n getVideoSenderStreamMqa({\n videoSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit[0].streams.push(videoSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.includes('video-share-send')) {\n const videoSenderStream = cloneDeep(emptyVideoTransmitStream);\n\n getVideoSenderStreamMqa({\n videoSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit[1].streams.push(videoSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.includes('video-recv')) {\n const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);\n\n getVideoReceiverStreamMqa({\n videoReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive[0].streams.push(videoReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.includes('video-share-recv')) {\n const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);\n\n getVideoReceiverStreamMqa({\n videoReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive[1].streams.push(videoReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n }\n });\n\n newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;\n\n // Adding peripheral information\n newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});\n if (this.statsResults['audio-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['audio-send'].trackLabel || _UNKNOWN_,\n name: MEDIA_DEVICES.MICROPHONE,\n });\n }\n if (this.statsResults['video-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['video-send'].trackLabel || _UNKNOWN_,\n name: MEDIA_DEVICES.CAMERA,\n });\n }\n\n newMqa.networkType = this.statsResults.connectionType.local.networkType;\n\n this.mqaSentCount += 1;\n\n newMqa.intervalNumber = this.mqaSentCount;\n\n this.resetStatsResults();\n\n this.emit(\n {\n file: 'statsAnalyzer',\n function: 'sendMqaData',\n },\n EVENTS.MEDIA_QUALITY,\n {\n data: newMqa,\n // @ts-ignore\n networkType: newMqa.networkType,\n }\n );\n }\n\n /**\n * updated the media connection when changed\n *\n * @private\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {void}\n */\n updateMediaConnection(mediaConnection: any) {\n this.mediaConnection = mediaConnection;\n }\n\n /**\n * Returns the local IP address for diagnostics.\n * this is the local IP of the interface used for the current media connection\n * a host can have many local Ip Addresses\n * @returns {string | undefined} The local IP address.\n */\n getLocalIpAddress(): string {\n return this.localIpAddress;\n }\n\n /**\n * Starts the stats analyzer on interval\n *\n * @public\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {Promise}\n */\n public startAnalyzer(mediaConnection: any) {\n if (!this.statsStarted) {\n this.statsStarted = true;\n this.mediaConnection = mediaConnection;\n\n return this.getStatsAndParse().then(() => {\n this.statsInterval = setInterval(() => {\n this.getStatsAndParse();\n }, this.config.analyzerInterval);\n // Trigger initial fetch\n this.sendMqaData();\n this.mqaInterval = setInterval(() => {\n this.sendMqaData();\n }, MQA_INTERVAL);\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Cleans up the analyzer when done\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public stopAnalyzer() {\n const sendOneLastMqa = this.mqaInterval && this.statsInterval;\n\n if (this.statsInterval) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n\n if (this.mqaInterval) {\n clearInterval(this.mqaInterval);\n this.mqaInterval = undefined;\n }\n\n if (sendOneLastMqa) {\n return this.getStatsAndParse().then(() => {\n this.sendMqaData();\n this.mediaConnection = null;\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Parse a single result of get stats\n *\n * @private\n * @param {*} getStatsResult\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private parseGetStatsResult(getStatsResult: any, type: string, isSender: boolean) {\n if (!getStatsResult) {\n return;\n }\n\n // Generate empty stats results\n if (!this.statsResults[type]) {\n this.statsResults[type] = {};\n }\n\n if (isSender && !this.statsResults[type].send) {\n this.statsResults[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults[type].recv) {\n this.statsResults[type].recv = cloneDeep(emptyReceiver);\n }\n\n switch (getStatsResult.type) {\n case 'outbound-rtp':\n this.processOutboundRTPResult(getStatsResult, type);\n break;\n case 'inbound-rtp':\n this.processInboundRTPResult(getStatsResult, type);\n break;\n case 'remote-inbound-rtp':\n case 'remote-outbound-rtp':\n this.compareSentAndReceived(getStatsResult, type);\n break;\n case 'remotecandidate':\n case 'remote-candidate':\n this.parseCandidate(getStatsResult, type, isSender, true);\n break;\n case 'local-candidate':\n this.parseCandidate(getStatsResult, type, isSender, false);\n break;\n case 'media-source':\n this.parseAudioSource(getStatsResult, type);\n break;\n default:\n break;\n }\n }\n\n /**\n * Filters the get stats results for types\n * @private\n * @param {Array} statsItem\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n */\n filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {\n const {types} = DEFAULT_GET_STATS_FILTER;\n\n // get the successful candidate pair before parsing stats.\n statsItem.report.forEach((report) => {\n if (report.type === 'candidate-pair' && report.state === 'succeeded') {\n this.successfulCandidatePair = report;\n }\n });\n\n statsItem.report.forEach((result) => {\n if (types.includes(result.type)) {\n this.parseGetStatsResult(result, type, isSender);\n }\n });\n\n if (this.statsResults[type]) {\n this.statsResults[type].direction = statsItem.currentDirection;\n this.statsResults[type].trackLabel = statsItem.localTrackLabel;\n this.statsResults[type].csi = statsItem.csi;\n this.extractAndSetLocalIpAddressInfoForDiagnostics(\n this.successfulCandidatePair?.localCandidateId,\n this.statsResults?.candidates\n );\n // reset the successful candidate pair.\n this.successfulCandidatePair = {};\n }\n }\n\n /**\n * parse the audio\n * @param {String} result\n * @param {boolean} type\n * @returns {void}\n */\n parseAudioSource(result: any, type: any) {\n if (!result) {\n return;\n }\n\n if (type.includes('audio-send')) {\n this.statsResults[type].send.audioLevel = result.audioLevel;\n this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;\n }\n }\n\n /**\n * emits started/stopped events for local/remote media by checking\n * if given values are increasing or not. The previousValue, currentValue\n * params can be any numerical value like number of receive packets or\n * decoded frames, etc.\n *\n * @private\n * @param {string} mediaType\n * @param {number} previousValue - value to compare\n * @param {number} currentValue - value to compare (must be same type of value as previousValue)\n * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n emitStartStopEvents = (\n mediaType: string,\n previousValue: number,\n currentValue: number,\n isLocal: boolean\n ) => {\n if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {\n throw new Error(`Unsupported mediaType: ${mediaType}`);\n }\n\n // eslint-disable-next-line no-param-reassign\n if (previousValue === undefined) previousValue = 0;\n // eslint-disable-next-line no-param-reassign\n if (currentValue === undefined) currentValue = 0;\n\n if (!this.lastEmittedStartStopEvent[mediaType]) {\n this.lastEmittedStartStopEvent[mediaType] = {};\n }\n\n const lastEmittedEvent = isLocal\n ? this.lastEmittedStartStopEvent[mediaType].local\n : this.lastEmittedStartStopEvent[mediaType].remote;\n\n let newEvent;\n\n if (currentValue - previousValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;\n } else if (currentValue === previousValue && currentValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;\n }\n\n if (newEvent && lastEmittedEvent !== newEvent) {\n if (isLocal) {\n this.lastEmittedStartStopEvent[mediaType].local = newEvent;\n } else {\n this.lastEmittedStartStopEvent[mediaType].remote = newEvent;\n }\n this.emit(\n {\n file: 'statsAnalyzer/index',\n function: 'compareLastStatsResult',\n },\n newEvent,\n {\n type: mediaType,\n }\n );\n }\n };\n\n /**\n * compares current and previous stats to check if packets are not sent\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n private compareLastStatsResult() {\n if (this.lastStatsResults !== null && this.meetingMediaStatus) {\n const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);\n\n const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);\n\n // Audio Transmit\n if (this.lastStatsResults['audio-send']) {\n // compare audio stats sent\n // NOTE: relies on there being only one sender.\n const currentStats = this.statsResults['audio-send'].send;\n const previousStats = this.lastStatsResults['audio-send'].send;\n\n if (\n (this.meetingMediaStatus.expected.sendAudio &&\n currentStats.totalPacketsSent === previousStats.totalPacketsSent) ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,\n currentStats.totalPacketsSent\n );\n } else {\n if (\n (this.meetingMediaStatus.expected.sendAudio &&\n currentStats.totalAudioEnergy === previousStats.totalAudioEnergy) ||\n currentStats.totalAudioEnergy === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,\n currentStats.totalAudioEnergy\n );\n }\n\n if (this.meetingMediaStatus.expected.sendAudio && currentStats.audioLevel === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`\n );\n }\n }\n\n this.emitStartStopEvents(\n 'audio',\n previousStats.totalPacketsSent,\n currentStats.totalPacketsSent,\n true\n );\n }\n\n // Audio Receive\n const currentAudioPacketsReceived = getCurrentStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n const previousAudioPacketsReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n\n this.emitStartStopEvents(\n 'audio',\n previousAudioPacketsReceived,\n currentAudioPacketsReceived,\n false\n );\n\n // Video Transmit\n if (this.lastStatsResults['video-send']) {\n // compare video stats sent\n const currentStats = this.statsResults['video-send'].send;\n const previousStats = this.lastStatsResults['video-send'].send;\n\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,\n currentStats.totalPacketsSent\n );\n } else {\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,\n currentStats.framesEncoded\n );\n }\n\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (this.statsResults['video-send'].send.framesSent ===\n this.lastStatsResults['video-send'].send.framesSent ||\n this.statsResults['video-send'].send.framesSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,\n this.statsResults['video-send'].send.framesSent\n );\n }\n }\n\n this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);\n }\n\n // Video Receive\n const currentVideoFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');\n const previousVideoFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');\n\n this.emitStartStopEvents(\n 'video',\n previousVideoFramesDecoded,\n currentVideoFramesDecoded,\n false\n );\n\n // Share Transmit\n if (this.lastStatsResults['video-share-send']) {\n // compare share stats sent\n\n const currentStats = this.statsResults['video-share-send'].send;\n const previousStats = this.lastStatsResults['video-share-send'].send;\n\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,\n currentStats.totalPacketsSent\n );\n } else {\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,\n currentStats.framesEncoded\n );\n }\n\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (this.statsResults['video-share-send'].send.framesSent ===\n this.lastStatsResults['video-share-send'].send.framesSent ||\n this.statsResults['video-share-send'].send.framesSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,\n this.statsResults['video-share-send'].send.framesSent\n );\n }\n }\n\n this.emitStartStopEvents('share', previousStats.framesSent, currentStats.framesSent, true);\n }\n\n // Share receive\n const currentShareFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');\n const previousShareFramesDecoded = getPreviousStatsTotals(\n 'video-share-recv',\n 'framesDecoded'\n );\n\n this.emitStartStopEvents(\n 'share',\n previousShareFramesDecoded,\n currentShareFramesDecoded,\n false\n );\n }\n }\n\n /**\n * Does a `getStats` on all the transceivers and parses the results\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {Promise}\n */\n private getStatsAndParse() {\n if (!this.mediaConnection) {\n return Promise.resolve();\n }\n\n if (\n this.mediaConnection &&\n this.mediaConnection.getConnectionState() === ConnectionState.Failed\n ) {\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'\n );\n\n return Promise.resolve();\n }\n\n LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');\n\n return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {\n transceiverStats.video.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)\n );\n transceiverStats.audio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)\n );\n transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)\n );\n transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)\n );\n\n transceiverStats.video.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-send', true);\n });\n transceiverStats.audio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-send', true);\n });\n transceiverStats.screenShareVideo.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-share-send', true);\n });\n transceiverStats.screenShareAudio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);\n });\n\n this.compareLastStatsResult();\n\n // Save the last results to compare with the current\n // DO Deep copy, for some reason it takes the reference all the time rather then old value set\n this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));\n\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats'\n );\n });\n }\n\n /**\n * Processes OutboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processOutboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.SEND_DIRECTION;\n\n if (result.bytesSent) {\n const kilobytes = 0;\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;\n }\n\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;\n\n // Data saved to send MQA metrics\n\n this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;\n this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].encoderImplementation =\n result.encoderImplementation;\n this.statsResults[mediaType][sendrecvType].qualityLimitationReason =\n result.qualityLimitationReason;\n this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =\n result.qualityLimitationResolutionChanges;\n this.statsResults[mediaType][sendrecvType].retransmittedPacketsSent =\n result.retransmittedPacketsSent;\n this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;\n this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;\n this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =\n result.retransmittedBytesSent;\n }\n }\n\n /**\n * Processes InboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processInboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.RECEIVE_DIRECTION;\n\n if (result.bytesReceived) {\n let kilobytes = 0;\n const receiveSlot = this.receiveSlotCallback(result.ssrc);\n const sourceState = receiveSlot?.sourceState;\n const idAndCsi = receiveSlot\n ? `id: \"${receiveSlot.id || ''}\"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`\n : '';\n\n const bytes =\n result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;\n\n kilobytes = bytes / 1024;\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n\n let currentPacketsLost =\n result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;\n if (currentPacketsLost < 0) {\n currentPacketsLost = 0;\n }\n const packetsReceivedDiff =\n result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n if (packetsReceivedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No packets received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total packets received on slot: `,\n result.packetsReceived\n );\n }\n }\n\n if (mediaType.startsWith('video') || mediaType.startsWith('share')) {\n const videoFramesReceivedDiff =\n result.framesReceived - this.statsResults[mediaType][sendrecvType].framesReceived;\n\n if (videoFramesReceivedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No frames received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames received on slot: `,\n result.framesReceived\n );\n }\n }\n\n const videoFramesDecodedDiff =\n result.framesDecoded - this.statsResults[mediaType][sendrecvType].framesDecoded;\n\n if (videoFramesDecodedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No frames decoded for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames decoded on slot: `,\n result.framesDecoded\n );\n }\n }\n\n const videoFramesDroppedDiff =\n result.framesDropped - this.statsResults[mediaType][sendrecvType].framesDropped;\n\n if (videoFramesDroppedDiff > 10) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> Frames dropped for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames dropped on slot: `,\n result.framesDropped\n );\n }\n }\n }\n\n // Check the over all packet Lost ratio\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =\n currentPacketsLost > 0\n ? currentPacketsLost / (packetsReceivedDiff + currentPacketsLost)\n : 0;\n if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio\n );\n }\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;\n }\n\n // TODO: check the packet loss value is negative values here\n\n if (result.packetsLost) {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost =\n result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;\n } else {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n\n // From Thin\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;\n this.statsResults[mediaType][sendrecvType].framesDropped = result.framesDropped;\n\n this.statsResults[mediaType][sendrecvType].decoderImplementation =\n result.decoderImplementation;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;\n this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;\n this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;\n\n this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);\n\n // Audio stats\n\n this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;\n this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;\n this.statsResults[mediaType][sendrecvType].totalSamplesReceived =\n result.totalSamplesReceived || 0;\n this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =\n result.totalSamplesDecoded || 0;\n this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;\n }\n }\n\n /**\n * extracts the local Ip address from the statsResult object by looking at stats results candidates\n * and matches that ID with the successful candidate pair. It looks at the type of local candidate it is\n * and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc\n * note, there are known incompatibilities and it is possible for this to set undefined, or for the IP address to be the public IP address\n * for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP\n * @private\n * @param {string} successfulCandidatePairId - The ID of the successful candidate pair.\n * @param {Object} candidates - the stats result candidates\n * @returns {void}\n */\n extractAndSetLocalIpAddressInfoForDiagnostics = (\n successfulCandidatePairId: string,\n candidates: {[key: string]: Record<string, unknown>}\n ) => {\n let newIpAddress = '';\n if (successfulCandidatePairId && !isEmpty(candidates)) {\n const localCandidate = candidates[successfulCandidatePairId];\n if (localCandidate) {\n if (localCandidate.candidateType === 'host') {\n // if it's a host candidate, use the address property - it will be the local IP\n newIpAddress = `${localCandidate.address}`;\n } else if (localCandidate.candidateType === 'prflx') {\n // if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)\n // then look at the relatedAddress - it will be the local\n //\n // Firefox doesn't populate the relayProtocol property\n if (!localCandidate.relayProtocol) {\n newIpAddress = `${localCandidate.relatedAddress}`;\n } else {\n // if it's a peer reflexive candidate and we are using a relay -\n // in that case the relatedAddress will be the IP of the TURN server (Linus),\n // so we can only look at the address, but it might be local IP or public IP,\n // depending on if the user is behind a NAT or not\n newIpAddress = `${localCandidate.address}`;\n }\n }\n }\n }\n this.localIpAddress = newIpAddress;\n };\n\n /**\n * Processes remote and local candidate result and stores\n * @private\n * @param {*} result\n * @param {*} type\n * @param {boolean} isSender\n * @param {boolean} isRemote\n *\n * @returns {void}\n */\n parseCandidate = (result: any, type: any, isSender: boolean, isRemote: boolean) => {\n if (!result || !result.id) {\n return;\n }\n\n // We only care about the successful local candidate\n if (this.successfulCandidatePair?.localCandidateId !== result.id) {\n return;\n }\n\n let transport;\n if (result.relayProtocol) {\n transport = result.relayProtocol.toUpperCase();\n } else if (result.protocol) {\n transport = result.protocol.toUpperCase();\n }\n\n const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;\n const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;\n\n if (!this.statsResults.candidates) {\n this.statsResults.candidates = {};\n }\n\n this.statsResults.candidates[result.id] = {\n candidateType: result.candidateType,\n ipAddress: result.ip, // TODO: add ports\n relatedAddress: result.relatedAddress,\n relatedPort: result.relatedPort,\n relayProtocol: result.relayProtocol,\n protocol: result.protocol,\n address: result.address,\n portNumber: result.port,\n networkType: result.networkType,\n priority: result.priority,\n transport,\n timestamp: result.time,\n id: result.id,\n type: result.type,\n };\n\n this.statsResults.connectionType[ipType].candidateType = result.candidateType;\n this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;\n\n this.statsResults.connectionType[ipType].networkType =\n result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;\n this.statsResults.connectionType[ipType].transport = transport;\n\n this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;\n };\n\n /**\n *\n * @private\n * @param {*} result\n * @param {*} type\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n compareSentAndReceived(result, type) {\n // Don't compare on transceivers without a sender.\n if (!type || !this.statsResults[type].send) {\n return;\n }\n\n const mediaType = type;\n\n const currentPacketLoss =\n result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;\n\n this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n\n this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);\n this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);\n\n this.statsResults[mediaType].send.timestamp = result.timestamp;\n this.statsResults[mediaType].send.ssrc = result.ssrc;\n this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;\n\n // Total packloss ratio on this video section of the call\n this.statsResults[mediaType].send.overAllPacketLossRatio =\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0\n ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver /\n this.statsResults[mediaType].send.totalPacketsSent\n : 0;\n this.statsResults[mediaType].send.currentPacketLossRatio =\n this.statsResults[mediaType].send.packetsLostOnReceiver > 0\n ? (this.statsResults[mediaType].send.packetsLostOnReceiver * 100) /\n (this.statsResults[mediaType].send.packetsSent +\n this.statsResults[mediaType].send.packetsLostOnReceiver)\n : 0;\n\n if (\n this.statsResults[mediaType].send.maxPacketLossRatio <\n this.statsResults[mediaType].send.currentPacketLossRatio\n ) {\n this.statsResults[mediaType].send.maxPacketLossRatio =\n this.statsResults[mediaType].send.currentPacketLossRatio;\n }\n\n if (result.type === 'remote-inbound-rtp') {\n this.networkQualityMonitor.determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults: result,\n statsAnalyzerCurrentStats: this.statsResults,\n });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["EVENTS","MEDIA_QUALITY","LOCAL_MEDIA_STARTED","LOCAL_MEDIA_STOPPED","REMOTE_MEDIA_STARTED","REMOTE_MEDIA_STOPPED","emptySender","trackLabel","maxPacketLossRatio","availableBandwidth","bytesSent","meanRemoteJitter","meanRoundTripTime","emptyReceiver","bytesReceived","meanRtpJitter","StatsAnalyzer","config","receiveSlotCallback","undefined","networkQualityMonitor","statsResults","defaultStats","mediaType","previousValue","currentValue","isLocal","Error","lastEmittedStartStopEvent","lastEmittedEvent","local","remote","newEvent","emit","file","function","type","successfulCandidatePairId","candidates","newIpAddress","localCandidate","candidateType","address","relayProtocol","relatedAddress","localIpAddress","result","isSender","isRemote","id","successfulCandidatePair","localCandidateId","transport","toUpperCase","protocol","sendRecvType","STATS","SEND_DIRECTION","RECEIVE_DIRECTION","ipType","REMOTE","LOCAL","ipAddress","ip","relatedPort","portNumber","port","networkType","priority","timestamp","time","connectionType","NETWORK_TYPE","VPN","UNKNOWN","totalRoundTripTime","statsStarted","lastStatsResults","correlationId","mqaSentCount","lastMqaDataSent","forEach","includes","recv","send","status","meetingMediaStatus","actual","expected","newMqa","emptyMqaInterval","audioSender","emptyAudioTransmit","audioShareSender","audioReceiver","emptyAudioReceive","audioShareReceiver","videoSender","emptyVideoTransmit","videoShareSender","videoReceiver","emptyVideoReceive","videoShareReceiver","getAudioSenderMqa","baseMediaType","audioTransmit","push","getAudioReceiverMqa","audioReceive","getVideoSenderMqa","videoTransmit","getVideoReceiverMqa","videoReceive","startsWith","audioSenderStream","emptyAudioTransmitStream","getAudioSenderStreamMqa","streams","audioReceiverStream","emptyAudioReceiveStream","getAudioReceiverStreamMqa","videoSenderStream","emptyVideoTransmitStream","getVideoSenderStreamMqa","videoReceiverStream","emptyVideoReceiveStream","getVideoReceiverStreamMqa","intervalMetadata","peerReflexiveIP","peripherals","information","_UNKNOWN_","name","MEDIA_DEVICES","SPEAKER","MICROPHONE","existingVideoSender","find","item","CAMERA","intervalNumber","resetStatsResults","data","mediaConnection","getStatsAndParse","then","statsInterval","setInterval","analyzerInterval","sendMqaData","mqaInterval","MQA_INTERVAL","resolve","sendOneLastMqa","clearInterval","getStatsResult","processOutboundRTPResult","processInboundRTPResult","compareSentAndReceived","parseCandidate","parseAudioSource","statsItem","types","DEFAULT_GET_STATS_FILTER","report","state","videoSenderIndex","newType","parseGetStatsResult","direction","currentDirection","localTrackLabel","csi","extractAndSetLocalIpAddressInfoForDiagnostics","audioLevel","totalAudioEnergy","getCurrentStatsTotals","keyPrefix","value","filter","key","reduce","prev","cur","getPreviousStatsTotals","currentStats","previousStats","sendAudio","totalPacketsSent","LoggerProxy","logger","info","emitStartStopEvents","currentAudioPacketsReceived","previousAudioPacketsReceived","currentTotalPacketsSent","previousTotalPacketsSent","currentFramesEncoded","previousFramesEncoded","currentFramesSent","previousFramesSent","doesVideoSendExist","some","sendVideo","currentVideoFramesDecoded","previousVideoFramesDecoded","sendShare","framesEncoded","framesSent","currentShareFramesDecoded","previousShareFramesDecoded","getConnectionState","ConnectionState","Failed","trace","getTransceiverStats","transceiverStats","video","receivers","receiver","i","filterAndParseGetStatsResults","audio","screenShareVideo","screenShareAudio","senders","sender","compareLastStatsResult","JSON","parse","sendrecvType","kilobytes","frameWidth","frameHeight","width","height","hugeFramesSent","toFixed","keyFramesEncoded","packetsSent","totalKeyFramesEncoded","totalNackCount","nackCount","totalPliCount","pliCount","totalFirCount","firCount","encoderImplementation","qualityLimitationReason","qualityLimitationResolutionChanges","retransmittedPacketsSent","totalBytesSent","headerBytesSent","retransmittedBytesSent","receiveSlot","ssrc","sourceState","idAndCsi","bytes","totalBytesReceived","currentPacketsLost","packetsLost","totalPacketsLost","packetsReceivedDiff","packetsReceived","totalPacketsReceived","videoFramesReceivedDiff","framesReceived","videoFramesDecodedDiff","framesDecoded","videoFramesDroppedDiff","framesDropped","currentPacketLossRatio","lastPacketReceivedTimestamp","keyFramesDecoded","decoderImplementation","fecPacketsDiscarded","fecPacketsReceived","headerBytesReceived","jitter","totalSamplesReceived","totalSamplesDecoded","concealedSamples","currentPacketLoss","totalPacketsLostOnReceiver","packetsLostOnReceiver","roundTripTime","reportsReceived","overAllPacketLossRatio","determineUplinkNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","EventsScope"],"sources":["index.ts"],"sourcesContent":["/* eslint-disable prefer-destructuring */\n\nimport {cloneDeep, isEmpty} from 'lodash';\nimport {ConnectionState} from '@webex/internal-media-core';\n\nimport EventsScope from '../common/events/events-scope';\nimport {\n DEFAULT_GET_STATS_FILTER,\n STATS,\n MQA_INTERVAL,\n NETWORK_TYPE,\n MEDIA_DEVICES,\n _UNKNOWN_,\n} from '../constants';\nimport {\n emptyAudioReceive,\n emptyAudioTransmit,\n emptyMqaInterval,\n emptyVideoReceive,\n emptyVideoTransmit,\n emptyAudioReceiveStream,\n emptyAudioTransmitStream,\n emptyVideoReceiveStream,\n emptyVideoTransmitStream,\n} from '../mediaQualityMetrics/config';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport defaultStats from './global';\nimport {\n getAudioSenderMqa,\n getAudioReceiverMqa,\n getVideoSenderMqa,\n getVideoReceiverMqa,\n getAudioSenderStreamMqa,\n getAudioReceiverStreamMqa,\n getVideoSenderStreamMqa,\n getVideoReceiverStreamMqa,\n} from './mqaUtil';\nimport {ReceiveSlot} from '../multistream/receiveSlot';\n\nexport const EVENTS = {\n MEDIA_QUALITY: 'MEDIA_QUALITY',\n LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',\n LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',\n REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',\n REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',\n};\n\nconst emptySender = {\n trackLabel: '',\n maxPacketLossRatio: 0,\n availableBandwidth: 0,\n bytesSent: 0,\n meanRemoteJitter: [],\n meanRoundTripTime: [],\n};\n\nconst emptyReceiver = {\n availableBandwidth: 0,\n bytesReceived: 0,\n meanRtpJitter: [],\n meanRoundTripTime: [],\n};\n\ntype ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;\ntype MediaStatus = {\n actual?: any;\n expected?: any;\n};\n/**\n * Stats Analyzer class that will emit events based on detected quality\n *\n * @export\n * @class StatsAnalyzer\n * @extends {EventsScope}\n */\nexport class StatsAnalyzer extends EventsScope {\n config: any;\n correlationId: any;\n lastEmittedStartStopEvent: any;\n lastMqaDataSent: any;\n lastStatsResults: any;\n meetingMediaStatus: any;\n mqaInterval: NodeJS.Timeout;\n mqaSentCount: any;\n networkQualityMonitor: any;\n mediaConnection: any;\n statsInterval: NodeJS.Timeout;\n statsResults: any;\n statsStarted: any;\n successfulCandidatePair: any;\n localIpAddress: string; // Returns the local IP address for diagnostics. this is the local IP of the interface used for the current media connection a host can have many local Ip Addresses\n receiveSlotCallback: ReceiveSlotCallback;\n\n /**\n * Creates a new instance of StatsAnalyzer\n * @constructor\n * @public\n * @param {Object} config SDK Configuration Object\n * @param {Function} receiveSlotCallback Callback used to access receive slots.\n * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)\n * @param {Object} statsResults Default properties for stats\n */\n constructor(\n config: any,\n receiveSlotCallback: ReceiveSlotCallback = () => undefined,\n networkQualityMonitor: object = {},\n statsResults: object = defaultStats\n ) {\n super();\n this.statsStarted = false;\n this.statsResults = statsResults;\n this.lastStatsResults = null;\n this.config = config;\n this.networkQualityMonitor = networkQualityMonitor;\n this.correlationId = config.correlationId;\n this.mqaSentCount = -1;\n this.lastMqaDataSent = {};\n this.lastEmittedStartStopEvent = {};\n this.receiveSlotCallback = receiveSlotCallback;\n this.successfulCandidatePair = {};\n this.localIpAddress = '';\n }\n\n /**\n * Resets cumulative stats arrays.\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n resetStatsResults() {\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('recv')) {\n this.statsResults[mediaType].recv.meanRtpJitter = [];\n }\n\n if (mediaType.includes('send')) {\n this.statsResults[mediaType].send.meanRemoteJitter = [];\n this.statsResults[mediaType].send.meanRoundTripTime = [];\n }\n });\n }\n\n /**\n * sets mediaStatus status for analyzing metrics\n *\n * @public\n * @param {Object} status for the audio and video\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public updateMediaStatus(status: MediaStatus) {\n this.meetingMediaStatus = {\n actual: {\n ...this.meetingMediaStatus?.actual,\n ...status?.actual,\n },\n expected: {\n ...this.meetingMediaStatus?.expected,\n ...status?.expected,\n },\n };\n }\n\n /**\n * captures MQA data from media connection\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n sendMqaData() {\n const newMqa = cloneDeep(emptyMqaInterval);\n\n // Fill in empty stats items for lastMqaDataSent\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (!this.lastMqaDataSent[mediaType]) {\n this.lastMqaDataSent[mediaType] = {};\n }\n\n if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {\n this.lastMqaDataSent[mediaType].send = {};\n }\n\n if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {\n this.lastMqaDataSent[mediaType].recv = {};\n }\n });\n\n // Create stats the first level, totals for senders and receivers\n const audioSender = cloneDeep(emptyAudioTransmit);\n const audioShareSender = cloneDeep(emptyAudioTransmit);\n const audioReceiver = cloneDeep(emptyAudioReceive);\n const audioShareReceiver = cloneDeep(emptyAudioReceive);\n const videoSender = cloneDeep(emptyVideoTransmit);\n const videoShareSender = cloneDeep(emptyVideoTransmit);\n const videoReceiver = cloneDeep(emptyVideoReceive);\n const videoShareReceiver = cloneDeep(emptyVideoReceive);\n\n getAudioSenderMqa({\n audioSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-send',\n });\n newMqa.audioTransmit.push(audioSender);\n\n getAudioSenderMqa({\n audioSender: audioShareSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-share-send',\n });\n newMqa.audioTransmit.push(audioShareSender);\n\n getAudioReceiverMqa({\n audioReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-recv',\n });\n newMqa.audioReceive.push(audioReceiver);\n\n getAudioReceiverMqa({\n audioReceiver: audioShareReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'audio-share-recv',\n });\n newMqa.audioReceive.push(audioShareReceiver);\n\n getVideoSenderMqa({\n videoSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-send',\n });\n newMqa.videoTransmit.push(videoSender);\n\n getVideoSenderMqa({\n videoSender: videoShareSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-share-send',\n });\n newMqa.videoTransmit.push(videoShareSender);\n\n getVideoReceiverMqa({\n videoReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-recv',\n });\n newMqa.videoReceive.push(videoReceiver);\n\n getVideoReceiverMqa({\n videoReceiver: videoShareReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n baseMediaType: 'video-share-recv',\n });\n newMqa.videoReceive.push(videoShareReceiver);\n\n // Add stats for individual streams\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.startsWith('audio-send')) {\n const audioSenderStream = cloneDeep(emptyAudioTransmitStream);\n\n getAudioSenderStreamMqa({\n audioSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit[0].streams.push(audioSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.startsWith('audio-share-send')) {\n const audioSenderStream = cloneDeep(emptyAudioTransmitStream);\n\n getAudioSenderStreamMqa({\n audioSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit[1].streams.push(audioSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.startsWith('audio-recv')) {\n const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);\n\n getAudioReceiverStreamMqa({\n audioReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive[0].streams.push(audioReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.startsWith('audio-share-recv')) {\n const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);\n\n getAudioReceiverStreamMqa({\n audioReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive[1].streams.push(audioReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.startsWith('video-send-layer')) {\n // We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.\n const videoSenderStream = cloneDeep(emptyVideoTransmitStream);\n\n getVideoSenderStreamMqa({\n videoSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit[0].streams.push(videoSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.startsWith('video-share-send')) {\n const videoSenderStream = cloneDeep(emptyVideoTransmitStream);\n\n getVideoSenderStreamMqa({\n videoSenderStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit[1].streams.push(videoSenderStream);\n\n this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);\n } else if (mediaType.startsWith('video-recv')) {\n const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);\n\n getVideoReceiverStreamMqa({\n videoReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive[0].streams.push(videoReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n } else if (mediaType.startsWith('video-share-recv')) {\n const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);\n\n getVideoReceiverStreamMqa({\n videoReceiverStream,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive[1].streams.push(videoReceiverStream);\n\n this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);\n }\n });\n\n newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;\n\n // Adding peripheral information\n newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});\n if (this.statsResults['audio-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['audio-send'].trackLabel || _UNKNOWN_,\n name: MEDIA_DEVICES.MICROPHONE,\n });\n }\n\n const existingVideoSender = Object.keys(this.statsResults).find((item) =>\n item.includes('video-send')\n );\n\n if (existingVideoSender) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults[existingVideoSender].trackLabel || _UNKNOWN_,\n name: MEDIA_DEVICES.CAMERA,\n });\n }\n\n newMqa.networkType = this.statsResults.connectionType.local.networkType;\n\n this.mqaSentCount += 1;\n\n newMqa.intervalNumber = this.mqaSentCount;\n\n this.resetStatsResults();\n\n this.emit(\n {\n file: 'statsAnalyzer',\n function: 'sendMqaData',\n },\n EVENTS.MEDIA_QUALITY,\n {\n data: newMqa,\n // @ts-ignore\n networkType: newMqa.networkType,\n }\n );\n }\n\n /**\n * updated the media connection when changed\n *\n * @private\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {void}\n */\n updateMediaConnection(mediaConnection: any) {\n this.mediaConnection = mediaConnection;\n }\n\n /**\n * Returns the local IP address for diagnostics.\n * this is the local IP of the interface used for the current media connection\n * a host can have many local Ip Addresses\n * @returns {string | undefined} The local IP address.\n */\n getLocalIpAddress(): string {\n return this.localIpAddress;\n }\n\n /**\n * Starts the stats analyzer on interval\n *\n * @public\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {Promise}\n */\n public startAnalyzer(mediaConnection: any) {\n if (!this.statsStarted) {\n this.statsStarted = true;\n this.mediaConnection = mediaConnection;\n\n return this.getStatsAndParse().then(() => {\n this.statsInterval = setInterval(() => {\n this.getStatsAndParse();\n }, this.config.analyzerInterval);\n // Trigger initial fetch\n this.sendMqaData();\n this.mqaInterval = setInterval(() => {\n this.sendMqaData();\n }, MQA_INTERVAL);\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Cleans up the analyzer when done\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public stopAnalyzer() {\n const sendOneLastMqa = this.mqaInterval && this.statsInterval;\n\n if (this.statsInterval) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n\n if (this.mqaInterval) {\n clearInterval(this.mqaInterval);\n this.mqaInterval = undefined;\n }\n\n if (sendOneLastMqa) {\n return this.getStatsAndParse().then(() => {\n this.sendMqaData();\n this.mediaConnection = null;\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Parse a single result of get stats\n *\n * @private\n * @param {*} getStatsResult\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private parseGetStatsResult(getStatsResult: any, type: string, isSender: boolean) {\n if (!getStatsResult) {\n return;\n }\n\n // Generate empty stats results\n if (!this.statsResults[type]) {\n this.statsResults[type] = {};\n }\n\n if (isSender && !this.statsResults[type].send) {\n this.statsResults[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults[type].recv) {\n this.statsResults[type].recv = cloneDeep(emptyReceiver);\n }\n\n switch (getStatsResult.type) {\n case 'outbound-rtp':\n this.processOutboundRTPResult(getStatsResult, type);\n break;\n case 'inbound-rtp':\n this.processInboundRTPResult(getStatsResult, type);\n break;\n case 'remote-inbound-rtp':\n case 'remote-outbound-rtp':\n this.compareSentAndReceived(getStatsResult, type);\n break;\n case 'remotecandidate':\n case 'remote-candidate':\n this.parseCandidate(getStatsResult, type, isSender, true);\n break;\n case 'local-candidate':\n this.parseCandidate(getStatsResult, type, isSender, false);\n break;\n case 'media-source':\n this.parseAudioSource(getStatsResult, type);\n break;\n default:\n break;\n }\n }\n\n /**\n * Filters the get stats results for types\n * @private\n * @param {Array} statsItem\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n */\n filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {\n const {types} = DEFAULT_GET_STATS_FILTER;\n\n // get the successful candidate pair before parsing stats.\n statsItem.report.forEach((report) => {\n if (report.type === 'candidate-pair' && report.state === 'succeeded') {\n this.successfulCandidatePair = report;\n }\n });\n\n let videoSenderIndex = 0;\n statsItem.report.forEach((result) => {\n if (types.includes(result.type)) {\n // if the video sender has multiple streams in the report, it is a new stream object.\n if (type === 'video-send' && result.type === 'outbound-rtp') {\n const newType = `video-send-layer-${videoSenderIndex}`;\n this.parseGetStatsResult(result, newType, isSender);\n videoSenderIndex += 1;\n\n this.statsResults[newType].direction = statsItem.currentDirection;\n this.statsResults[newType].trackLabel = statsItem.localTrackLabel;\n this.statsResults[newType].csi = statsItem.csi;\n } else {\n this.parseGetStatsResult(result, type, isSender);\n }\n }\n });\n\n if (this.statsResults[type]) {\n this.statsResults[type].direction = statsItem.currentDirection;\n this.statsResults[type].trackLabel = statsItem.localTrackLabel;\n this.statsResults[type].csi = statsItem.csi;\n this.extractAndSetLocalIpAddressInfoForDiagnostics(\n this.successfulCandidatePair?.localCandidateId,\n this.statsResults?.candidates\n );\n // reset the successful candidate pair.\n this.successfulCandidatePair = {};\n }\n }\n\n /**\n * parse the audio\n * @param {String} result\n * @param {boolean} type\n * @returns {void}\n */\n parseAudioSource(result: any, type: any) {\n if (!result) {\n return;\n }\n\n if (type.includes('audio-send')) {\n this.statsResults[type].send.audioLevel = result.audioLevel;\n this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;\n }\n }\n\n /**\n * emits started/stopped events for local/remote media by checking\n * if given values are increasing or not. The previousValue, currentValue\n * params can be any numerical value like number of receive packets or\n * decoded frames, etc.\n *\n * @private\n * @param {string} mediaType\n * @param {number} previousValue - value to compare\n * @param {number} currentValue - value to compare (must be same type of value as previousValue)\n * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n emitStartStopEvents = (\n mediaType: string,\n previousValue: number,\n currentValue: number,\n isLocal: boolean\n ) => {\n if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {\n throw new Error(`Unsupported mediaType: ${mediaType}`);\n }\n\n // eslint-disable-next-line no-param-reassign\n if (previousValue === undefined) previousValue = 0;\n // eslint-disable-next-line no-param-reassign\n if (currentValue === undefined) currentValue = 0;\n\n if (!this.lastEmittedStartStopEvent[mediaType]) {\n this.lastEmittedStartStopEvent[mediaType] = {};\n }\n\n const lastEmittedEvent = isLocal\n ? this.lastEmittedStartStopEvent[mediaType].local\n : this.lastEmittedStartStopEvent[mediaType].remote;\n\n let newEvent;\n\n if (currentValue - previousValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;\n } else if (currentValue === previousValue && currentValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;\n }\n\n if (newEvent && lastEmittedEvent !== newEvent) {\n if (isLocal) {\n this.lastEmittedStartStopEvent[mediaType].local = newEvent;\n } else {\n this.lastEmittedStartStopEvent[mediaType].remote = newEvent;\n }\n this.emit(\n {\n file: 'statsAnalyzer/index',\n function: 'compareLastStatsResult',\n },\n newEvent,\n {\n type: mediaType,\n }\n );\n }\n };\n\n /**\n * compares current and previous stats to check if packets are not sent\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n private compareLastStatsResult() {\n if (this.lastStatsResults !== null && this.meetingMediaStatus) {\n const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce(\n (prev, cur) =>\n prev +\n (this.statsResults[cur]?.[keyPrefix.includes('send') ? 'send' : 'recv'][value] || 0),\n 0\n );\n\n const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce(\n (prev, cur) =>\n prev +\n (this.lastStatsResults[cur]?.[keyPrefix.includes('send') ? 'send' : 'recv'][value] ||\n 0),\n 0\n );\n\n // Audio Transmit\n if (this.lastStatsResults['audio-send']) {\n // compare audio stats sent\n // NOTE: relies on there being only one sender.\n const currentStats = this.statsResults['audio-send'].send;\n const previousStats = this.lastStatsResults['audio-send'].send;\n\n if (\n (this.meetingMediaStatus.expected.sendAudio &&\n currentStats.totalPacketsSent === previousStats.totalPacketsSent) ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,\n currentStats.totalPacketsSent\n );\n } else {\n if (\n (this.meetingMediaStatus.expected.sendAudio &&\n currentStats.totalAudioEnergy === previousStats.totalAudioEnergy) ||\n currentStats.totalAudioEnergy === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,\n currentStats.totalAudioEnergy\n );\n }\n\n if (this.meetingMediaStatus.expected.sendAudio && currentStats.audioLevel === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`\n );\n }\n }\n\n this.emitStartStopEvents(\n 'audio',\n previousStats.totalPacketsSent,\n currentStats.totalPacketsSent,\n true\n );\n }\n\n // Audio Receive\n const currentAudioPacketsReceived = getCurrentStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n const previousAudioPacketsReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n\n this.emitStartStopEvents(\n 'audio',\n previousAudioPacketsReceived,\n currentAudioPacketsReceived,\n false\n );\n\n const currentTotalPacketsSent = getCurrentStatsTotals('video-send', 'totalPacketsSent');\n const previousTotalPacketsSent = getPreviousStatsTotals('video-send', 'totalPacketsSent');\n\n const currentFramesEncoded = getCurrentStatsTotals('video-send', 'framesEncoded');\n const previousFramesEncoded = getPreviousStatsTotals('video-send', 'framesEncoded');\n\n const currentFramesSent = getCurrentStatsTotals('video-send', 'framesSent');\n const previousFramesSent = getPreviousStatsTotals('video-send', 'framesSent');\n\n const doesVideoSendExist = Object.keys(this.lastStatsResults).some((item) =>\n item.includes('video-send')\n );\n\n // Video Transmit\n if (doesVideoSendExist) {\n // compare video stats sent\n\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (currentTotalPacketsSent === previousTotalPacketsSent || currentTotalPacketsSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,\n currentTotalPacketsSent\n );\n } else {\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (currentFramesEncoded === previousFramesEncoded || currentFramesEncoded === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,\n currentFramesEncoded\n );\n }\n\n if (\n this.meetingMediaStatus.expected.sendVideo &&\n (currentFramesSent === previousFramesSent || currentFramesSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,\n currentFramesSent\n );\n }\n }\n\n this.emitStartStopEvents('video', previousFramesSent, currentFramesSent, true);\n }\n\n // Video Receive\n const currentVideoFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');\n const previousVideoFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');\n\n this.emitStartStopEvents(\n 'video',\n previousVideoFramesDecoded,\n currentVideoFramesDecoded,\n false\n );\n\n // Share Transmit\n if (this.lastStatsResults['video-share-send']) {\n // compare share stats sent\n\n const currentStats = this.statsResults['video-share-send'].send;\n const previousStats = this.lastStatsResults['video-share-send'].send;\n\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,\n currentStats.totalPacketsSent\n );\n } else {\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,\n currentStats.framesEncoded\n );\n }\n\n if (\n this.meetingMediaStatus.expected.sendShare &&\n (this.statsResults['video-share-send'].send.framesSent ===\n this.lastStatsResults['video-share-send'].send.framesSent ||\n this.statsResults['video-share-send'].send.framesSent === 0)\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,\n this.statsResults['video-share-send'].send.framesSent\n );\n }\n }\n\n this.emitStartStopEvents('share', previousStats.framesSent, currentStats.framesSent, true);\n }\n\n // Share receive\n const currentShareFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');\n const previousShareFramesDecoded = getPreviousStatsTotals(\n 'video-share-recv',\n 'framesDecoded'\n );\n\n this.emitStartStopEvents(\n 'share',\n previousShareFramesDecoded,\n currentShareFramesDecoded,\n false\n );\n }\n }\n\n /**\n * Does a `getStats` on all the transceivers and parses the results\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {Promise}\n */\n private getStatsAndParse() {\n if (!this.mediaConnection) {\n return Promise.resolve();\n }\n\n if (\n this.mediaConnection &&\n this.mediaConnection.getConnectionState() === ConnectionState.Failed\n ) {\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'\n );\n\n return Promise.resolve();\n }\n\n LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');\n\n return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {\n transceiverStats.video.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)\n );\n transceiverStats.audio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)\n );\n transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)\n );\n transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)\n );\n\n transceiverStats.video.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-send', true);\n });\n transceiverStats.audio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-send', true);\n });\n transceiverStats.screenShareVideo.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-share-send', true);\n });\n transceiverStats.screenShareAudio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);\n });\n\n this.compareLastStatsResult();\n\n // Save the last results to compare with the current\n // DO Deep copy, for some reason it takes the reference all the time rather then old value set\n this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));\n\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats'\n );\n });\n }\n\n /**\n * Processes OutboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processOutboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.SEND_DIRECTION;\n\n if (result.bytesSent) {\n const kilobytes = 0;\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;\n }\n\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;\n\n // Data saved to send MQA metrics\n\n this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;\n this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].encoderImplementation =\n result.encoderImplementation;\n this.statsResults[mediaType][sendrecvType].qualityLimitationReason =\n result.qualityLimitationReason;\n this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =\n result.qualityLimitationResolutionChanges;\n this.statsResults[mediaType][sendrecvType].retransmittedPacketsSent =\n result.retransmittedPacketsSent;\n this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;\n this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;\n this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =\n result.retransmittedBytesSent;\n }\n }\n\n /**\n * Processes InboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processInboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.RECEIVE_DIRECTION;\n\n if (result.bytesReceived) {\n let kilobytes = 0;\n const receiveSlot = this.receiveSlotCallback(result.ssrc);\n const sourceState = receiveSlot?.sourceState;\n const idAndCsi = receiveSlot\n ? `id: \"${receiveSlot.id || ''}\"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`\n : '';\n\n const bytes =\n result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;\n\n kilobytes = bytes / 1024;\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n\n let currentPacketsLost =\n result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;\n if (currentPacketsLost < 0) {\n currentPacketsLost = 0;\n }\n const packetsReceivedDiff =\n result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n if (packetsReceivedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No packets received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total packets received on slot: `,\n result.packetsReceived\n );\n }\n }\n\n if (mediaType.startsWith('video') || mediaType.startsWith('share')) {\n const videoFramesReceivedDiff =\n result.framesReceived - this.statsResults[mediaType][sendrecvType].framesReceived;\n\n if (videoFramesReceivedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No frames received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames received on slot: `,\n result.framesReceived\n );\n }\n }\n\n const videoFramesDecodedDiff =\n result.framesDecoded - this.statsResults[mediaType][sendrecvType].framesDecoded;\n\n if (videoFramesDecodedDiff === 0) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No frames decoded for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames decoded on slot: `,\n result.framesDecoded\n );\n }\n }\n\n const videoFramesDroppedDiff =\n result.framesDropped - this.statsResults[mediaType][sendrecvType].framesDropped;\n\n if (videoFramesDroppedDiff > 10) {\n if (receiveSlot && sourceState === 'live') {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> Frames dropped for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames dropped on slot: `,\n result.framesDropped\n );\n }\n }\n }\n\n // Check the over all packet Lost ratio\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =\n currentPacketsLost > 0\n ? currentPacketsLost / (packetsReceivedDiff + currentPacketsLost)\n : 0;\n if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio\n );\n }\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;\n }\n\n // TODO: check the packet loss value is negative values here\n\n if (result.packetsLost) {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost =\n result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;\n } else {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n\n // From Thin\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;\n this.statsResults[mediaType][sendrecvType].framesDropped = result.framesDropped;\n\n this.statsResults[mediaType][sendrecvType].decoderImplementation =\n result.decoderImplementation;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;\n this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;\n this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;\n\n this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);\n\n // Audio stats\n\n this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;\n this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;\n this.statsResults[mediaType][sendrecvType].totalSamplesReceived =\n result.totalSamplesReceived || 0;\n this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =\n result.totalSamplesDecoded || 0;\n this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;\n }\n }\n\n /**\n * extracts the local Ip address from the statsResult object by looking at stats results candidates\n * and matches that ID with the successful candidate pair. It looks at the type of local candidate it is\n * and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc\n * note, there are known incompatibilities and it is possible for this to set undefined, or for the IP address to be the public IP address\n * for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP\n * @private\n * @param {string} successfulCandidatePairId - The ID of the successful candidate pair.\n * @param {Object} candidates - the stats result candidates\n * @returns {void}\n */\n extractAndSetLocalIpAddressInfoForDiagnostics = (\n successfulCandidatePairId: string,\n candidates: {[key: string]: Record<string, unknown>}\n ) => {\n let newIpAddress = '';\n if (successfulCandidatePairId && !isEmpty(candidates)) {\n const localCandidate = candidates[successfulCandidatePairId];\n if (localCandidate) {\n if (localCandidate.candidateType === 'host') {\n // if it's a host candidate, use the address property - it will be the local IP\n newIpAddress = `${localCandidate.address}`;\n } else if (localCandidate.candidateType === 'prflx') {\n // if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)\n // then look at the relatedAddress - it will be the local\n //\n // Firefox doesn't populate the relayProtocol property\n if (!localCandidate.relayProtocol) {\n newIpAddress = `${localCandidate.relatedAddress}`;\n } else {\n // if it's a peer reflexive candidate and we are using a relay -\n // in that case the relatedAddress will be the IP of the TURN server (Linus),\n // so we can only look at the address, but it might be local IP or public IP,\n // depending on if the user is behind a NAT or not\n newIpAddress = `${localCandidate.address}`;\n }\n }\n }\n }\n this.localIpAddress = newIpAddress;\n };\n\n /**\n * Processes remote and local candidate result and stores\n * @private\n * @param {*} result\n * @param {*} type\n * @param {boolean} isSender\n * @param {boolean} isRemote\n *\n * @returns {void}\n */\n parseCandidate = (result: any, type: any, isSender: boolean, isRemote: boolean) => {\n if (!result || !result.id) {\n return;\n }\n\n // We only care about the successful local candidate\n if (this.successfulCandidatePair?.localCandidateId !== result.id) {\n return;\n }\n\n let transport;\n if (result.relayProtocol) {\n transport = result.relayProtocol.toUpperCase();\n } else if (result.protocol) {\n transport = result.protocol.toUpperCase();\n }\n\n const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;\n const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;\n\n if (!this.statsResults.candidates) {\n this.statsResults.candidates = {};\n }\n\n this.statsResults.candidates[result.id] = {\n candidateType: result.candidateType,\n ipAddress: result.ip, // TODO: add ports\n relatedAddress: result.relatedAddress,\n relatedPort: result.relatedPort,\n relayProtocol: result.relayProtocol,\n protocol: result.protocol,\n address: result.address,\n portNumber: result.port,\n networkType: result.networkType,\n priority: result.priority,\n transport,\n timestamp: result.time,\n id: result.id,\n type: result.type,\n };\n\n this.statsResults.connectionType[ipType].candidateType = result.candidateType;\n this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;\n\n this.statsResults.connectionType[ipType].networkType =\n result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;\n this.statsResults.connectionType[ipType].transport = transport;\n\n this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;\n };\n\n /**\n *\n * @private\n * @param {*} result\n * @param {*} type\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n compareSentAndReceived(result, type) {\n // Don't compare on transceivers without a sender.\n if (!type || !this.statsResults[type].send) {\n return;\n }\n\n const mediaType = type;\n\n const currentPacketLoss =\n result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;\n\n this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n\n this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);\n this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);\n\n this.statsResults[mediaType].send.timestamp = result.timestamp;\n this.statsResults[mediaType].send.ssrc = result.ssrc;\n this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;\n\n // Total packloss ratio on this video section of the call\n this.statsResults[mediaType].send.overAllPacketLossRatio =\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0\n ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver /\n this.statsResults[mediaType].send.totalPacketsSent\n : 0;\n this.statsResults[mediaType].send.currentPacketLossRatio =\n this.statsResults[mediaType].send.packetsLostOnReceiver > 0\n ? (this.statsResults[mediaType].send.packetsLostOnReceiver * 100) /\n (this.statsResults[mediaType].send.packetsSent +\n this.statsResults[mediaType].send.packetsLostOnReceiver)\n : 0;\n\n if (\n this.statsResults[mediaType].send.maxPacketLossRatio <\n this.statsResults[mediaType].send.currentPacketLossRatio\n ) {\n this.statsResults[mediaType].send.maxPacketLossRatio =\n this.statsResults[mediaType].send.currentPacketLossRatio;\n }\n\n if (result.type === 'remote-inbound-rtp') {\n this.networkQualityMonitor.determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults: result,\n statsAnalyzerCurrentStats: this.statsResults,\n });\n }\n }\n}\n"],"mappings":"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"}
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
62
62
  updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
63
63
  this.set('canManageWebcast', canManageWebcast);
64
64
  },
65
- version: "3.0.0-beta.405"
65
+ version: "3.0.0-beta.406"
66
66
  });
67
67
  var _default = Webinar;
68
68
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.405",
3
+ "version": "3.0.0-beta.406",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -33,12 +33,12 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@peculiar/webcrypto": "^1.4.3",
36
- "@webex/plugin-meetings": "3.0.0-beta.405",
37
- "@webex/test-helper-chai": "3.0.0-beta.405",
38
- "@webex/test-helper-mocha": "3.0.0-beta.405",
39
- "@webex/test-helper-mock-webex": "3.0.0-beta.405",
40
- "@webex/test-helper-retry": "3.0.0-beta.405",
41
- "@webex/test-helper-test-users": "3.0.0-beta.405",
36
+ "@webex/plugin-meetings": "3.0.0-beta.406",
37
+ "@webex/test-helper-chai": "3.0.0-beta.406",
38
+ "@webex/test-helper-mocha": "3.0.0-beta.406",
39
+ "@webex/test-helper-mock-webex": "3.0.0-beta.406",
40
+ "@webex/test-helper-retry": "3.0.0-beta.406",
41
+ "@webex/test-helper-test-users": "3.0.0-beta.406",
42
42
  "chai": "^4.3.4",
43
43
  "chai-as-promised": "^7.1.1",
44
44
  "jsdom-global": "3.0.2",
@@ -47,19 +47,19 @@
47
47
  "typescript": "^4.7.4"
48
48
  },
49
49
  "dependencies": {
50
- "@webex/common": "3.0.0-beta.405",
50
+ "@webex/common": "3.0.0-beta.406",
51
51
  "@webex/internal-media-core": "2.3.2",
52
- "@webex/internal-plugin-conversation": "3.0.0-beta.405",
53
- "@webex/internal-plugin-device": "3.0.0-beta.405",
54
- "@webex/internal-plugin-llm": "3.0.0-beta.405",
55
- "@webex/internal-plugin-mercury": "3.0.0-beta.405",
56
- "@webex/internal-plugin-metrics": "3.0.0-beta.405",
57
- "@webex/internal-plugin-support": "3.0.0-beta.405",
58
- "@webex/internal-plugin-user": "3.0.0-beta.405",
59
- "@webex/media-helpers": "3.0.0-beta.405",
60
- "@webex/plugin-people": "3.0.0-beta.405",
61
- "@webex/plugin-rooms": "3.0.0-beta.405",
62
- "@webex/webex-core": "3.0.0-beta.405",
52
+ "@webex/internal-plugin-conversation": "3.0.0-beta.406",
53
+ "@webex/internal-plugin-device": "3.0.0-beta.406",
54
+ "@webex/internal-plugin-llm": "3.0.0-beta.406",
55
+ "@webex/internal-plugin-mercury": "3.0.0-beta.406",
56
+ "@webex/internal-plugin-metrics": "3.0.0-beta.406",
57
+ "@webex/internal-plugin-support": "3.0.0-beta.406",
58
+ "@webex/internal-plugin-user": "3.0.0-beta.406",
59
+ "@webex/media-helpers": "3.0.0-beta.406",
60
+ "@webex/plugin-people": "3.0.0-beta.406",
61
+ "@webex/plugin-rooms": "3.0.0-beta.406",
62
+ "@webex/webex-core": "3.0.0-beta.406",
63
63
  "ampersand-collection": "^2.0.2",
64
64
  "bowser": "^2.11.0",
65
65
  "btoa": "^1.2.1",
@@ -264,7 +264,7 @@ export class StatsAnalyzer extends EventsScope {
264
264
 
265
265
  // Add stats for individual streams
266
266
  Object.keys(this.statsResults).forEach((mediaType) => {
267
- if (mediaType.includes('audio-send')) {
267
+ if (mediaType.startsWith('audio-send')) {
268
268
  const audioSenderStream = cloneDeep(emptyAudioTransmitStream);
269
269
 
270
270
  getAudioSenderStreamMqa({
@@ -276,7 +276,7 @@ export class StatsAnalyzer extends EventsScope {
276
276
  newMqa.audioTransmit[0].streams.push(audioSenderStream);
277
277
 
278
278
  this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
279
- } else if (mediaType.includes('audio-share-send')) {
279
+ } else if (mediaType.startsWith('audio-share-send')) {
280
280
  const audioSenderStream = cloneDeep(emptyAudioTransmitStream);
281
281
 
282
282
  getAudioSenderStreamMqa({
@@ -288,7 +288,7 @@ export class StatsAnalyzer extends EventsScope {
288
288
  newMqa.audioTransmit[1].streams.push(audioSenderStream);
289
289
 
290
290
  this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
291
- } else if (mediaType.includes('audio-recv')) {
291
+ } else if (mediaType.startsWith('audio-recv')) {
292
292
  const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);
293
293
 
294
294
  getAudioReceiverStreamMqa({
@@ -300,7 +300,7 @@ export class StatsAnalyzer extends EventsScope {
300
300
  newMqa.audioReceive[0].streams.push(audioReceiverStream);
301
301
 
302
302
  this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
303
- } else if (mediaType.includes('audio-share-recv')) {
303
+ } else if (mediaType.startsWith('audio-share-recv')) {
304
304
  const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);
305
305
 
306
306
  getAudioReceiverStreamMqa({
@@ -312,7 +312,8 @@ export class StatsAnalyzer extends EventsScope {
312
312
  newMqa.audioReceive[1].streams.push(audioReceiverStream);
313
313
 
314
314
  this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
315
- } else if (mediaType.includes('video-send')) {
315
+ } else if (mediaType.startsWith('video-send-layer')) {
316
+ // We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.
316
317
  const videoSenderStream = cloneDeep(emptyVideoTransmitStream);
317
318
 
318
319
  getVideoSenderStreamMqa({
@@ -324,7 +325,7 @@ export class StatsAnalyzer extends EventsScope {
324
325
  newMqa.videoTransmit[0].streams.push(videoSenderStream);
325
326
 
326
327
  this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
327
- } else if (mediaType.includes('video-share-send')) {
328
+ } else if (mediaType.startsWith('video-share-send')) {
328
329
  const videoSenderStream = cloneDeep(emptyVideoTransmitStream);
329
330
 
330
331
  getVideoSenderStreamMqa({
@@ -336,7 +337,7 @@ export class StatsAnalyzer extends EventsScope {
336
337
  newMqa.videoTransmit[1].streams.push(videoSenderStream);
337
338
 
338
339
  this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
339
- } else if (mediaType.includes('video-recv')) {
340
+ } else if (mediaType.startsWith('video-recv')) {
340
341
  const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);
341
342
 
342
343
  getVideoReceiverStreamMqa({
@@ -348,7 +349,7 @@ export class StatsAnalyzer extends EventsScope {
348
349
  newMqa.videoReceive[0].streams.push(videoReceiverStream);
349
350
 
350
351
  this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
351
- } else if (mediaType.includes('video-share-recv')) {
352
+ } else if (mediaType.startsWith('video-share-recv')) {
352
353
  const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);
353
354
 
354
355
  getVideoReceiverStreamMqa({
@@ -373,9 +374,14 @@ export class StatsAnalyzer extends EventsScope {
373
374
  name: MEDIA_DEVICES.MICROPHONE,
374
375
  });
375
376
  }
376
- if (this.statsResults['video-send']) {
377
+
378
+ const existingVideoSender = Object.keys(this.statsResults).find((item) =>
379
+ item.includes('video-send')
380
+ );
381
+
382
+ if (existingVideoSender) {
377
383
  newMqa.intervalMetadata.peripherals.push({
378
- information: this.statsResults['video-send'].trackLabel || _UNKNOWN_,
384
+ information: this.statsResults[existingVideoSender].trackLabel || _UNKNOWN_,
379
385
  name: MEDIA_DEVICES.CAMERA,
380
386
  });
381
387
  }
@@ -552,9 +558,21 @@ export class StatsAnalyzer extends EventsScope {
552
558
  }
553
559
  });
554
560
 
561
+ let videoSenderIndex = 0;
555
562
  statsItem.report.forEach((result) => {
556
563
  if (types.includes(result.type)) {
557
- this.parseGetStatsResult(result, type, isSender);
564
+ // if the video sender has multiple streams in the report, it is a new stream object.
565
+ if (type === 'video-send' && result.type === 'outbound-rtp') {
566
+ const newType = `video-send-layer-${videoSenderIndex}`;
567
+ this.parseGetStatsResult(result, newType, isSender);
568
+ videoSenderIndex += 1;
569
+
570
+ this.statsResults[newType].direction = statsItem.currentDirection;
571
+ this.statsResults[newType].trackLabel = statsItem.localTrackLabel;
572
+ this.statsResults[newType].csi = statsItem.csi;
573
+ } else {
574
+ this.parseGetStatsResult(result, type, isSender);
575
+ }
558
576
  }
559
577
  });
560
578
 
@@ -664,12 +682,23 @@ export class StatsAnalyzer extends EventsScope {
664
682
  const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
665
683
  Object.keys(this.statsResults)
666
684
  .filter((key) => key.startsWith(keyPrefix))
667
- .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
685
+ .reduce(
686
+ (prev, cur) =>
687
+ prev +
688
+ (this.statsResults[cur]?.[keyPrefix.includes('send') ? 'send' : 'recv'][value] || 0),
689
+ 0
690
+ );
668
691
 
669
692
  const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
670
693
  Object.keys(this.statsResults)
671
694
  .filter((key) => key.startsWith(keyPrefix))
672
- .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
695
+ .reduce(
696
+ (prev, cur) =>
697
+ prev +
698
+ (this.lastStatsResults[cur]?.[keyPrefix.includes('send') ? 'send' : 'recv'][value] ||
699
+ 0),
700
+ 0
701
+ );
673
702
 
674
703
  // Audio Transmit
675
704
  if (this.lastStatsResults['audio-send']) {
@@ -731,47 +760,54 @@ export class StatsAnalyzer extends EventsScope {
731
760
  false
732
761
  );
733
762
 
763
+ const currentTotalPacketsSent = getCurrentStatsTotals('video-send', 'totalPacketsSent');
764
+ const previousTotalPacketsSent = getPreviousStatsTotals('video-send', 'totalPacketsSent');
765
+
766
+ const currentFramesEncoded = getCurrentStatsTotals('video-send', 'framesEncoded');
767
+ const previousFramesEncoded = getPreviousStatsTotals('video-send', 'framesEncoded');
768
+
769
+ const currentFramesSent = getCurrentStatsTotals('video-send', 'framesSent');
770
+ const previousFramesSent = getPreviousStatsTotals('video-send', 'framesSent');
771
+
772
+ const doesVideoSendExist = Object.keys(this.lastStatsResults).some((item) =>
773
+ item.includes('video-send')
774
+ );
775
+
734
776
  // Video Transmit
735
- if (this.lastStatsResults['video-send']) {
777
+ if (doesVideoSendExist) {
736
778
  // compare video stats sent
737
- const currentStats = this.statsResults['video-send'].send;
738
- const previousStats = this.lastStatsResults['video-send'].send;
739
779
 
740
780
  if (
741
781
  this.meetingMediaStatus.expected.sendVideo &&
742
- (currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
743
- currentStats.totalPacketsSent === 0)
782
+ (currentTotalPacketsSent === previousTotalPacketsSent || currentTotalPacketsSent === 0)
744
783
  ) {
745
784
  LoggerProxy.logger.info(
746
785
  `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
747
- currentStats.totalPacketsSent
786
+ currentTotalPacketsSent
748
787
  );
749
788
  } else {
750
789
  if (
751
790
  this.meetingMediaStatus.expected.sendVideo &&
752
- (currentStats.framesEncoded === previousStats.framesEncoded ||
753
- currentStats.framesEncoded === 0)
791
+ (currentFramesEncoded === previousFramesEncoded || currentFramesEncoded === 0)
754
792
  ) {
755
793
  LoggerProxy.logger.info(
756
794
  `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
757
- currentStats.framesEncoded
795
+ currentFramesEncoded
758
796
  );
759
797
  }
760
798
 
761
799
  if (
762
800
  this.meetingMediaStatus.expected.sendVideo &&
763
- (this.statsResults['video-send'].send.framesSent ===
764
- this.lastStatsResults['video-send'].send.framesSent ||
765
- this.statsResults['video-send'].send.framesSent === 0)
801
+ (currentFramesSent === previousFramesSent || currentFramesSent === 0)
766
802
  ) {
767
803
  LoggerProxy.logger.info(
768
804
  `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
769
- this.statsResults['video-send'].send.framesSent
805
+ currentFramesSent
770
806
  );
771
807
  }
772
808
  }
773
809
 
774
- this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);
810
+ this.emitStartStopEvents('video', previousFramesSent, currentFramesSent, true);
775
811
  }
776
812
 
777
813
  // Video Receive
@@ -1543,6 +1543,185 @@ describe('plugin-meetings', () => {
1543
1543
  },
1544
1544
  ]);
1545
1545
  });
1546
+
1547
+ it('has three streams for video senders for simulcast', async () => {
1548
+ pc.getTransceiverStats = sinon.stub().resolves({
1549
+ audio: {
1550
+ senders: [fakeStats.audio.senders[0]],
1551
+ receivers: [fakeStats.audio.receivers[0]],
1552
+ },
1553
+ video: {
1554
+ senders: [
1555
+ {
1556
+ localTrackLabel: 'fake-camera',
1557
+ report: [
1558
+ {
1559
+ type: 'outbound-rtp',
1560
+ bytesSent: 1,
1561
+ framesSent: 0,
1562
+ packetsSent: 0,
1563
+ },
1564
+ {
1565
+ type: 'outbound-rtp',
1566
+ bytesSent: 0,
1567
+ framesSent: 0,
1568
+ packetsSent: 0,
1569
+ },
1570
+ {
1571
+ type: 'outbound-rtp',
1572
+ bytesSent: 1000,
1573
+ framesSent: 1,
1574
+ packetsSent: 1,
1575
+ },
1576
+ {
1577
+ type: 'remote-inbound-rtp',
1578
+ packetsLost: 0,
1579
+ },
1580
+ {
1581
+ type: 'candidate-pair',
1582
+ state: 'succeeded',
1583
+ localCandidateId: 'fake-candidate-id',
1584
+ },
1585
+ {
1586
+ type: 'candidate-pair',
1587
+ state: 'failed',
1588
+ localCandidateId: 'bad-candidate-id',
1589
+ },
1590
+ {
1591
+ type: 'local-candidate',
1592
+ id: 'fake-candidate-id',
1593
+ protocol: 'tcp',
1594
+ },
1595
+ ],
1596
+ },
1597
+ ],
1598
+ receivers: [fakeStats.video.receivers[0]],
1599
+ },
1600
+ screenShareAudio: {
1601
+ senders: [fakeStats.audio.senders[0]],
1602
+ receivers: [fakeStats.audio.receivers[0]],
1603
+ },
1604
+ screenShareVideo: {
1605
+ senders: [fakeStats.video.senders[0]],
1606
+ receivers: [fakeStats.video.receivers[0]],
1607
+ },
1608
+ });
1609
+
1610
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
1611
+
1612
+ await progressTime();
1613
+
1614
+ assert.deepEqual(mqeData.videoTransmit[0].streams, [
1615
+ {
1616
+ common: {
1617
+ codec: 'H264',
1618
+ csi: [],
1619
+ duplicateSsci: 0,
1620
+ requestedBitrate: 0,
1621
+ requestedFrames: 0,
1622
+ rtpPackets: 0,
1623
+ ssci: 0,
1624
+ transmittedBitrate: 0.13333333333333333,
1625
+ transmittedFrameRate: 0
1626
+ },
1627
+ h264CodecProfile: 'BP',
1628
+ isAvatar: false,
1629
+ isHardwareEncoded: false,
1630
+ localConfigurationChanges: 2,
1631
+ maxFrameQp: 0,
1632
+ maxNoiseLevel: 0,
1633
+ minRegionQp: 0,
1634
+ remoteConfigurationChanges: 0,
1635
+ requestedFrameSize: 0,
1636
+ requestedKeyFrames: 0,
1637
+ transmittedFrameSize: 0,
1638
+ transmittedHeight: 0,
1639
+ transmittedKeyFrames: 0,
1640
+ transmittedKeyFramesClient: 0,
1641
+ transmittedKeyFramesConfigurationChange: 0,
1642
+ transmittedKeyFramesFeedback: 0,
1643
+ transmittedKeyFramesLocalDrop: 0,
1644
+ transmittedKeyFramesOtherLayer: 0,
1645
+ transmittedKeyFramesPeriodic: 0,
1646
+ transmittedKeyFramesSceneChange: 0,
1647
+ transmittedKeyFramesStartup: 0,
1648
+ transmittedKeyFramesUnknown: 0,
1649
+ transmittedWidth: 0,
1650
+ },
1651
+ {
1652
+ common: {
1653
+ codec: 'H264',
1654
+ csi: [],
1655
+ duplicateSsci: 0,
1656
+ requestedBitrate: 0,
1657
+ requestedFrames: 0,
1658
+ rtpPackets: 0,
1659
+ ssci: 0,
1660
+ transmittedBitrate: 0,
1661
+ transmittedFrameRate: 0,
1662
+ },
1663
+ h264CodecProfile: 'BP',
1664
+ isAvatar: false,
1665
+ isHardwareEncoded: false,
1666
+ localConfigurationChanges: 2,
1667
+ maxFrameQp: 0,
1668
+ maxNoiseLevel: 0,
1669
+ minRegionQp: 0,
1670
+ remoteConfigurationChanges: 0,
1671
+ requestedFrameSize: 0,
1672
+ requestedKeyFrames: 0,
1673
+ transmittedFrameSize: 0,
1674
+ transmittedHeight: 0,
1675
+ transmittedKeyFrames: 0,
1676
+ transmittedKeyFramesClient: 0,
1677
+ transmittedKeyFramesConfigurationChange: 0,
1678
+ transmittedKeyFramesFeedback: 0,
1679
+ transmittedKeyFramesLocalDrop: 0,
1680
+ transmittedKeyFramesOtherLayer: 0,
1681
+ transmittedKeyFramesPeriodic: 0,
1682
+ transmittedKeyFramesSceneChange: 0,
1683
+ transmittedKeyFramesStartup: 0,
1684
+ transmittedKeyFramesUnknown: 0,
1685
+ transmittedWidth: 0,
1686
+ },
1687
+ {
1688
+ common: {
1689
+ codec: 'H264',
1690
+ csi: [],
1691
+ duplicateSsci: 0,
1692
+ requestedBitrate: 0,
1693
+ requestedFrames: 0,
1694
+ rtpPackets: 1,
1695
+ ssci: 0,
1696
+ transmittedBitrate: 133.33333333333334,
1697
+ transmittedFrameRate: 0,
1698
+ },
1699
+ h264CodecProfile: 'BP',
1700
+ isAvatar: false,
1701
+ isHardwareEncoded: false,
1702
+ localConfigurationChanges: 2,
1703
+ maxFrameQp: 0,
1704
+ maxNoiseLevel: 0,
1705
+ minRegionQp: 0,
1706
+ remoteConfigurationChanges: 0,
1707
+ requestedFrameSize: 0,
1708
+ requestedKeyFrames: 0,
1709
+ transmittedFrameSize: 0,
1710
+ transmittedHeight: 0,
1711
+ transmittedKeyFrames: 0,
1712
+ transmittedKeyFramesClient: 0,
1713
+ transmittedKeyFramesConfigurationChange: 0,
1714
+ transmittedKeyFramesFeedback: 0,
1715
+ transmittedKeyFramesLocalDrop: 0,
1716
+ transmittedKeyFramesOtherLayer: 0,
1717
+ transmittedKeyFramesPeriodic: 0,
1718
+ transmittedKeyFramesSceneChange: 0,
1719
+ transmittedKeyFramesStartup: 0,
1720
+ transmittedKeyFramesUnknown: 0,
1721
+ transmittedWidth: 0,
1722
+ }
1723
+ ]);
1724
+ });
1546
1725
  });
1547
1726
  });
1548
1727
  });