@webex/plugin-meetings 3.0.0-beta.16 → 3.0.0-beta.18

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 (156) hide show
  1. package/dist/breakouts/breakout.js +116 -0
  2. package/dist/breakouts/breakout.js.map +1 -0
  3. package/dist/breakouts/collection.js +23 -0
  4. package/dist/breakouts/collection.js.map +1 -0
  5. package/dist/breakouts/index.js +226 -0
  6. package/dist/breakouts/index.js.map +1 -0
  7. package/dist/config.js +4 -1
  8. package/dist/config.js.map +1 -1
  9. package/dist/constants.js +43 -6
  10. package/dist/constants.js.map +1 -1
  11. package/dist/locus-info/controlsUtils.js +2 -1
  12. package/dist/locus-info/controlsUtils.js.map +1 -1
  13. package/dist/locus-info/index.js +48 -0
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/locus-info/parser.js +1 -0
  16. package/dist/locus-info/parser.js.map +1 -1
  17. package/dist/locus-info/selfUtils.js +19 -11
  18. package/dist/locus-info/selfUtils.js.map +1 -1
  19. package/dist/media/index.js +3 -3
  20. package/dist/media/index.js.map +1 -1
  21. package/dist/media/properties.js +4 -4
  22. package/dist/media/properties.js.map +1 -1
  23. package/dist/meeting/in-meeting-actions.js +5 -1
  24. package/dist/meeting/in-meeting-actions.js.map +1 -1
  25. package/dist/meeting/index.js +652 -459
  26. package/dist/meeting/index.js.map +1 -1
  27. package/dist/meeting/request.js +25 -44
  28. package/dist/meeting/request.js.map +1 -1
  29. package/dist/meeting/request.type.js.map +1 -1
  30. package/dist/meeting/util.js +22 -57
  31. package/dist/meeting/util.js.map +1 -1
  32. package/dist/meeting-info/meeting-info-v2.js +2 -0
  33. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  34. package/dist/meetings/index.js +28 -18
  35. package/dist/meetings/index.js.map +1 -1
  36. package/dist/meetings/request.js +14 -12
  37. package/dist/meetings/request.js.map +1 -1
  38. package/dist/member/index.js +9 -0
  39. package/dist/member/index.js.map +1 -1
  40. package/dist/member/util.js +14 -1
  41. package/dist/member/util.js.map +1 -1
  42. package/dist/members/index.js +8 -6
  43. package/dist/members/index.js.map +1 -1
  44. package/dist/members/request.js +3 -1
  45. package/dist/members/request.js.map +1 -1
  46. package/dist/multistream/mediaRequestManager.js +46 -6
  47. package/dist/multistream/mediaRequestManager.js.map +1 -1
  48. package/dist/multistream/multistreamMedia.js +4 -0
  49. package/dist/multistream/multistreamMedia.js.map +1 -1
  50. package/dist/multistream/receiveSlot.js +3 -3
  51. package/dist/multistream/receiveSlot.js.map +1 -1
  52. package/dist/multistream/receiveSlotManager.js +8 -6
  53. package/dist/multistream/receiveSlotManager.js.map +1 -1
  54. package/dist/multistream/remoteMedia.js.map +1 -1
  55. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  56. package/dist/multistream/remoteMediaManager.js +168 -63
  57. package/dist/multistream/remoteMediaManager.js.map +1 -1
  58. package/dist/reachability/index.js +63 -51
  59. package/dist/reachability/index.js.map +1 -1
  60. package/dist/reactions/constants.js +13 -0
  61. package/dist/reactions/constants.js.map +1 -0
  62. package/dist/reactions/reactions.type.js.map +1 -1
  63. package/dist/reconnection-manager/index.js +25 -12
  64. package/dist/reconnection-manager/index.js.map +1 -1
  65. package/dist/recording-controller/enums.js +17 -0
  66. package/dist/recording-controller/enums.js.map +1 -0
  67. package/dist/recording-controller/index.js +343 -0
  68. package/dist/recording-controller/index.js.map +1 -0
  69. package/dist/recording-controller/util.js +63 -0
  70. package/dist/recording-controller/util.js.map +1 -0
  71. package/dist/roap/request.js +88 -68
  72. package/dist/roap/request.js.map +1 -1
  73. package/dist/roap/turnDiscovery.js +72 -47
  74. package/dist/roap/turnDiscovery.js.map +1 -1
  75. package/dist/statsAnalyzer/index.js +3 -3
  76. package/dist/statsAnalyzer/index.js.map +1 -1
  77. package/dist/statsAnalyzer/mqaUtil.js +18 -6
  78. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  79. package/package.json +24 -19
  80. package/src/breakouts/README.md +190 -0
  81. package/src/breakouts/breakout.ts +110 -0
  82. package/src/breakouts/collection.ts +19 -0
  83. package/src/breakouts/index.ts +225 -0
  84. package/src/config.ts +4 -1
  85. package/src/constants.ts +39 -1
  86. package/src/locus-info/controlsUtils.ts +2 -0
  87. package/src/locus-info/index.ts +59 -1
  88. package/src/locus-info/parser.ts +1 -0
  89. package/src/locus-info/selfUtils.ts +8 -0
  90. package/src/media/index.ts +1 -2
  91. package/src/media/properties.ts +6 -9
  92. package/src/meeting/in-meeting-actions.ts +8 -0
  93. package/src/meeting/index.ts +360 -111
  94. package/src/meeting/request.ts +9 -31
  95. package/src/meeting/request.type.ts +2 -0
  96. package/src/meeting/util.ts +25 -60
  97. package/src/meeting-info/meeting-info-v2.ts +2 -0
  98. package/src/meetings/index.ts +10 -5
  99. package/src/meetings/request.ts +1 -1
  100. package/src/member/index.ts +9 -0
  101. package/src/member/util.ts +14 -1
  102. package/src/members/index.ts +1 -0
  103. package/src/members/request.ts +1 -0
  104. package/src/multistream/mediaRequestManager.ts +79 -15
  105. package/src/multistream/multistreamMedia.ts +4 -0
  106. package/src/multistream/receiveSlot.ts +17 -12
  107. package/src/multistream/receiveSlotManager.ts +22 -21
  108. package/src/multistream/remoteMedia.ts +1 -1
  109. package/src/multistream/remoteMediaGroup.ts +2 -2
  110. package/src/multistream/remoteMediaManager.ts +150 -37
  111. package/src/reachability/index.ts +16 -13
  112. package/src/reactions/constants.ts +4 -0
  113. package/src/reactions/reactions.type.ts +25 -0
  114. package/src/reconnection-manager/index.ts +18 -9
  115. package/src/recording-controller/enums.ts +8 -0
  116. package/src/recording-controller/index.ts +315 -0
  117. package/src/recording-controller/util.ts +58 -0
  118. package/src/roap/request.ts +78 -73
  119. package/src/roap/turnDiscovery.ts +8 -6
  120. package/src/statsAnalyzer/index.ts +4 -4
  121. package/src/statsAnalyzer/mqaUtil.ts +6 -0
  122. package/test/unit/spec/breakouts/breakout.ts +119 -0
  123. package/test/unit/spec/breakouts/collection.ts +15 -0
  124. package/test/unit/spec/breakouts/index.ts +293 -0
  125. package/test/unit/spec/locus-info/controlsUtils.js +20 -0
  126. package/test/unit/spec/locus-info/index.js +103 -0
  127. package/test/unit/spec/locus-info/selfConstant.js +25 -0
  128. package/test/unit/spec/locus-info/selfUtils.js +84 -0
  129. package/test/unit/spec/media/index.ts +1 -1
  130. package/test/unit/spec/media/properties.ts +9 -9
  131. package/test/unit/spec/meeting/effectsState.js +5 -1
  132. package/test/unit/spec/meeting/in-meeting-actions.ts +5 -1
  133. package/test/unit/spec/meeting/index.js +241 -50
  134. package/test/unit/spec/meeting/request.js +17 -0
  135. package/test/unit/spec/meeting/utils.js +28 -122
  136. package/test/unit/spec/meetings/index.js +1 -0
  137. package/test/unit/spec/member/util.js +26 -1
  138. package/test/unit/spec/multistream/mediaRequestManager.ts +312 -50
  139. package/test/unit/spec/multistream/receiveSlot.ts +6 -6
  140. package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
  141. package/test/unit/spec/multistream/remoteMedia.ts +2 -2
  142. package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
  143. package/test/unit/spec/multistream/remoteMediaManager.ts +354 -65
  144. package/test/unit/spec/reachability/index.ts +58 -24
  145. package/test/unit/spec/reconnection-manager/index.js +42 -13
  146. package/test/unit/spec/recording-controller/index.js +231 -0
  147. package/test/unit/spec/recording-controller/util.js +102 -0
  148. package/test/unit/spec/roap/index.ts +2 -1
  149. package/test/unit/spec/roap/request.ts +114 -0
  150. package/test/unit/spec/roap/turnDiscovery.ts +45 -29
  151. package/test/unit/spec/stats-analyzer/index.js +2 -2
  152. package/test/utils/webex-test-users.js +1 -0
  153. package/tsconfig.json +6 -0
  154. package/dist/media/internal-media-core-wrapper.js +0 -18
  155. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  156. package/src/media/internal-media-core-wrapper.ts +0 -9
@@ -0,0 +1,315 @@
1
+ import PermissionError from '../common/errors/permission';
2
+ import {CONTROLS, HTTP_VERBS} from '../constants';
3
+ import MeetingRequest from '../meeting/request';
4
+ import RecordingAction from './enums';
5
+ import Util from './util';
6
+ import LoggerProxy from '../common/logs/logger-proxy';
7
+
8
+ /**
9
+ * @description Recording manages the recording functionality of the meeting object, there should only be one instantation of recording per meeting
10
+ * @export
11
+ * @private
12
+ * @class Recording
13
+ */
14
+ export default class RecordingController {
15
+ /**
16
+ * @instance
17
+ * @type {MeetingRequest}
18
+ * @private
19
+ * @memberof RecordingController
20
+ */
21
+ private request: MeetingRequest;
22
+
23
+ /**
24
+ * @instance
25
+ * @type {Array}
26
+ * @private
27
+ * @memberof RecordingInfo
28
+ */
29
+ private displayHints: Array<string> = [];
30
+
31
+ /**
32
+ * @instance
33
+ * @type {string}
34
+ * @private
35
+ * @memberof RecordingInfo
36
+ */
37
+ private serviceUrl: string;
38
+
39
+ /**
40
+ * @instance
41
+ * @type {string}
42
+ * @private
43
+ * @memberof RecordingInfo
44
+ */
45
+ private sessionId: string;
46
+
47
+ /**
48
+ * @instance
49
+ * @type {string}
50
+ * @private
51
+ * @memberof RecordingInfo
52
+ */
53
+ private locusUrl: string;
54
+
55
+ /**
56
+ * @instance
57
+ * @type {string}
58
+ * @private
59
+ * @memberof RecordingInfo
60
+ */
61
+ private locusId: string;
62
+
63
+ /**
64
+ * @param {MeetingRequest} request
65
+ * @param {Object} options
66
+ * @constructor
67
+ * @memberof RecordingController
68
+ */
69
+ constructor(
70
+ request: MeetingRequest,
71
+ options?: {
72
+ serviceUrl?: string;
73
+ sessionId: string;
74
+ locusUrl: string;
75
+ displayHints?: Array<string>;
76
+ }
77
+ ) {
78
+ this.initialize(request);
79
+ this.set(options);
80
+ }
81
+
82
+ /**
83
+ * @param {MeetingRequest} request
84
+ * @param {LocusInfo} info
85
+ * @returns {void}
86
+ * @private
87
+ * @memberof RecordingController
88
+ */
89
+ private initialize(request: MeetingRequest) {
90
+ this.request = request;
91
+ }
92
+
93
+ /**
94
+ * @param {Object} options
95
+ * @returns {void}
96
+ * @public
97
+ * @memberof RecordingController
98
+ */
99
+ public set(options?: {
100
+ serviceUrl?: string;
101
+ sessionId: string;
102
+ locusUrl: string;
103
+ displayHints?: Array<string>;
104
+ }) {
105
+ this.extract(options);
106
+ }
107
+
108
+ /**
109
+ * @param {string} url
110
+ * @returns {void}
111
+ * @public
112
+ * @memberof RecordingController
113
+ */
114
+ public setLocusUrl(url: string) {
115
+ this.locusUrl = url;
116
+ this.locusId = Util.extractLocusId(this.locusUrl);
117
+ }
118
+
119
+ /**
120
+ * @param {Array} hints
121
+ * @returns {void}
122
+ * @public
123
+ * @memberof RecordingController
124
+ */
125
+ public setDisplayHints(hints: Array<string>) {
126
+ this.displayHints = hints;
127
+ }
128
+
129
+ /**
130
+ * @param {string} id
131
+ * @returns {void}
132
+ * @public
133
+ * @memberof RecordingController
134
+ */
135
+ public setSessionId(id: string) {
136
+ this.sessionId = id;
137
+ }
138
+
139
+ /**
140
+ * @param {string} url
141
+ * @returns {void}
142
+ * @public
143
+ * @memberof RecordingController
144
+ */
145
+ public setServiceUrl(url: string) {
146
+ this.serviceUrl = url;
147
+ }
148
+
149
+ /**
150
+ * @returns {string}
151
+ * @public
152
+ * @memberof RecordingController
153
+ */
154
+ public getLocusUrl() {
155
+ return this.locusUrl;
156
+ }
157
+
158
+ /**
159
+ * @returns {string}
160
+ * @public
161
+ * @memberof RecordingController
162
+ */
163
+ public getLocusId() {
164
+ return this.locusId;
165
+ }
166
+
167
+ /**
168
+ * @returns {string}
169
+ * @public
170
+ * @memberof RecordingController
171
+ */
172
+ public getSessionId() {
173
+ return this.sessionId;
174
+ }
175
+
176
+ /**
177
+ * @returns {string}
178
+ * @public
179
+ * @memberof RecordingController
180
+ */
181
+ public getServiceUrl() {
182
+ return this.serviceUrl;
183
+ }
184
+
185
+ /**
186
+ * @returns {Array}
187
+ * @public
188
+ * @memberof RecordingController
189
+ */
190
+ public getDisplayHints() {
191
+ return this.displayHints;
192
+ }
193
+
194
+ /**
195
+ * @param {Object} options
196
+ * @returns {void}
197
+ * @private
198
+ * @memberof RecordingController
199
+ */
200
+ private extract(options?: {
201
+ serviceUrl?: string;
202
+ sessionId: string;
203
+ locusUrl: string;
204
+ displayHints?: Array<string>;
205
+ }) {
206
+ this.setServiceUrl(options?.serviceUrl);
207
+ this.setSessionId(options?.sessionId);
208
+ this.setDisplayHints(options?.displayHints);
209
+ this.setLocusUrl(options?.locusUrl);
210
+ }
211
+
212
+ /**
213
+ * @param {RecordingAction} action
214
+ * @private
215
+ * @memberof RecordingController
216
+ * @returns {Promise}
217
+ */
218
+ private recordingService(action: RecordingAction): Promise<any> {
219
+ // @ts-ignore
220
+ return this.request.request({
221
+ body: {
222
+ meetingInfo: {
223
+ locusSessionId: this.sessionId,
224
+ },
225
+ recording: {
226
+ action: action.toLowerCase(),
227
+ },
228
+ },
229
+ uri: `${this.serviceUrl}/loci/${this.locusId}/recording`,
230
+ method: HTTP_VERBS.PUT,
231
+ });
232
+ }
233
+
234
+ /**
235
+ * @param {RecordingAction} action
236
+ * @private
237
+ * @memberof RecordingController
238
+ * @returns {Promise}
239
+ */
240
+ private recordingControls(action: RecordingAction): Promise<any> {
241
+ const record = Util.deriveRecordingStates(action);
242
+
243
+ LoggerProxy.logger.log(`RecordingController:index#recordingControls --> ${record}`);
244
+
245
+ // @ts-ignore
246
+ return this.request.request({
247
+ uri: `${this.locusUrl}/${CONTROLS}`,
248
+ body: {
249
+ record,
250
+ },
251
+ method: HTTP_VERBS.PATCH,
252
+ });
253
+ }
254
+
255
+ /**
256
+ * @param {RecordingAction} action
257
+ * @private
258
+ * @memberof RecordingController
259
+ * @returns {Promise}
260
+ */
261
+ private recordingFacade(action: RecordingAction): Promise<any> {
262
+ LoggerProxy.logger.log(
263
+ `RecordingController:index#recordingFacade --> recording action [${action}]`
264
+ );
265
+
266
+ // assumes action is proper cased (i.e., Example)
267
+ if (Util?.[`canUser${action}`](this.displayHints)) {
268
+ if (this.serviceUrl) {
269
+ return this.recordingService(action);
270
+ }
271
+
272
+ return this.recordingControls(action);
273
+ }
274
+
275
+ return Promise.reject(
276
+ new PermissionError(`${action} recording not allowed, due to moderator property.`)
277
+ );
278
+ }
279
+
280
+ /**
281
+ * @private
282
+ * @memberof RecordingController
283
+ * @returns {Promise}
284
+ */
285
+ public startRecording(): Promise<any> {
286
+ return this.recordingFacade(RecordingAction.Start);
287
+ }
288
+
289
+ /**
290
+ * @private
291
+ * @memberof RecordingController
292
+ * @returns {Promise}
293
+ */
294
+ public stopRecording(): Promise<any> {
295
+ return this.recordingFacade(RecordingAction.Stop);
296
+ }
297
+
298
+ /**
299
+ * @private
300
+ * @memberof RecordingController
301
+ * @returns {Promise}
302
+ */
303
+ public pauseRecording(): Promise<any> {
304
+ return this.recordingFacade(RecordingAction.Pause);
305
+ }
306
+
307
+ /**
308
+ * @private
309
+ * @memberof RecordingController
310
+ * @returns {Promise}
311
+ */
312
+ public resumeRecording(): Promise<any> {
313
+ return this.recordingFacade(RecordingAction.Resume);
314
+ }
315
+ }
@@ -0,0 +1,58 @@
1
+ import {DISPLAY_HINTS} from '../constants';
2
+ import RecordingAction from './enums';
3
+
4
+ const canUserStart = (displayHints: Array<string>): boolean =>
5
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
6
+
7
+ const canUserPause = (displayHints: Array<string>): boolean =>
8
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
9
+
10
+ const canUserResume = (displayHints: Array<string>): boolean =>
11
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
12
+
13
+ const canUserStop = (displayHints: Array<string>): boolean =>
14
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
15
+
16
+ const extractLocusId = (url: string) => {
17
+ return url?.split('/').pop();
18
+ };
19
+
20
+ const deriveRecordingStates = (action: RecordingAction): {recording: boolean; paused: boolean} => {
21
+ let recording;
22
+ let paused;
23
+
24
+ switch (action) {
25
+ case RecordingAction.Start:
26
+ recording = true;
27
+ paused = false;
28
+ break;
29
+ case RecordingAction.Stop:
30
+ recording = false;
31
+ paused = false;
32
+ break;
33
+ case RecordingAction.Resume:
34
+ recording = true;
35
+ paused = false;
36
+ break;
37
+ case RecordingAction.Pause:
38
+ recording = true;
39
+ paused = true;
40
+ break;
41
+ default:
42
+ throw new Error(`Recording state cannot be derived from invalid action: ${action}`);
43
+ }
44
+
45
+ return {
46
+ recording,
47
+ paused,
48
+ };
49
+ };
50
+
51
+ export default {
52
+ canUserStart,
53
+ canUserPause,
54
+ canUserResume,
55
+ canUserStop,
56
+ deriveRecordingStates,
57
+ extractLocusId,
58
+ };
@@ -13,12 +13,14 @@ import {eventType} from '../metrics/config';
13
13
  export default class RoapRequest extends StatelessWebexPlugin {
14
14
  /**
15
15
  * Joins a meeting via ROAP
16
- * @param {Object} options
16
+ * @param {Object} localSdp
17
17
  * @returns {Promise} returns a promise that resolves/rejects whatever the request does
18
18
  */
19
-
20
- attachRechabilityData(localSdp) {
21
- const reachabilityData = window.localStorage.getItem(REACHABILITY.localStorage);
19
+ async attachRechabilityData(localSdp) {
20
+ // @ts-ignore
21
+ const reachabilityData = await this.webex.boundedStorage
22
+ .get(REACHABILITY.namespace, REACHABILITY.localStorage)
23
+ .catch(() => {});
22
24
 
23
25
  if (reachabilityData) {
24
26
  try {
@@ -48,6 +50,7 @@ export default class RoapRequest extends StatelessWebexPlugin {
48
50
  * @param {Boolean} options.audioMuted
49
51
  * @param {Boolean} options.videoMuted
50
52
  * @param {String} options.meetingId
53
+ * @param {Boolean} options.preferTranscoding
51
54
  * @returns {Promise} returns the response/failure of the request
52
55
  */
53
56
  sendRoap(options: {
@@ -76,77 +79,79 @@ export default class RoapRequest extends StatelessWebexPlugin {
76
79
 
77
80
  Metrics.postEvent({event: eventType.MEDIA_REQUEST, meetingId});
78
81
 
79
- // @ts-ignore
80
- return this.webex
81
- .request({
82
- uri: mediaUrl,
83
- method: HTTP_VERBS.PUT,
84
- body: {
85
- device: {
86
- url: deviceUrl,
87
- // @ts-ignore
88
- deviceType: this.config.meetings.deviceType,
89
- },
90
- correlationId,
91
- localMedias: [
92
- {
93
- localSdp: JSON.stringify(
94
- this.attachRechabilityData({
95
- roapMessage,
96
- // eslint-disable-next-line no-warning-comments
97
- // TODO: check whats the need for video and audiomute
98
- audioMuted: !!options.audioMuted,
99
- videoMuted: !!options.videoMuted,
100
- })
101
- ),
102
- mediaId: options.mediaId,
82
+ return this.attachRechabilityData({
83
+ roapMessage,
84
+ // eslint-disable-next-line no-warning-comments
85
+ // TODO: check whats the need for video and audiomute
86
+ audioMuted: !!options.audioMuted,
87
+ videoMuted: !!options.videoMuted,
88
+ }).then((sdpWithReachability) => {
89
+ // @ts-ignore
90
+ return this.webex
91
+ .request({
92
+ uri: mediaUrl,
93
+ method: HTTP_VERBS.PUT,
94
+ body: {
95
+ device: {
96
+ url: deviceUrl,
97
+ // @ts-ignore
98
+ deviceType: this.config.meetings.deviceType,
99
+ },
100
+ correlationId,
101
+ localMedias: [
102
+ {
103
+ localSdp: JSON.stringify(sdpWithReachability),
104
+ mediaId: options.mediaId,
105
+ },
106
+ ],
107
+ clientMediaPreferences: {
108
+ preferTranscoding: options.preferTranscoding ?? true,
103
109
  },
104
- ],
105
- clientMediaPreferences: {
106
- preferTranscoding: options.preferTranscoding ?? true,
107
110
  },
108
- },
109
- })
110
- .then((res) => {
111
- Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meetingId});
112
-
113
- // always it will be the first mediaConnection Object
114
- const mediaConnections =
115
- res.body.mediaConnections &&
116
- res.body.mediaConnections.length > 0 &&
117
- res.body.mediaConnections[0];
118
-
119
- LoggerProxy.logger.info(
120
- `Roap:request#sendRoap --> response:${JSON.stringify(
121
- mediaConnections,
122
- null,
123
- 2
124
- )}'\n StatusCode:'${res.statusCode}`
125
- );
126
- const {locus} = res.body;
127
-
128
- locus.roapSeq = options.roapMessage.seq;
129
-
130
- return {
131
- locus,
132
- ...(mediaConnections && {mediaConnections: res.body.mediaConnections}),
133
- };
134
- })
135
- .catch((err) => {
136
- Metrics.postEvent({
137
- event: eventType.MEDIA_RESPONSE,
138
- meetingId,
139
- data: {error: Metrics.parseLocusError(err, true)},
111
+ })
112
+ .then((res) => {
113
+ Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meetingId});
114
+
115
+ // always it will be the first mediaConnection Object
116
+ const mediaConnections =
117
+ res.body.mediaConnections &&
118
+ res.body.mediaConnections.length > 0 &&
119
+ res.body.mediaConnections[0];
120
+
121
+ LoggerProxy.logger.info(
122
+ `Roap:request#sendRoap --> response:${JSON.stringify(
123
+ mediaConnections,
124
+ null,
125
+ 2
126
+ )}'\n StatusCode:'${res.statusCode}`
127
+ );
128
+ const {locus} = res.body;
129
+
130
+ locus.roapSeq = options.roapMessage.seq;
131
+
132
+ return {
133
+ locus,
134
+ ...(mediaConnections && {mediaConnections: res.body.mediaConnections}),
135
+ };
136
+ })
137
+ .catch((err) => {
138
+ Metrics.postEvent({
139
+ event: eventType.MEDIA_RESPONSE,
140
+ meetingId,
141
+ data: {error: Metrics.parseLocusError(err, true)},
142
+ });
143
+ LoggerProxy.logger.error(
144
+ `Roap:request#sendRoap --> Error:${JSON.stringify(err, null, 2)}`
145
+ );
146
+ LoggerProxy.logger.error(
147
+ `Roap:request#sendRoapRequest --> errorBody:${JSON.stringify(
148
+ roapMessage,
149
+ null,
150
+ 2
151
+ )} + '\\n mediaId:'${options.mediaId}`
152
+ );
153
+ throw err;
140
154
  });
141
- LoggerProxy.logger.error(`Roap:request#sendRoap --> Error:${JSON.stringify(err, null, 2)}`);
142
- LoggerProxy.logger.error(
143
- `Roap:request#sendRoapRequest --> errorBody:${JSON.stringify(
144
- roapMessage,
145
- null,
146
- 2
147
- )} + '\\n mediaId:'${options.mediaId}`
148
- );
149
- throw err;
150
- });
155
+ });
151
156
  }
152
157
  }
@@ -184,6 +184,7 @@ export default class TurnDiscovery {
184
184
  audioMuted: meeting.isAudioMuted(),
185
185
  videoMuted: meeting.isVideoMuted(),
186
186
  meetingId: meeting.id,
187
+ preferTranscoding: !meeting.isMultistream,
187
188
  })
188
189
  .then(({mediaConnections}) => {
189
190
  if (mediaConnections) {
@@ -216,6 +217,7 @@ export default class TurnDiscovery {
216
217
  audioMuted: meeting.isAudioMuted(),
217
218
  videoMuted: meeting.isVideoMuted(),
218
219
  meetingId: meeting.id,
220
+ preferTranscoding: !meeting.isMultistream,
219
221
  });
220
222
  }
221
223
 
@@ -236,19 +238,19 @@ export default class TurnDiscovery {
236
238
  * media connection just after a reconnection
237
239
  * @returns {Promise}
238
240
  */
239
- doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {
241
+ async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {
240
242
  // @ts-ignore - fix type
241
- const isAnyClusterReachable = meeting.webex.meetings.reachability.isAnyClusterReachable();
243
+ const isAnyClusterReachable = await meeting.webex.meetings.reachability.isAnyClusterReachable();
242
244
 
243
245
  if (isAnyClusterReachable) {
244
246
  LoggerProxy.logger.info(
245
247
  'Roap:turnDiscovery#doTurnDiscovery --> reachability has not failed, skipping TURN discovery'
246
248
  );
247
249
 
248
- return Promise.resolve({
250
+ return {
249
251
  turnServerInfo: undefined,
250
252
  turnDiscoverySkippedReason: 'reachability',
251
- });
253
+ };
252
254
  }
253
255
 
254
256
  // @ts-ignore - fix type
@@ -257,7 +259,7 @@ export default class TurnDiscovery {
257
259
  'Roap:turnDiscovery#doTurnDiscovery --> TURN discovery disabled in config, skipping it'
258
260
  );
259
261
 
260
- return Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'});
262
+ return {turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'};
261
263
  }
262
264
 
263
265
  return this.sendRoapTurnDiscoveryRequest(meeting, isReconnecting)
@@ -283,7 +285,7 @@ export default class TurnDiscovery {
283
285
  stack: e.stack,
284
286
  });
285
287
 
286
- return Promise.resolve({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});
288
+ return {turnServerInfo: undefined, turnDiscoverySkippedReason: undefined};
287
289
  });
288
290
  }
289
291
  }
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable prefer-destructuring */
2
2
 
3
3
  import {cloneDeep} from 'lodash';
4
- import {MediaConnection as MC} from '@webex/internal-media-core';
4
+ import {ConnectionState} from '@webex/internal-media-core';
5
5
 
6
6
  import EventsScope from '../common/events/events-scope';
7
7
  import {
@@ -335,7 +335,7 @@ export class StatsAnalyzer extends EventsScope {
335
335
  *
336
336
  * @private
337
337
  * @memberof StatsAnalyzer
338
- * @param {MC.RoapMediaConnection} mediaConnection
338
+ * @param {RoapMediaConnection} mediaConnection
339
339
  * @returns {void}
340
340
  */
341
341
  updateMediaConnection(mediaConnection: any) {
@@ -347,7 +347,7 @@ export class StatsAnalyzer extends EventsScope {
347
347
  *
348
348
  * @public
349
349
  * @memberof StatsAnalyzer
350
- * @param {MC.RoapMediaConnection} mediaConnection
350
+ * @param {RoapMediaConnection} mediaConnection
351
351
  * @returns {Promise}
352
352
  */
353
353
  public startAnalyzer(mediaConnection: any) {
@@ -820,7 +820,7 @@ export class StatsAnalyzer extends EventsScope {
820
820
 
821
821
  if (
822
822
  this.mediaConnection &&
823
- this.mediaConnection.getConnectionState() === MC.ConnectionState.Failed
823
+ this.mediaConnection.getConnectionState() === ConnectionState.Failed
824
824
  ) {
825
825
  LoggerProxy.logger.trace(
826
826
  'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'
@@ -26,6 +26,7 @@ export const getAudioReceiverMqa = ({audioReceiver, statsResults, lastMqaDataSen
26
26
 
27
27
  // @ts-ignore
28
28
  audioReceiver.streams[0].common.maxRtpJitter =
29
+ // @ts-ignore
29
30
  max(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
30
31
  audioReceiver.streams[0].common.meanRtpJitter =
31
32
  mean(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
@@ -72,6 +73,7 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent})
72
73
 
73
74
  // @ts-ignore
74
75
  audioSender.common.maxRemoteJitter =
76
+ // @ts-ignore
75
77
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
76
78
  audioSender.common.meanRemoteJitter =
77
79
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -96,6 +98,7 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent})
96
98
 
97
99
  // @ts-ignore
98
100
  audioSender.common.maxRoundTripTime =
101
+ // @ts-ignore
99
102
  max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
100
103
  audioSender.common.meanRoundTripTime =
101
104
  mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
@@ -152,6 +155,7 @@ export const getVideoReceiverMqa = ({
152
155
 
153
156
  // @ts-ignore
154
157
  videoReceiver.common.maxRemoteJitter =
158
+ // @ts-ignore
155
159
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
156
160
  videoReceiver.common.meanRemoteJitter =
157
161
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -217,6 +221,7 @@ export const getVideoSenderMqa = ({
217
221
 
218
222
  // @ts-ignore
219
223
  videoSender.common.maxRemoteJitter =
224
+ // @ts-ignore
220
225
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
221
226
  videoSender.common.meanRemoteJitter =
222
227
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -239,6 +244,7 @@ export const getVideoSenderMqa = ({
239
244
 
240
245
  // @ts-ignore
241
246
  videoSender.common.maxRoundTripTime =
247
+ // @ts-ignore
242
248
  max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
243
249
  videoSender.common.meanRoundTripTime =
244
250
  mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;