@webex/plugin-meetings 3.3.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +7 -2
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/constants.js +11 -4
  5. package/dist/constants.js.map +1 -1
  6. package/dist/interpretation/index.js +1 -1
  7. package/dist/interpretation/siLanguage.js +1 -1
  8. package/dist/locus-info/selfUtils.js +0 -5
  9. package/dist/locus-info/selfUtils.js.map +1 -1
  10. package/dist/media/MediaConnectionAwaiter.js +70 -15
  11. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  12. package/dist/media/index.js +12 -0
  13. package/dist/media/index.js.map +1 -1
  14. package/dist/meeting/connectionStateHandler.js +67 -0
  15. package/dist/meeting/connectionStateHandler.js.map +1 -0
  16. package/dist/meeting/index.js +552 -357
  17. package/dist/meeting/index.js.map +1 -1
  18. package/dist/meeting/locusMediaRequest.js +7 -0
  19. package/dist/meeting/locusMediaRequest.js.map +1 -1
  20. package/dist/meeting/muteState.js +6 -1
  21. package/dist/meeting/muteState.js.map +1 -1
  22. package/dist/meeting/util.js +1 -0
  23. package/dist/meeting/util.js.map +1 -1
  24. package/dist/meeting-info/index.js +4 -4
  25. package/dist/meeting-info/index.js.map +1 -1
  26. package/dist/meeting-info/meeting-info-v2.js +2 -2
  27. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  28. package/dist/meeting-info/util.js +17 -17
  29. package/dist/meeting-info/util.js.map +1 -1
  30. package/dist/meeting-info/utilv2.js +16 -16
  31. package/dist/meeting-info/utilv2.js.map +1 -1
  32. package/dist/meetings/collection.js +1 -1
  33. package/dist/meetings/collection.js.map +1 -1
  34. package/dist/meetings/index.js +37 -33
  35. package/dist/meetings/index.js.map +1 -1
  36. package/dist/meetings/meetings.types.js +8 -0
  37. package/dist/meetings/meetings.types.js.map +1 -1
  38. package/dist/meetings/util.js +3 -2
  39. package/dist/meetings/util.js.map +1 -1
  40. package/dist/metrics/constants.js +2 -1
  41. package/dist/metrics/constants.js.map +1 -1
  42. package/dist/metrics/index.js +57 -0
  43. package/dist/metrics/index.js.map +1 -1
  44. package/dist/personal-meeting-room/index.js +1 -1
  45. package/dist/personal-meeting-room/index.js.map +1 -1
  46. package/dist/reachability/clusterReachability.js +108 -53
  47. package/dist/reachability/clusterReachability.js.map +1 -1
  48. package/dist/reachability/index.js +415 -56
  49. package/dist/reachability/index.js.map +1 -1
  50. package/dist/types/constants.d.ts +11 -3
  51. package/dist/types/media/MediaConnectionAwaiter.d.ts +24 -4
  52. package/dist/types/meeting/connectionStateHandler.d.ts +30 -0
  53. package/dist/types/meeting/index.d.ts +27 -7
  54. package/dist/types/meeting/locusMediaRequest.d.ts +2 -0
  55. package/dist/types/meeting-info/index.d.ts +3 -2
  56. package/dist/types/meeting-info/meeting-info-v2.d.ts +3 -2
  57. package/dist/types/meeting-info/util.d.ts +5 -4
  58. package/dist/types/meeting-info/utilv2.d.ts +3 -2
  59. package/dist/types/meetings/collection.d.ts +3 -2
  60. package/dist/types/meetings/index.d.ts +4 -3
  61. package/dist/types/meetings/meetings.types.d.ts +9 -0
  62. package/dist/types/metrics/constants.d.ts +1 -0
  63. package/dist/types/metrics/index.d.ts +15 -0
  64. package/dist/types/reachability/clusterReachability.d.ts +31 -3
  65. package/dist/types/reachability/index.d.ts +93 -2
  66. package/dist/webinar/index.js +1 -1
  67. package/package.json +23 -23
  68. package/src/breakouts/index.ts +7 -1
  69. package/src/constants.ts +13 -17
  70. package/src/locus-info/selfUtils.ts +0 -5
  71. package/src/media/MediaConnectionAwaiter.ts +89 -14
  72. package/src/media/index.ts +13 -0
  73. package/src/meeting/connectionStateHandler.ts +65 -0
  74. package/src/meeting/index.ts +526 -292
  75. package/src/meeting/locusMediaRequest.ts +5 -0
  76. package/src/meeting/muteState.ts +6 -1
  77. package/src/meeting/util.ts +1 -0
  78. package/src/meeting-info/index.ts +9 -6
  79. package/src/meeting-info/meeting-info-v2.ts +4 -4
  80. package/src/meeting-info/util.ts +23 -28
  81. package/src/meeting-info/utilv2.ts +18 -24
  82. package/src/meetings/collection.ts +3 -3
  83. package/src/meetings/index.ts +39 -40
  84. package/src/meetings/meetings.types.ts +11 -0
  85. package/src/meetings/util.ts +5 -4
  86. package/src/metrics/constants.ts +1 -0
  87. package/src/metrics/index.ts +44 -0
  88. package/src/personal-meeting-room/index.ts +2 -2
  89. package/src/reachability/clusterReachability.ts +86 -25
  90. package/src/reachability/index.ts +316 -27
  91. package/test/unit/spec/breakouts/index.ts +51 -32
  92. package/test/unit/spec/locus-info/selfUtils.js +25 -23
  93. package/test/unit/spec/media/MediaConnectionAwaiter.ts +131 -32
  94. package/test/unit/spec/media/index.ts +42 -27
  95. package/test/unit/spec/meeting/connectionStateHandler.ts +102 -0
  96. package/test/unit/spec/meeting/index.js +758 -179
  97. package/test/unit/spec/meeting/locusMediaRequest.ts +7 -0
  98. package/test/unit/spec/meeting/muteState.js +24 -0
  99. package/test/unit/spec/meeting-info/index.js +4 -4
  100. package/test/unit/spec/meeting-info/meetinginfov2.js +24 -28
  101. package/test/unit/spec/meeting-info/request.js +2 -2
  102. package/test/unit/spec/meeting-info/utilv2.js +41 -49
  103. package/test/unit/spec/meetings/index.js +14 -0
  104. package/test/unit/spec/metrics/index.js +126 -0
  105. package/test/unit/spec/multistream/mediaRequestManager.ts +2 -2
  106. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -2
  107. package/test/unit/spec/reachability/clusterReachability.ts +116 -22
  108. package/test/unit/spec/reachability/index.ts +1153 -84
  109. package/test/unit/spec/rtcMetrics/index.ts +1 -0
  110. package/dist/mediaQualityMetrics/config.js +0 -321
  111. package/dist/mediaQualityMetrics/config.js.map +0 -1
  112. package/dist/statsAnalyzer/global.js +0 -44
  113. package/dist/statsAnalyzer/global.js.map +0 -1
  114. package/dist/statsAnalyzer/index.js +0 -1072
  115. package/dist/statsAnalyzer/index.js.map +0 -1
  116. package/dist/statsAnalyzer/mqaUtil.js +0 -368
  117. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  118. package/dist/types/mediaQualityMetrics/config.d.ts +0 -247
  119. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  120. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  121. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  122. package/src/mediaQualityMetrics/config.ts +0 -255
  123. package/src/statsAnalyzer/global.ts +0 -37
  124. package/src/statsAnalyzer/index.ts +0 -1318
  125. package/src/statsAnalyzer/mqaUtil.ts +0 -463
  126. package/test/unit/spec/stats-analyzer/index.js +0 -1819
@@ -1,1072 +0,0 @@
1
- "use strict";
2
-
3
- var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
4
- var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
5
- var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
6
- var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
7
- var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
8
- var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
9
- var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
10
- var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
11
- _Object$defineProperty(exports, "__esModule", {
12
- value: true
13
- });
14
- exports.StatsAnalyzer = exports.EVENTS = void 0;
15
- var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
16
- var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
17
- var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
18
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
19
- var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
20
- var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/assertThisInitialized"));
21
- var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
22
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
23
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
24
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
25
- var _lodash = require("lodash");
26
- var _internalMediaCore = require("@webex/internal-media-core");
27
- var _eventsScope = _interopRequireDefault(require("../common/events/events-scope"));
28
- var _constants = require("../constants");
29
- var _config = require("../mediaQualityMetrics/config");
30
- var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
31
- var _global = _interopRequireDefault(require("./global"));
32
- var _mqaUtil = require("./mqaUtil");
33
- function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
34
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
35
- function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
36
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /* eslint-disable prefer-destructuring */
37
- var EVENTS = exports.EVENTS = {
38
- MEDIA_QUALITY: 'MEDIA_QUALITY',
39
- LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',
40
- LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',
41
- REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',
42
- REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED'
43
- };
44
- var emptySender = {
45
- trackLabel: '',
46
- maxPacketLossRatio: 0,
47
- availableBandwidth: 0,
48
- bytesSent: 0,
49
- meanRemoteJitter: [],
50
- meanRoundTripTime: []
51
- };
52
- var emptyReceiver = {
53
- availableBandwidth: 0,
54
- bytesReceived: 0,
55
- meanRtpJitter: [],
56
- meanRoundTripTime: []
57
- };
58
- /**
59
- * Stats Analyzer class that will emit events based on detected quality
60
- *
61
- * @export
62
- * @class StatsAnalyzer
63
- * @extends {EventsScope}
64
- */
65
- var StatsAnalyzer = exports.StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
66
- (0, _inherits2.default)(StatsAnalyzer, _EventsScope);
67
- var _super = _createSuper(StatsAnalyzer);
68
- /**
69
- * Creates a new instance of StatsAnalyzer
70
- * @constructor
71
- * @public
72
- * @param {Object} config SDK Configuration Object
73
- * @param {Function} receiveSlotCallback Callback used to access receive slots.
74
- * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
75
- * @param {Object} statsResults Default properties for stats
76
- */
77
- function StatsAnalyzer(config) {
78
- var _this;
79
- var receiveSlotCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
80
- return undefined;
81
- };
82
- var networkQualityMonitor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
83
- var statsResults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _global.default;
84
- (0, _classCallCheck2.default)(this, StatsAnalyzer);
85
- _this = _super.call(this);
86
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "config", void 0);
87
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "correlationId", void 0);
88
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastEmittedStartStopEvent", void 0);
89
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastMqaDataSent", void 0);
90
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastStatsResults", void 0);
91
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "meetingMediaStatus", void 0);
92
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mqaInterval", void 0);
93
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mqaSentCount", void 0);
94
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "networkQualityMonitor", void 0);
95
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mediaConnection", void 0);
96
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsInterval", void 0);
97
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsResults", void 0);
98
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsStarted", void 0);
99
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "successfulCandidatePair", void 0);
100
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "localIpAddress", void 0);
101
- // 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
102
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "receiveSlotCallback", void 0);
103
- /**
104
- * emits started/stopped events for local/remote media by checking
105
- * if given values are increasing or not. The previousValue, currentValue
106
- * params can be any numerical value like number of receive packets or
107
- * decoded frames, etc.
108
- *
109
- * @private
110
- * @param {string} mediaType
111
- * @param {number} previousValue - value to compare
112
- * @param {number} currentValue - value to compare (must be same type of value as previousValue)
113
- * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received
114
- * @memberof StatsAnalyzer
115
- * @returns {void}
116
- */
117
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "emitStartStopEvents", function (mediaType, previousValue, currentValue, isLocal) {
118
- if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {
119
- throw new Error("Unsupported mediaType: ".concat(mediaType));
120
- }
121
-
122
- // eslint-disable-next-line no-param-reassign
123
- if (previousValue === undefined) previousValue = 0;
124
- // eslint-disable-next-line no-param-reassign
125
- if (currentValue === undefined) currentValue = 0;
126
- if (!_this.lastEmittedStartStopEvent[mediaType]) {
127
- _this.lastEmittedStartStopEvent[mediaType] = {};
128
- }
129
- var lastEmittedEvent = isLocal ? _this.lastEmittedStartStopEvent[mediaType].local : _this.lastEmittedStartStopEvent[mediaType].remote;
130
- var newEvent;
131
- if (currentValue - previousValue > 0) {
132
- newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
133
- } else if (currentValue === previousValue && currentValue > 0) {
134
- newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
135
- }
136
- if (newEvent && lastEmittedEvent !== newEvent) {
137
- if (isLocal) {
138
- _this.lastEmittedStartStopEvent[mediaType].local = newEvent;
139
- } else {
140
- _this.lastEmittedStartStopEvent[mediaType].remote = newEvent;
141
- }
142
- _this.emit({
143
- file: 'statsAnalyzer/index',
144
- function: 'compareLastStatsResult'
145
- }, newEvent, {
146
- type: mediaType
147
- });
148
- }
149
- });
150
- /**
151
- * extracts the local Ip address from the statsResult object by looking at stats results candidates
152
- * and matches that ID with the successful candidate pair. It looks at the type of local candidate it is
153
- * and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc
154
- * 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
155
- * for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP
156
- * @private
157
- * @param {string} successfulCandidatePairId - The ID of the successful candidate pair.
158
- * @param {Object} candidates - the stats result candidates
159
- * @returns {void}
160
- */
161
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "extractAndSetLocalIpAddressInfoForDiagnostics", function (successfulCandidatePairId, candidates) {
162
- var newIpAddress = '';
163
- if (successfulCandidatePairId && !(0, _lodash.isEmpty)(candidates)) {
164
- var localCandidate = candidates[successfulCandidatePairId];
165
- if (localCandidate) {
166
- if (localCandidate.candidateType === 'host') {
167
- // if it's a host candidate, use the address property - it will be the local IP
168
- newIpAddress = "".concat(localCandidate.address);
169
- } else if (localCandidate.candidateType === 'prflx') {
170
- // if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)
171
- // then look at the relatedAddress - it will be the local
172
- //
173
- // Firefox doesn't populate the relayProtocol property
174
- if (!localCandidate.relayProtocol) {
175
- newIpAddress = "".concat(localCandidate.relatedAddress);
176
- } else {
177
- // if it's a peer reflexive candidate and we are using a relay -
178
- // in that case the relatedAddress will be the IP of the TURN server (Linus),
179
- // so we can only look at the address, but it might be local IP or public IP,
180
- // depending on if the user is behind a NAT or not
181
- newIpAddress = "".concat(localCandidate.address);
182
- }
183
- }
184
- }
185
- }
186
- _this.localIpAddress = newIpAddress;
187
- });
188
- /**
189
- * Processes remote and local candidate result and stores
190
- * @private
191
- * @param {*} result
192
- * @param {*} type
193
- * @param {boolean} isSender
194
- * @param {boolean} isRemote
195
- *
196
- * @returns {void}
197
- */
198
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "parseCandidate", function (result, type, isSender, isRemote) {
199
- var _this$successfulCandi;
200
- if (!result || !result.id) {
201
- return;
202
- }
203
-
204
- // We only care about the successful local candidate
205
- if (((_this$successfulCandi = _this.successfulCandidatePair) === null || _this$successfulCandi === void 0 ? void 0 : _this$successfulCandi.localCandidateId) !== result.id) {
206
- return;
207
- }
208
- var transport;
209
- if (result.relayProtocol) {
210
- transport = result.relayProtocol.toUpperCase();
211
- } else if (result.protocol) {
212
- transport = result.protocol.toUpperCase();
213
- }
214
- var sendRecvType = isSender ? _constants.STATS.SEND_DIRECTION : _constants.STATS.RECEIVE_DIRECTION;
215
- var ipType = isRemote ? _constants.STATS.REMOTE : _constants.STATS.LOCAL;
216
- if (!_this.statsResults.candidates) {
217
- _this.statsResults.candidates = {};
218
- }
219
- _this.statsResults.candidates[result.id] = {
220
- candidateType: result.candidateType,
221
- ipAddress: result.ip,
222
- // TODO: add ports
223
- relatedAddress: result.relatedAddress,
224
- relatedPort: result.relatedPort,
225
- relayProtocol: result.relayProtocol,
226
- protocol: result.protocol,
227
- address: result.address,
228
- portNumber: result.port,
229
- networkType: result.networkType,
230
- priority: result.priority,
231
- transport: transport,
232
- timestamp: result.time,
233
- id: result.id,
234
- type: result.type
235
- };
236
- _this.statsResults.connectionType[ipType].candidateType = result.candidateType;
237
- _this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
238
- _this.statsResults.connectionType[ipType].networkType = result.networkType === _constants.NETWORK_TYPE.VPN ? _constants.NETWORK_TYPE.UNKNOWN : result.networkType;
239
- _this.statsResults.connectionType[ipType].transport = transport;
240
- _this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
241
- });
242
- _this.statsStarted = false;
243
- _this.statsResults = statsResults;
244
- _this.lastStatsResults = null;
245
- _this.config = config;
246
- _this.networkQualityMonitor = networkQualityMonitor;
247
- _this.correlationId = config.correlationId;
248
- _this.mqaSentCount = -1;
249
- _this.lastMqaDataSent = {};
250
- _this.lastEmittedStartStopEvent = {};
251
- _this.receiveSlotCallback = receiveSlotCallback;
252
- _this.successfulCandidatePair = {};
253
- _this.localIpAddress = '';
254
- return _this;
255
- }
256
-
257
- /**
258
- * Resets cumulative stats arrays.
259
- *
260
- * @public
261
- * @memberof StatsAnalyzer
262
- * @returns {void}
263
- */
264
- (0, _createClass2.default)(StatsAnalyzer, [{
265
- key: "resetStatsResults",
266
- value: function resetStatsResults() {
267
- var _this2 = this;
268
- (0, _keys.default)(this.statsResults).forEach(function (mediaType) {
269
- if (mediaType.includes('recv')) {
270
- _this2.statsResults[mediaType].recv.meanRtpJitter = [];
271
- }
272
- if (mediaType.includes('send')) {
273
- _this2.statsResults[mediaType].send.meanRemoteJitter = [];
274
- _this2.statsResults[mediaType].send.meanRoundTripTime = [];
275
- }
276
- });
277
- }
278
-
279
- /**
280
- * sets mediaStatus status for analyzing metrics
281
- *
282
- * @public
283
- * @param {Object} status for the audio and video
284
- * @memberof StatsAnalyzer
285
- * @returns {void}
286
- */
287
- }, {
288
- key: "updateMediaStatus",
289
- value: function updateMediaStatus(status) {
290
- var _this$meetingMediaSta, _this$meetingMediaSta2;
291
- this.meetingMediaStatus = {
292
- actual: _objectSpread(_objectSpread({}, (_this$meetingMediaSta = this.meetingMediaStatus) === null || _this$meetingMediaSta === void 0 ? void 0 : _this$meetingMediaSta.actual), status === null || status === void 0 ? void 0 : status.actual),
293
- expected: _objectSpread(_objectSpread({}, (_this$meetingMediaSta2 = this.meetingMediaStatus) === null || _this$meetingMediaSta2 === void 0 ? void 0 : _this$meetingMediaSta2.expected), status === null || status === void 0 ? void 0 : status.expected)
294
- };
295
- }
296
-
297
- /**
298
- * captures MQA data from media connection
299
- *
300
- * @public
301
- * @memberof StatsAnalyzer
302
- * @returns {void}
303
- */
304
- }, {
305
- key: "sendMqaData",
306
- value: function sendMqaData() {
307
- var _this3 = this;
308
- var newMqa = (0, _lodash.cloneDeep)(_config.emptyMqaInterval);
309
-
310
- // Fill in empty stats items for lastMqaDataSent
311
- (0, _keys.default)(this.statsResults).forEach(function (mediaType) {
312
- if (!_this3.lastMqaDataSent[mediaType]) {
313
- _this3.lastMqaDataSent[mediaType] = {};
314
- }
315
- if (!_this3.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
316
- _this3.lastMqaDataSent[mediaType].send = {};
317
- }
318
- if (!_this3.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
319
- _this3.lastMqaDataSent[mediaType].recv = {};
320
- }
321
- });
322
-
323
- // Create stats the first level, totals for senders and receivers
324
- var audioSender = (0, _lodash.cloneDeep)(_config.emptyAudioTransmit);
325
- var audioShareSender = (0, _lodash.cloneDeep)(_config.emptyAudioTransmit);
326
- var audioReceiver = (0, _lodash.cloneDeep)(_config.emptyAudioReceive);
327
- var audioShareReceiver = (0, _lodash.cloneDeep)(_config.emptyAudioReceive);
328
- var videoSender = (0, _lodash.cloneDeep)(_config.emptyVideoTransmit);
329
- var videoShareSender = (0, _lodash.cloneDeep)(_config.emptyVideoTransmit);
330
- var videoReceiver = (0, _lodash.cloneDeep)(_config.emptyVideoReceive);
331
- var videoShareReceiver = (0, _lodash.cloneDeep)(_config.emptyVideoReceive);
332
- (0, _mqaUtil.getAudioSenderMqa)({
333
- audioSender: audioSender,
334
- statsResults: this.statsResults,
335
- lastMqaDataSent: this.lastMqaDataSent,
336
- baseMediaType: 'audio-send'
337
- });
338
- newMqa.audioTransmit.push(audioSender);
339
- (0, _mqaUtil.getAudioSenderMqa)({
340
- audioSender: audioShareSender,
341
- statsResults: this.statsResults,
342
- lastMqaDataSent: this.lastMqaDataSent,
343
- baseMediaType: 'audio-share-send'
344
- });
345
- newMqa.audioTransmit.push(audioShareSender);
346
- (0, _mqaUtil.getAudioReceiverMqa)({
347
- audioReceiver: audioReceiver,
348
- statsResults: this.statsResults,
349
- lastMqaDataSent: this.lastMqaDataSent,
350
- baseMediaType: 'audio-recv'
351
- });
352
- newMqa.audioReceive.push(audioReceiver);
353
- (0, _mqaUtil.getAudioReceiverMqa)({
354
- audioReceiver: audioShareReceiver,
355
- statsResults: this.statsResults,
356
- lastMqaDataSent: this.lastMqaDataSent,
357
- baseMediaType: 'audio-share-recv'
358
- });
359
- newMqa.audioReceive.push(audioShareReceiver);
360
- (0, _mqaUtil.getVideoSenderMqa)({
361
- videoSender: videoSender,
362
- statsResults: this.statsResults,
363
- lastMqaDataSent: this.lastMqaDataSent,
364
- baseMediaType: 'video-send'
365
- });
366
- newMqa.videoTransmit.push(videoSender);
367
- (0, _mqaUtil.getVideoSenderMqa)({
368
- videoSender: videoShareSender,
369
- statsResults: this.statsResults,
370
- lastMqaDataSent: this.lastMqaDataSent,
371
- baseMediaType: 'video-share-send'
372
- });
373
- newMqa.videoTransmit.push(videoShareSender);
374
- (0, _mqaUtil.getVideoReceiverMqa)({
375
- videoReceiver: videoReceiver,
376
- statsResults: this.statsResults,
377
- lastMqaDataSent: this.lastMqaDataSent,
378
- baseMediaType: 'video-recv'
379
- });
380
- newMqa.videoReceive.push(videoReceiver);
381
- (0, _mqaUtil.getVideoReceiverMqa)({
382
- videoReceiver: videoShareReceiver,
383
- statsResults: this.statsResults,
384
- lastMqaDataSent: this.lastMqaDataSent,
385
- baseMediaType: 'video-share-recv'
386
- });
387
- newMqa.videoReceive.push(videoShareReceiver);
388
-
389
- // Add stats for individual streams
390
- (0, _keys.default)(this.statsResults).forEach(function (mediaType) {
391
- if (mediaType.startsWith('audio-send')) {
392
- var audioSenderStream = (0, _lodash.cloneDeep)(_config.emptyAudioTransmitStream);
393
- (0, _mqaUtil.getAudioSenderStreamMqa)({
394
- audioSenderStream: audioSenderStream,
395
- statsResults: _this3.statsResults,
396
- lastMqaDataSent: _this3.lastMqaDataSent,
397
- mediaType: mediaType
398
- });
399
- newMqa.audioTransmit[0].streams.push(audioSenderStream);
400
- _this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
401
- } else if (mediaType.startsWith('audio-share-send')) {
402
- var _audioSenderStream = (0, _lodash.cloneDeep)(_config.emptyAudioTransmitStream);
403
- (0, _mqaUtil.getAudioSenderStreamMqa)({
404
- audioSenderStream: _audioSenderStream,
405
- statsResults: _this3.statsResults,
406
- lastMqaDataSent: _this3.lastMqaDataSent,
407
- mediaType: mediaType
408
- });
409
- newMqa.audioTransmit[1].streams.push(_audioSenderStream);
410
- _this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
411
- } else if (mediaType.startsWith('audio-recv')) {
412
- var audioReceiverStream = (0, _lodash.cloneDeep)(_config.emptyAudioReceiveStream);
413
- (0, _mqaUtil.getAudioReceiverStreamMqa)({
414
- audioReceiverStream: audioReceiverStream,
415
- statsResults: _this3.statsResults,
416
- lastMqaDataSent: _this3.lastMqaDataSent,
417
- mediaType: mediaType
418
- });
419
- newMqa.audioReceive[0].streams.push(audioReceiverStream);
420
- _this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
421
- } else if (mediaType.startsWith('audio-share-recv')) {
422
- var _audioReceiverStream = (0, _lodash.cloneDeep)(_config.emptyAudioReceiveStream);
423
- (0, _mqaUtil.getAudioReceiverStreamMqa)({
424
- audioReceiverStream: _audioReceiverStream,
425
- statsResults: _this3.statsResults,
426
- lastMqaDataSent: _this3.lastMqaDataSent,
427
- mediaType: mediaType
428
- });
429
- newMqa.audioReceive[1].streams.push(_audioReceiverStream);
430
- _this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
431
- } else if (mediaType.startsWith('video-send-layer')) {
432
- // We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.
433
- var videoSenderStream = (0, _lodash.cloneDeep)(_config.emptyVideoTransmitStream);
434
- (0, _mqaUtil.getVideoSenderStreamMqa)({
435
- videoSenderStream: videoSenderStream,
436
- statsResults: _this3.statsResults,
437
- lastMqaDataSent: _this3.lastMqaDataSent,
438
- mediaType: mediaType
439
- });
440
- newMqa.videoTransmit[0].streams.push(videoSenderStream);
441
- _this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
442
- } else if (mediaType.startsWith('video-share-send')) {
443
- var _videoSenderStream = (0, _lodash.cloneDeep)(_config.emptyVideoTransmitStream);
444
- (0, _mqaUtil.getVideoSenderStreamMqa)({
445
- videoSenderStream: _videoSenderStream,
446
- statsResults: _this3.statsResults,
447
- lastMqaDataSent: _this3.lastMqaDataSent,
448
- mediaType: mediaType
449
- });
450
- newMqa.videoTransmit[1].streams.push(_videoSenderStream);
451
- _this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
452
- } else if (mediaType.startsWith('video-recv')) {
453
- var videoReceiverStream = (0, _lodash.cloneDeep)(_config.emptyVideoReceiveStream);
454
- (0, _mqaUtil.getVideoReceiverStreamMqa)({
455
- videoReceiverStream: videoReceiverStream,
456
- statsResults: _this3.statsResults,
457
- lastMqaDataSent: _this3.lastMqaDataSent,
458
- mediaType: mediaType
459
- });
460
- newMqa.videoReceive[0].streams.push(videoReceiverStream);
461
- _this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
462
- } else if (mediaType.startsWith('video-share-recv')) {
463
- var _videoReceiverStream = (0, _lodash.cloneDeep)(_config.emptyVideoReceiveStream);
464
- (0, _mqaUtil.getVideoReceiverStreamMqa)({
465
- videoReceiverStream: _videoReceiverStream,
466
- statsResults: _this3.statsResults,
467
- lastMqaDataSent: _this3.lastMqaDataSent,
468
- mediaType: mediaType
469
- });
470
- newMqa.videoReceive[1].streams.push(_videoReceiverStream);
471
- _this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
472
- }
473
- });
474
- newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
475
-
476
- // Adding peripheral information
477
- newMqa.intervalMetadata.peripherals.push({
478
- information: _constants._UNKNOWN_,
479
- name: _constants.MEDIA_DEVICES.SPEAKER
480
- });
481
- if (this.statsResults['audio-send']) {
482
- newMqa.intervalMetadata.peripherals.push({
483
- information: this.statsResults['audio-send'].trackLabel || _constants._UNKNOWN_,
484
- name: _constants.MEDIA_DEVICES.MICROPHONE
485
- });
486
- }
487
- var existingVideoSender = (0, _keys.default)(this.statsResults).find(function (item) {
488
- return item.includes('video-send');
489
- });
490
- if (existingVideoSender) {
491
- newMqa.intervalMetadata.peripherals.push({
492
- information: this.statsResults[existingVideoSender].trackLabel || _constants._UNKNOWN_,
493
- name: _constants.MEDIA_DEVICES.CAMERA
494
- });
495
- }
496
- newMqa.networkType = this.statsResults.connectionType.local.networkType;
497
- this.mqaSentCount += 1;
498
- newMqa.intervalNumber = this.mqaSentCount;
499
- this.resetStatsResults();
500
- this.emit({
501
- file: 'statsAnalyzer',
502
- function: 'sendMqaData'
503
- }, EVENTS.MEDIA_QUALITY, {
504
- data: newMqa,
505
- // @ts-ignore
506
- networkType: newMqa.networkType
507
- });
508
- }
509
-
510
- /**
511
- * updated the media connection when changed
512
- *
513
- * @private
514
- * @memberof StatsAnalyzer
515
- * @param {RoapMediaConnection} mediaConnection
516
- * @returns {void}
517
- */
518
- }, {
519
- key: "updateMediaConnection",
520
- value: function updateMediaConnection(mediaConnection) {
521
- this.mediaConnection = mediaConnection;
522
- }
523
-
524
- /**
525
- * Returns the local IP address for diagnostics.
526
- * this is the local IP of the interface used for the current media connection
527
- * a host can have many local Ip Addresses
528
- * @returns {string | undefined} The local IP address.
529
- */
530
- }, {
531
- key: "getLocalIpAddress",
532
- value: function getLocalIpAddress() {
533
- return this.localIpAddress;
534
- }
535
-
536
- /**
537
- * Starts the stats analyzer on interval
538
- *
539
- * @public
540
- * @memberof StatsAnalyzer
541
- * @param {RoapMediaConnection} mediaConnection
542
- * @returns {Promise}
543
- */
544
- }, {
545
- key: "startAnalyzer",
546
- value: function startAnalyzer(mediaConnection) {
547
- var _this4 = this;
548
- if (!this.statsStarted) {
549
- this.statsStarted = true;
550
- this.mediaConnection = mediaConnection;
551
- return this.getStatsAndParse().then(function () {
552
- _this4.statsInterval = setInterval(function () {
553
- _this4.getStatsAndParse();
554
- }, _this4.config.analyzerInterval);
555
- // Trigger initial fetch
556
- _this4.sendMqaData();
557
- _this4.mqaInterval = setInterval(function () {
558
- _this4.sendMqaData();
559
- }, _constants.MQA_INTERVAL);
560
- });
561
- }
562
- return _promise.default.resolve();
563
- }
564
-
565
- /**
566
- * Cleans up the analyzer when done
567
- *
568
- * @public
569
- * @memberof StatsAnalyzer
570
- * @returns {void}
571
- */
572
- }, {
573
- key: "stopAnalyzer",
574
- value: function stopAnalyzer() {
575
- var _this5 = this;
576
- var sendOneLastMqa = this.mqaInterval && this.statsInterval;
577
- if (this.statsInterval) {
578
- clearInterval(this.statsInterval);
579
- this.statsInterval = undefined;
580
- }
581
- if (this.mqaInterval) {
582
- clearInterval(this.mqaInterval);
583
- this.mqaInterval = undefined;
584
- }
585
- if (sendOneLastMqa) {
586
- return this.getStatsAndParse().then(function () {
587
- _this5.sendMqaData();
588
- _this5.mediaConnection = null;
589
- });
590
- }
591
- return _promise.default.resolve();
592
- }
593
-
594
- /**
595
- * Parse a single result of get stats
596
- *
597
- * @private
598
- * @param {*} getStatsResult
599
- * @param {String} type
600
- * @param {boolean} isSender
601
- * @returns {void}
602
- * @memberof StatsAnalyzer
603
- */
604
- }, {
605
- key: "parseGetStatsResult",
606
- value: function parseGetStatsResult(getStatsResult, type, isSender) {
607
- if (!getStatsResult) {
608
- return;
609
- }
610
-
611
- // Generate empty stats results
612
- if (!this.statsResults[type]) {
613
- this.statsResults[type] = {};
614
- }
615
- if (isSender && !this.statsResults[type].send) {
616
- this.statsResults[type].send = (0, _lodash.cloneDeep)(emptySender);
617
- } else if (!isSender && !this.statsResults[type].recv) {
618
- this.statsResults[type].recv = (0, _lodash.cloneDeep)(emptyReceiver);
619
- }
620
- switch (getStatsResult.type) {
621
- case 'outbound-rtp':
622
- this.processOutboundRTPResult(getStatsResult, type);
623
- break;
624
- case 'inbound-rtp':
625
- this.processInboundRTPResult(getStatsResult, type);
626
- break;
627
- case 'remote-inbound-rtp':
628
- case 'remote-outbound-rtp':
629
- this.compareSentAndReceived(getStatsResult, type);
630
- break;
631
- case 'remotecandidate':
632
- case 'remote-candidate':
633
- this.parseCandidate(getStatsResult, type, isSender, true);
634
- break;
635
- case 'local-candidate':
636
- this.parseCandidate(getStatsResult, type, isSender, false);
637
- break;
638
- case 'media-source':
639
- this.parseAudioSource(getStatsResult, type);
640
- break;
641
- default:
642
- break;
643
- }
644
- }
645
-
646
- /**
647
- * Filters the get stats results for types
648
- * @private
649
- * @param {Array} statsItem
650
- * @param {String} type
651
- * @param {boolean} isSender
652
- * @returns {void}
653
- */
654
- }, {
655
- key: "filterAndParseGetStatsResults",
656
- value: function filterAndParseGetStatsResults(statsItem, type, isSender) {
657
- var _this6 = this;
658
- var types = _constants.DEFAULT_GET_STATS_FILTER.types;
659
-
660
- // get the successful candidate pair before parsing stats.
661
- statsItem.report.forEach(function (report) {
662
- if (report.type === 'candidate-pair' && report.state === 'succeeded') {
663
- _this6.successfulCandidatePair = report;
664
- }
665
- });
666
- var videoSenderIndex = 0;
667
- statsItem.report.forEach(function (result) {
668
- if (types.includes(result.type)) {
669
- // if the video sender has multiple streams in the report, it is a new stream object.
670
- if (type === 'video-send' && result.type === 'outbound-rtp') {
671
- var newType = "video-send-layer-".concat(videoSenderIndex);
672
- _this6.parseGetStatsResult(result, newType, isSender);
673
- videoSenderIndex += 1;
674
- _this6.statsResults[newType].direction = statsItem.currentDirection;
675
- _this6.statsResults[newType].trackLabel = statsItem.localTrackLabel;
676
- _this6.statsResults[newType].csi = statsItem.csi;
677
- } else {
678
- _this6.parseGetStatsResult(result, type, isSender);
679
- }
680
- }
681
- });
682
- if (this.statsResults[type]) {
683
- var _this$successfulCandi2, _this$statsResults;
684
- this.statsResults[type].direction = statsItem.currentDirection;
685
- this.statsResults[type].trackLabel = statsItem.localTrackLabel;
686
- this.statsResults[type].csi = statsItem.csi;
687
- this.extractAndSetLocalIpAddressInfoForDiagnostics((_this$successfulCandi2 = this.successfulCandidatePair) === null || _this$successfulCandi2 === void 0 ? void 0 : _this$successfulCandi2.localCandidateId, (_this$statsResults = this.statsResults) === null || _this$statsResults === void 0 ? void 0 : _this$statsResults.candidates);
688
- // reset the successful candidate pair.
689
- this.successfulCandidatePair = {};
690
- }
691
- }
692
-
693
- /**
694
- * parse the audio
695
- * @param {String} result
696
- * @param {boolean} type
697
- * @returns {void}
698
- */
699
- }, {
700
- key: "parseAudioSource",
701
- value: function parseAudioSource(result, type) {
702
- if (!result) {
703
- return;
704
- }
705
- if (type.includes('audio-send')) {
706
- this.statsResults[type].send.audioLevel = result.audioLevel;
707
- this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;
708
- }
709
- }
710
- }, {
711
- key: "compareLastStatsResult",
712
- value:
713
- /**
714
- * compares current and previous stats to check if packets are not sent
715
- *
716
- * @private
717
- * @memberof StatsAnalyzer
718
- * @returns {void}
719
- */
720
- function compareLastStatsResult() {
721
- var _this7 = this;
722
- if (this.lastStatsResults !== null && this.meetingMediaStatus) {
723
- var getCurrentStatsTotals = function getCurrentStatsTotals(keyPrefix, value) {
724
- return (0, _keys.default)(_this7.statsResults).filter(function (key) {
725
- return key.startsWith(keyPrefix);
726
- }).reduce(function (prev, cur) {
727
- var _this7$statsResults$c;
728
- 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);
729
- }, 0);
730
- };
731
- var getPreviousStatsTotals = function getPreviousStatsTotals(keyPrefix, value) {
732
- return (0, _keys.default)(_this7.statsResults).filter(function (key) {
733
- return key.startsWith(keyPrefix);
734
- }).reduce(function (prev, cur) {
735
- var _this7$lastStatsResul;
736
- return prev + (((_this7$lastStatsResul = _this7.lastStatsResults[cur]) === null || _this7$lastStatsResul === void 0 ? void 0 : _this7$lastStatsResul[keyPrefix.includes('send') ? 'send' : 'recv'][value]) || 0);
737
- }, 0);
738
- };
739
-
740
- // Audio Transmit
741
- if (this.lastStatsResults['audio-send']) {
742
- // compare audio stats sent
743
- // NOTE: relies on there being only one sender.
744
- var currentStats = this.statsResults['audio-send'].send;
745
- var previousStats = this.lastStatsResults['audio-send'].send;
746
- if (this.meetingMediaStatus.expected.sendAudio && currentStats.totalPacketsSent === previousStats.totalPacketsSent || currentStats.totalPacketsSent === 0) {
747
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent", currentStats.totalPacketsSent);
748
- } else {
749
- if (this.meetingMediaStatus.expected.sendAudio && currentStats.totalAudioEnergy === previousStats.totalAudioEnergy || currentStats.totalAudioEnergy === 0) {
750
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present", currentStats.totalAudioEnergy);
751
- }
752
- if (this.meetingMediaStatus.expected.sendAudio && currentStats.audioLevel === 0) {
753
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user");
754
- }
755
- }
756
- this.emitStartStopEvents('audio', previousStats.totalPacketsSent, currentStats.totalPacketsSent, true);
757
- }
758
-
759
- // Audio Receive
760
- var currentAudioPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
761
- var previousAudioPacketsReceived = getPreviousStatsTotals('audio-recv', 'totalPacketsReceived');
762
- this.emitStartStopEvents('audio', previousAudioPacketsReceived, currentAudioPacketsReceived, false);
763
- var currentTotalPacketsSent = getCurrentStatsTotals('video-send', 'totalPacketsSent');
764
- var previousTotalPacketsSent = getPreviousStatsTotals('video-send', 'totalPacketsSent');
765
- var currentFramesEncoded = getCurrentStatsTotals('video-send', 'framesEncoded');
766
- var previousFramesEncoded = getPreviousStatsTotals('video-send', 'framesEncoded');
767
- var currentFramesSent = getCurrentStatsTotals('video-send', 'framesSent');
768
- var previousFramesSent = getPreviousStatsTotals('video-send', 'framesSent');
769
- var doesVideoSendExist = (0, _keys.default)(this.lastStatsResults).some(function (item) {
770
- return item.includes('video-send');
771
- });
772
-
773
- // Video Transmit
774
- if (doesVideoSendExist) {
775
- // compare video stats sent
776
-
777
- if (this.meetingMediaStatus.expected.sendVideo && (currentTotalPacketsSent === previousTotalPacketsSent || currentTotalPacketsSent === 0)) {
778
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent", currentTotalPacketsSent);
779
- } else {
780
- if (this.meetingMediaStatus.expected.sendVideo && (currentFramesEncoded === previousFramesEncoded || currentFramesEncoded === 0)) {
781
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded", currentFramesEncoded);
782
- }
783
- if (this.meetingMediaStatus.expected.sendVideo && (currentFramesSent === previousFramesSent || currentFramesSent === 0)) {
784
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent", currentFramesSent);
785
- }
786
- }
787
- this.emitStartStopEvents('video', previousFramesSent, currentFramesSent, true);
788
- }
789
-
790
- // Video Receive
791
- var currentVideoFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
792
- var previousVideoFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
793
- this.emitStartStopEvents('video', previousVideoFramesDecoded, currentVideoFramesDecoded, false);
794
-
795
- // Share Transmit
796
- if (this.lastStatsResults['video-share-send']) {
797
- // compare share stats sent
798
-
799
- var _currentStats = this.statsResults['video-share-send'].send;
800
- var _previousStats = this.lastStatsResults['video-share-send'].send;
801
- if (this.meetingMediaStatus.expected.sendShare && (_currentStats.totalPacketsSent === _previousStats.totalPacketsSent || _currentStats.totalPacketsSent === 0)) {
802
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent", _currentStats.totalPacketsSent);
803
- } else {
804
- if (this.meetingMediaStatus.expected.sendShare && (_currentStats.framesEncoded === _previousStats.framesEncoded || _currentStats.framesEncoded === 0)) {
805
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded", _currentStats.framesEncoded);
806
- }
807
- 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)) {
808
- _loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames sent", this.statsResults['video-share-send'].send.framesSent);
809
- }
810
- }
811
- this.emitStartStopEvents('share', _previousStats.framesSent, _currentStats.framesSent, true);
812
- }
813
-
814
- // Share receive
815
- var currentShareFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
816
- var previousShareFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
817
- this.emitStartStopEvents('share', previousShareFramesDecoded, currentShareFramesDecoded, false);
818
- }
819
- }
820
-
821
- /**
822
- * Does a `getStats` on all the transceivers and parses the results
823
- *
824
- * @private
825
- * @memberof StatsAnalyzer
826
- * @returns {Promise}
827
- */
828
- }, {
829
- key: "getStatsAndParse",
830
- value: function getStatsAndParse() {
831
- var _this8 = this;
832
- if (!this.mediaConnection) {
833
- return _promise.default.resolve();
834
- }
835
- if (this.mediaConnection && this.mediaConnection.getConnectionState() === _internalMediaCore.ConnectionState.Failed) {
836
- _loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state');
837
- return _promise.default.resolve();
838
- }
839
- _loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');
840
- return this.mediaConnection.getTransceiverStats().then(function (transceiverStats) {
841
- transceiverStats.video.receivers.forEach(function (receiver, i) {
842
- return _this8.filterAndParseGetStatsResults(receiver, "video-recv-".concat(i), false);
843
- });
844
- transceiverStats.audio.receivers.forEach(function (receiver, i) {
845
- return _this8.filterAndParseGetStatsResults(receiver, "audio-recv-".concat(i), false);
846
- });
847
- transceiverStats.screenShareVideo.receivers.forEach(function (receiver, i) {
848
- return _this8.filterAndParseGetStatsResults(receiver, "video-share-recv-".concat(i), false);
849
- });
850
- transceiverStats.screenShareAudio.receivers.forEach(function (receiver, i) {
851
- return _this8.filterAndParseGetStatsResults(receiver, "audio-share-recv-".concat(i), false);
852
- });
853
- transceiverStats.video.senders.forEach(function (sender, i) {
854
- if (i > 0) {
855
- throw new Error('Stats Analyzer does not support multiple senders.');
856
- }
857
- _this8.filterAndParseGetStatsResults(sender, 'video-send', true);
858
- });
859
- transceiverStats.audio.senders.forEach(function (sender, i) {
860
- if (i > 0) {
861
- throw new Error('Stats Analyzer does not support multiple senders.');
862
- }
863
- _this8.filterAndParseGetStatsResults(sender, 'audio-send', true);
864
- });
865
- transceiverStats.screenShareVideo.senders.forEach(function (sender, i) {
866
- if (i > 0) {
867
- throw new Error('Stats Analyzer does not support multiple senders.');
868
- }
869
- _this8.filterAndParseGetStatsResults(sender, 'video-share-send', true);
870
- });
871
- transceiverStats.screenShareAudio.senders.forEach(function (sender, i) {
872
- if (i > 0) {
873
- throw new Error('Stats Analyzer does not support multiple senders.');
874
- }
875
- _this8.filterAndParseGetStatsResults(sender, 'audio-share-send', true);
876
- });
877
- _this8.compareLastStatsResult();
878
-
879
- // Save the last results to compare with the current
880
- // DO Deep copy, for some reason it takes the reference all the time rather then old value set
881
- _this8.lastStatsResults = JSON.parse((0, _stringify.default)(_this8.statsResults));
882
- _loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats');
883
- });
884
- }
885
-
886
- /**
887
- * Processes OutboundRTP stats result and stores
888
- * @private
889
- * @param {*} result
890
- * @param {*} mediaType
891
- * @returns {void}
892
- */
893
- }, {
894
- key: "processOutboundRTPResult",
895
- value: function processOutboundRTPResult(result, mediaType) {
896
- var sendrecvType = _constants.STATS.SEND_DIRECTION;
897
- if (result.bytesSent) {
898
- var kilobytes = 0;
899
- if (result.frameWidth && result.frameHeight) {
900
- this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
901
- this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
902
- this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
903
- this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
904
- }
905
- this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
906
- this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
907
- this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;
908
- this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;
909
-
910
- // Data saved to send MQA metrics
911
-
912
- this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;
913
- this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
914
- this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
915
- this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;
916
- this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;
917
- this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
918
- this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
919
- this.statsResults[mediaType][sendrecvType].encoderImplementation = result.encoderImplementation;
920
- this.statsResults[mediaType][sendrecvType].qualityLimitationReason = result.qualityLimitationReason;
921
- this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges = result.qualityLimitationResolutionChanges;
922
- this.statsResults[mediaType][sendrecvType].totalRtxPacketsSent = result.retransmittedPacketsSent;
923
- this.statsResults[mediaType][sendrecvType].totalRtxBytesSent = result.retransmittedBytesSent;
924
- this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;
925
- this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;
926
- this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
927
- this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
928
- }
929
- }
930
-
931
- /**
932
- * Processes InboundRTP stats result and stores
933
- * @private
934
- * @param {*} result
935
- * @param {*} mediaType
936
- * @returns {void}
937
- */
938
- }, {
939
- key: "processInboundRTPResult",
940
- value: function processInboundRTPResult(result, mediaType) {
941
- var sendrecvType = _constants.STATS.RECEIVE_DIRECTION;
942
- if (result.bytesReceived) {
943
- var kilobytes = 0;
944
- var receiveSlot = this.receiveSlotCallback(result.ssrc);
945
- var sourceState = receiveSlot === null || receiveSlot === void 0 ? void 0 : receiveSlot.sourceState;
946
- var idAndCsi = receiveSlot ? "id: \"".concat(receiveSlot.id || '', "\"").concat(receiveSlot.csi ? " and csi: ".concat(receiveSlot.csi) : '') : '';
947
- var bytes = result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;
948
- kilobytes = bytes / 1024;
949
- this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
950
- var currentPacketsLost = result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;
951
- if (currentPacketsLost < 0) {
952
- currentPacketsLost = 0;
953
- }
954
- var packetsReceivedDiff = result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;
955
- this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
956
- if (packetsReceivedDiff === 0) {
957
- if (receiveSlot && sourceState === 'live') {
958
- _loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No packets received for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total packets received on slot: "), result.packetsReceived);
959
- }
960
- }
961
- if (mediaType.startsWith('video') || mediaType.startsWith('share')) {
962
- var videoFramesReceivedDiff = result.framesReceived - this.statsResults[mediaType][sendrecvType].framesReceived;
963
- if (videoFramesReceivedDiff === 0) {
964
- if (receiveSlot && sourceState === 'live') {
965
- _loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No frames received for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames received on slot: "), result.framesReceived);
966
- }
967
- }
968
- var videoFramesDecodedDiff = result.framesDecoded - this.statsResults[mediaType][sendrecvType].framesDecoded;
969
- if (videoFramesDecodedDiff === 0) {
970
- if (receiveSlot && sourceState === 'live') {
971
- _loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No frames decoded for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames decoded on slot: "), result.framesDecoded);
972
- }
973
- }
974
- var videoFramesDroppedDiff = result.framesDropped - this.statsResults[mediaType][sendrecvType].framesDropped;
975
- if (videoFramesDroppedDiff > 10) {
976
- if (receiveSlot && sourceState === 'live') {
977
- _loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> Frames dropped for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames dropped on slot: "), result.framesDropped);
978
- }
979
- }
980
- }
981
-
982
- // Check the over all packet Lost ratio
983
- this.statsResults[mediaType][sendrecvType].currentPacketLossRatio = currentPacketsLost > 0 ? currentPacketsLost / (packetsReceivedDiff + currentPacketsLost) : 0;
984
- if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
985
- _loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ".concat(idAndCsi), this.statsResults[mediaType][sendrecvType].currentPacketLossRatio);
986
- }
987
- if (result.frameWidth && result.frameHeight) {
988
- this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
989
- this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
990
- this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;
991
- }
992
-
993
- // TODO: check the packet loss value is negative values here
994
-
995
- if (result.packetsLost) {
996
- this.statsResults[mediaType][sendrecvType].totalPacketsLost = result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;
997
- } else {
998
- this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;
999
- }
1000
- this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp = result.lastPacketReceivedTimestamp;
1001
- this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
1002
- this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
1003
-
1004
- // From Thin
1005
- this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
1006
- this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
1007
- this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
1008
- this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;
1009
- this.statsResults[mediaType][sendrecvType].framesDropped = result.framesDropped;
1010
- this.statsResults[mediaType][sendrecvType].decoderImplementation = result.decoderImplementation;
1011
- this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
1012
- this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;
1013
- this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;
1014
- this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;
1015
- this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;
1016
- this.statsResults[mediaType][sendrecvType].totalRtxPacketsReceived = result.retransmittedPacketsReceived;
1017
- this.statsResults[mediaType][sendrecvType].totalRtxBytesReceived = result.retransmittedBytesReceived;
1018
- this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);
1019
-
1020
- // Audio stats
1021
-
1022
- this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;
1023
- this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;
1024
- this.statsResults[mediaType][sendrecvType].totalSamplesReceived = result.totalSamplesReceived || 0;
1025
- this.statsResults[mediaType][sendrecvType].totalSamplesDecoded = result.totalSamplesDecoded || 0;
1026
- this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;
1027
- }
1028
- }
1029
- }, {
1030
- key: "compareSentAndReceived",
1031
- value:
1032
- /**
1033
- *
1034
- * @private
1035
- * @param {*} result
1036
- * @param {*} type
1037
- * @returns {void}
1038
- * @memberof StatsAnalyzer
1039
- */
1040
- function compareSentAndReceived(result, type) {
1041
- // Don't compare on transceivers without a sender.
1042
- if (!type || !this.statsResults[type].send) {
1043
- return;
1044
- }
1045
- var mediaType = type;
1046
- var currentPacketLoss = result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;
1047
- this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
1048
- this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1049
- this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);
1050
- this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);
1051
- this.statsResults[mediaType].send.timestamp = result.timestamp;
1052
- this.statsResults[mediaType].send.ssrc = result.ssrc;
1053
- this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;
1054
-
1055
- // Total packloss ratio on this video section of the call
1056
- this.statsResults[mediaType].send.overAllPacketLossRatio = this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0 ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver / this.statsResults[mediaType].send.totalPacketsSent : 0;
1057
- this.statsResults[mediaType].send.currentPacketLossRatio = this.statsResults[mediaType].send.packetsLostOnReceiver > 0 ? this.statsResults[mediaType].send.packetsLostOnReceiver * 100 / (this.statsResults[mediaType].send.packetsSent + this.statsResults[mediaType].send.packetsLostOnReceiver) : 0;
1058
- if (this.statsResults[mediaType].send.maxPacketLossRatio < this.statsResults[mediaType].send.currentPacketLossRatio) {
1059
- this.statsResults[mediaType].send.maxPacketLossRatio = this.statsResults[mediaType].send.currentPacketLossRatio;
1060
- }
1061
- if (result.type === 'remote-inbound-rtp') {
1062
- this.networkQualityMonitor.determineUplinkNetworkQuality({
1063
- mediaType: mediaType,
1064
- remoteRtpResults: result,
1065
- statsAnalyzerCurrentStats: this.statsResults
1066
- });
1067
- }
1068
- }
1069
- }]);
1070
- return StatsAnalyzer;
1071
- }(_eventsScope.default);
1072
- //# sourceMappingURL=index.js.map