@webex/plugin-meetings 3.0.0-beta.3 → 3.0.0-beta.300

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 (601) hide show
  1. package/README.md +46 -8
  2. package/UPGRADING.md +9 -9
  3. package/browsers.js +19 -24
  4. package/dist/annotation/annotation.types.js +7 -0
  5. package/dist/annotation/annotation.types.js.map +1 -0
  6. package/dist/annotation/constants.js +49 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.js +342 -0
  9. package/dist/annotation/index.js.map +1 -0
  10. package/dist/breakouts/breakout.js +216 -0
  11. package/dist/breakouts/breakout.js.map +1 -0
  12. package/dist/breakouts/collection.js +23 -0
  13. package/dist/breakouts/collection.js.map +1 -0
  14. package/dist/breakouts/edit-lock-error.js +52 -0
  15. package/dist/breakouts/edit-lock-error.js.map +1 -0
  16. package/dist/breakouts/events.js +45 -0
  17. package/dist/breakouts/events.js.map +1 -0
  18. package/dist/breakouts/index.js +1048 -0
  19. package/dist/breakouts/index.js.map +1 -0
  20. package/dist/breakouts/request.js +78 -0
  21. package/dist/breakouts/request.js.map +1 -0
  22. package/dist/breakouts/utils.js +67 -0
  23. package/dist/breakouts/utils.js.map +1 -0
  24. package/dist/common/browser-detection.js +1 -20
  25. package/dist/common/browser-detection.js.map +1 -1
  26. package/dist/common/collection.js +5 -20
  27. package/dist/common/collection.js.map +1 -1
  28. package/dist/common/config.js +0 -7
  29. package/dist/common/config.js.map +1 -1
  30. package/dist/common/errors/captcha-error.js +10 -24
  31. package/dist/common/errors/captcha-error.js.map +1 -1
  32. package/dist/common/errors/intent-to-join.js +11 -24
  33. package/dist/common/errors/intent-to-join.js.map +1 -1
  34. package/dist/common/errors/join-meeting.js +12 -25
  35. package/dist/common/errors/join-meeting.js.map +1 -1
  36. package/dist/common/errors/media.js +10 -24
  37. package/dist/common/errors/media.js.map +1 -1
  38. package/dist/common/errors/no-meeting-info.js +51 -0
  39. package/dist/common/errors/no-meeting-info.js.map +1 -0
  40. package/dist/common/errors/parameter.js +5 -33
  41. package/dist/common/errors/parameter.js.map +1 -1
  42. package/dist/common/errors/password-error.js +10 -24
  43. package/dist/common/errors/password-error.js.map +1 -1
  44. package/dist/common/errors/permission.js +9 -23
  45. package/dist/common/errors/permission.js.map +1 -1
  46. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  47. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  48. package/dist/common/errors/reconnection-in-progress.js +0 -17
  49. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  50. package/dist/common/errors/reconnection.js +10 -24
  51. package/dist/common/errors/reconnection.js.map +1 -1
  52. package/dist/common/errors/stats.js +10 -24
  53. package/dist/common/errors/stats.js.map +1 -1
  54. package/dist/common/errors/webex-errors.js +54 -48
  55. package/dist/common/errors/webex-errors.js.map +1 -1
  56. package/dist/common/errors/webex-meetings-error.js +5 -25
  57. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  58. package/dist/common/events/events-scope.js +0 -22
  59. package/dist/common/events/events-scope.js.map +1 -1
  60. package/dist/common/events/events.js +0 -23
  61. package/dist/common/events/events.js.map +1 -1
  62. package/dist/common/events/trigger-proxy.js +0 -12
  63. package/dist/common/events/trigger-proxy.js.map +1 -1
  64. package/dist/common/events/util.js +0 -15
  65. package/dist/common/events/util.js.map +1 -1
  66. package/dist/common/logs/logger-config.js +0 -4
  67. package/dist/common/logs/logger-config.js.map +1 -1
  68. package/dist/common/logs/logger-proxy.js +1 -8
  69. package/dist/common/logs/logger-proxy.js.map +1 -1
  70. package/dist/common/logs/request.js +41 -60
  71. package/dist/common/logs/request.js.map +1 -1
  72. package/dist/common/queue.js +28 -23
  73. package/dist/common/queue.js.map +1 -1
  74. package/dist/config.js +9 -15
  75. package/dist/config.js.map +1 -1
  76. package/dist/constants.js +315 -68
  77. package/dist/constants.js.map +1 -1
  78. package/dist/controls-options-manager/constants.js +14 -0
  79. package/dist/controls-options-manager/constants.js.map +1 -0
  80. package/dist/controls-options-manager/enums.js +27 -0
  81. package/dist/controls-options-manager/enums.js.map +1 -0
  82. package/dist/controls-options-manager/index.js +297 -0
  83. package/dist/controls-options-manager/index.js.map +1 -0
  84. package/dist/controls-options-manager/types.js +7 -0
  85. package/dist/controls-options-manager/types.js.map +1 -0
  86. package/dist/controls-options-manager/util.js +319 -0
  87. package/dist/controls-options-manager/util.js.map +1 -0
  88. package/dist/index.js +114 -17
  89. package/dist/index.js.map +1 -1
  90. package/dist/interpretation/collection.js +23 -0
  91. package/dist/interpretation/collection.js.map +1 -0
  92. package/dist/interpretation/index.js +366 -0
  93. package/dist/interpretation/index.js.map +1 -0
  94. package/dist/interpretation/siLanguage.js +25 -0
  95. package/dist/interpretation/siLanguage.js.map +1 -0
  96. package/dist/locus-info/controlsUtils.js +101 -29
  97. package/dist/locus-info/controlsUtils.js.map +1 -1
  98. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  99. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  100. package/dist/locus-info/fullState.js +0 -15
  101. package/dist/locus-info/fullState.js.map +1 -1
  102. package/dist/locus-info/hostUtils.js +4 -12
  103. package/dist/locus-info/hostUtils.js.map +1 -1
  104. package/dist/locus-info/index.js +561 -246
  105. package/dist/locus-info/index.js.map +1 -1
  106. package/dist/locus-info/infoUtils.js +10 -38
  107. package/dist/locus-info/infoUtils.js.map +1 -1
  108. package/dist/locus-info/mediaSharesUtils.js +68 -38
  109. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  110. package/dist/locus-info/parser.js +314 -163
  111. package/dist/locus-info/parser.js.map +1 -1
  112. package/dist/locus-info/selfUtils.js +110 -92
  113. package/dist/locus-info/selfUtils.js.map +1 -1
  114. package/dist/media/index.js +103 -231
  115. package/dist/media/index.js.map +1 -1
  116. package/dist/media/properties.js +137 -222
  117. package/dist/media/properties.js.map +1 -1
  118. package/dist/media/util.js +2 -9
  119. package/dist/media/util.js.map +1 -1
  120. package/dist/mediaQualityMetrics/config.js +505 -495
  121. package/dist/mediaQualityMetrics/config.js.map +1 -1
  122. package/dist/meeting/in-meeting-actions.js +93 -14
  123. package/dist/meeting/in-meeting-actions.js.map +1 -1
  124. package/dist/meeting/index.js +4624 -3740
  125. package/dist/meeting/index.js.map +1 -1
  126. package/dist/meeting/locusMediaRequest.js +292 -0
  127. package/dist/meeting/locusMediaRequest.js.map +1 -0
  128. package/dist/meeting/muteState.js +249 -184
  129. package/dist/meeting/muteState.js.map +1 -1
  130. package/dist/meeting/request.js +400 -346
  131. package/dist/meeting/request.js.map +1 -1
  132. package/dist/meeting/request.type.js +7 -0
  133. package/dist/meeting/request.type.js.map +1 -0
  134. package/dist/meeting/state.js +21 -31
  135. package/dist/meeting/state.js.map +1 -1
  136. package/dist/meeting/util.js +598 -586
  137. package/dist/meeting/util.js.map +1 -1
  138. package/dist/meeting-info/collection.js +6 -25
  139. package/dist/meeting-info/collection.js.map +1 -1
  140. package/dist/meeting-info/index.js +87 -39
  141. package/dist/meeting-info/index.js.map +1 -1
  142. package/dist/meeting-info/meeting-info-v2.js +349 -283
  143. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  144. package/dist/meeting-info/request.js +3 -15
  145. package/dist/meeting-info/request.js.map +1 -1
  146. package/dist/meeting-info/util.js +98 -183
  147. package/dist/meeting-info/util.js.map +1 -1
  148. package/dist/meeting-info/utilv2.js +143 -234
  149. package/dist/meeting-info/utilv2.js.map +1 -1
  150. package/dist/meetings/collection.js +26 -19
  151. package/dist/meetings/collection.js.map +1 -1
  152. package/dist/meetings/index.js +813 -596
  153. package/dist/meetings/index.js.map +1 -1
  154. package/dist/meetings/meetings.types.js +7 -0
  155. package/dist/meetings/meetings.types.js.map +1 -0
  156. package/dist/meetings/request.js +26 -41
  157. package/dist/meetings/request.js.map +1 -1
  158. package/dist/meetings/util.js +183 -156
  159. package/dist/meetings/util.js.map +1 -1
  160. package/dist/member/index.js +135 -85
  161. package/dist/member/index.js.map +1 -1
  162. package/dist/member/types.js +25 -0
  163. package/dist/member/types.js.map +1 -0
  164. package/dist/member/util.js +158 -88
  165. package/dist/member/util.js.map +1 -1
  166. package/dist/members/collection.js +13 -12
  167. package/dist/members/collection.js.map +1 -1
  168. package/dist/members/index.js +194 -204
  169. package/dist/members/index.js.map +1 -1
  170. package/dist/members/request.js +113 -68
  171. package/dist/members/request.js.map +1 -1
  172. package/dist/members/types.js +15 -0
  173. package/dist/members/types.js.map +1 -0
  174. package/dist/members/util.js +324 -259
  175. package/dist/members/util.js.map +1 -1
  176. package/dist/metrics/constants.js +14 -7
  177. package/dist/metrics/constants.js.map +1 -1
  178. package/dist/metrics/index.js +11 -558
  179. package/dist/metrics/index.js.map +1 -1
  180. package/dist/multistream/mediaRequestManager.js +263 -50
  181. package/dist/multistream/mediaRequestManager.js.map +1 -1
  182. package/dist/multistream/receiveSlot.js +58 -65
  183. package/dist/multistream/receiveSlot.js.map +1 -1
  184. package/dist/multistream/receiveSlotManager.js +76 -95
  185. package/dist/multistream/receiveSlotManager.js.map +1 -1
  186. package/dist/multistream/remoteMedia.js +62 -76
  187. package/dist/multistream/remoteMedia.js.map +1 -1
  188. package/dist/multistream/remoteMediaGroup.js +66 -43
  189. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  190. package/dist/multistream/remoteMediaManager.js +536 -439
  191. package/dist/multistream/remoteMediaManager.js.map +1 -1
  192. package/dist/multistream/sendSlotManager.js +233 -0
  193. package/dist/multistream/sendSlotManager.js.map +1 -0
  194. package/dist/networkQualityMonitor/index.js +40 -59
  195. package/dist/networkQualityMonitor/index.js.map +1 -1
  196. package/dist/personal-meeting-room/index.js +21 -45
  197. package/dist/personal-meeting-room/index.js.map +1 -1
  198. package/dist/personal-meeting-room/request.js +1 -31
  199. package/dist/personal-meeting-room/request.js.map +1 -1
  200. package/dist/personal-meeting-room/util.js +0 -13
  201. package/dist/personal-meeting-room/util.js.map +1 -1
  202. package/dist/reachability/index.js +322 -200
  203. package/dist/reachability/index.js.map +1 -1
  204. package/dist/reachability/request.js +20 -26
  205. package/dist/reachability/request.js.map +1 -1
  206. package/dist/reactions/constants.js +13 -0
  207. package/dist/reactions/constants.js.map +1 -0
  208. package/dist/reactions/reactions.js +109 -0
  209. package/dist/reactions/reactions.js.map +1 -0
  210. package/dist/reactions/reactions.type.js +36 -0
  211. package/dist/reactions/reactions.type.js.map +1 -0
  212. package/dist/reconnection-manager/index.js +388 -476
  213. package/dist/reconnection-manager/index.js.map +1 -1
  214. package/dist/recording-controller/enums.js +17 -0
  215. package/dist/recording-controller/enums.js.map +1 -0
  216. package/dist/recording-controller/index.js +362 -0
  217. package/dist/recording-controller/index.js.map +1 -0
  218. package/dist/recording-controller/util.js +64 -0
  219. package/dist/recording-controller/util.js.map +1 -0
  220. package/dist/roap/index.js +99 -94
  221. package/dist/roap/index.js.map +1 -1
  222. package/dist/roap/request.js +131 -135
  223. package/dist/roap/request.js.map +1 -1
  224. package/dist/roap/turnDiscovery.js +151 -101
  225. package/dist/roap/turnDiscovery.js.map +1 -1
  226. package/dist/rtcMetrics/constants.js +12 -0
  227. package/dist/rtcMetrics/constants.js.map +1 -0
  228. package/dist/rtcMetrics/index.js +117 -0
  229. package/dist/rtcMetrics/index.js.map +1 -0
  230. package/dist/statsAnalyzer/global.js +1 -95
  231. package/dist/statsAnalyzer/global.js.map +1 -1
  232. package/dist/statsAnalyzer/index.js +416 -497
  233. package/dist/statsAnalyzer/index.js.map +1 -1
  234. package/dist/statsAnalyzer/mqaUtil.js +145 -88
  235. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  236. package/dist/transcription/index.js +22 -47
  237. package/dist/transcription/index.js.map +1 -1
  238. package/dist/types/annotation/annotation.types.d.ts +42 -0
  239. package/dist/types/annotation/constants.d.ts +31 -0
  240. package/dist/types/annotation/index.d.ts +117 -0
  241. package/dist/types/breakouts/breakout.d.ts +8 -0
  242. package/dist/types/breakouts/collection.d.ts +5 -0
  243. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  244. package/dist/types/breakouts/events.d.ts +8 -0
  245. package/dist/types/breakouts/index.d.ts +5 -0
  246. package/dist/types/breakouts/request.d.ts +22 -0
  247. package/dist/types/breakouts/utils.d.ts +15 -0
  248. package/dist/types/common/browser-detection.d.ts +9 -0
  249. package/dist/types/common/collection.d.ts +48 -0
  250. package/dist/types/common/config.d.ts +2 -0
  251. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  252. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  253. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  254. package/dist/types/common/errors/media.d.ts +15 -0
  255. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  256. package/dist/types/common/errors/parameter.d.ts +15 -0
  257. package/dist/types/common/errors/password-error.d.ts +15 -0
  258. package/dist/types/common/errors/permission.d.ts +14 -0
  259. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  260. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  261. package/dist/types/common/errors/reconnection.d.ts +15 -0
  262. package/dist/types/common/errors/stats.d.ts +15 -0
  263. package/dist/types/common/errors/webex-errors.d.ts +93 -0
  264. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  265. package/dist/types/common/events/events-scope.d.ts +17 -0
  266. package/dist/types/common/events/events.d.ts +12 -0
  267. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  268. package/dist/types/common/events/util.d.ts +2 -0
  269. package/dist/types/common/logs/logger-config.d.ts +2 -0
  270. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  271. package/dist/types/common/logs/request.d.ts +36 -0
  272. package/dist/types/common/queue.d.ts +34 -0
  273. package/dist/types/config.d.ts +71 -0
  274. package/dist/types/constants.d.ts +1066 -0
  275. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  276. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  277. package/dist/types/controls-options-manager/index.d.ts +136 -0
  278. package/dist/types/controls-options-manager/types.d.ts +43 -0
  279. package/dist/types/controls-options-manager/util.d.ts +1 -0
  280. package/dist/types/index.d.ts +7 -0
  281. package/dist/types/interpretation/collection.d.ts +5 -0
  282. package/dist/types/interpretation/index.d.ts +5 -0
  283. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  284. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  285. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  286. package/dist/types/locus-info/fullState.d.ts +2 -0
  287. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  288. package/dist/types/locus-info/index.d.ts +322 -0
  289. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  290. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  291. package/dist/types/locus-info/parser.d.ts +273 -0
  292. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  293. package/dist/types/media/index.d.ts +34 -0
  294. package/dist/types/media/properties.d.ts +93 -0
  295. package/dist/types/media/util.d.ts +2 -0
  296. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  297. package/dist/types/meeting/in-meeting-actions.d.ts +163 -0
  298. package/dist/types/meeting/index.d.ts +1676 -0
  299. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  300. package/dist/types/meeting/muteState.d.ts +184 -0
  301. package/dist/types/meeting/request.d.ts +290 -0
  302. package/dist/types/meeting/request.type.d.ts +11 -0
  303. package/dist/types/meeting/state.d.ts +9 -0
  304. package/dist/types/meeting/util.d.ts +102 -0
  305. package/dist/types/meeting-info/collection.d.ts +20 -0
  306. package/dist/types/meeting-info/index.d.ts +69 -0
  307. package/dist/types/meeting-info/meeting-info-v2.d.ts +123 -0
  308. package/dist/types/meeting-info/request.d.ts +22 -0
  309. package/dist/types/meeting-info/util.d.ts +2 -0
  310. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  311. package/dist/types/meetings/collection.d.ts +31 -0
  312. package/dist/types/meetings/index.d.ts +367 -0
  313. package/dist/types/meetings/meetings.types.d.ts +4 -0
  314. package/dist/types/meetings/request.d.ts +27 -0
  315. package/dist/types/meetings/util.d.ts +18 -0
  316. package/dist/types/member/index.d.ts +160 -0
  317. package/dist/types/member/types.d.ts +32 -0
  318. package/dist/types/member/util.d.ts +2 -0
  319. package/dist/types/members/collection.d.ts +29 -0
  320. package/dist/types/members/index.d.ts +353 -0
  321. package/dist/types/members/request.d.ts +114 -0
  322. package/dist/types/members/types.d.ts +25 -0
  323. package/dist/types/members/util.d.ts +215 -0
  324. package/dist/types/metrics/constants.d.ts +65 -0
  325. package/dist/types/metrics/index.d.ts +45 -0
  326. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  327. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  328. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  329. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  330. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  331. package/dist/types/multistream/remoteMediaManager.d.ts +285 -0
  332. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  333. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  334. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  335. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  336. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  337. package/dist/types/reachability/index.d.ts +194 -0
  338. package/dist/types/reachability/request.d.ts +39 -0
  339. package/dist/types/reactions/constants.d.ts +3 -0
  340. package/dist/types/reactions/reactions.d.ts +4 -0
  341. package/dist/types/reactions/reactions.type.d.ts +52 -0
  342. package/dist/types/reconnection-manager/index.d.ts +126 -0
  343. package/dist/types/recording-controller/enums.d.ts +7 -0
  344. package/dist/types/recording-controller/index.d.ts +207 -0
  345. package/dist/types/recording-controller/util.d.ts +14 -0
  346. package/dist/types/roap/index.d.ts +78 -0
  347. package/dist/types/roap/request.d.ts +39 -0
  348. package/dist/types/roap/turnDiscovery.d.ts +92 -0
  349. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  350. package/dist/types/rtcMetrics/index.d.ts +47 -0
  351. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  352. package/dist/types/statsAnalyzer/index.d.ts +201 -0
  353. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  354. package/dist/types/transcription/index.d.ts +64 -0
  355. package/dist/types/webinar/collection.d.ts +16 -0
  356. package/dist/types/webinar/index.d.ts +5 -0
  357. package/dist/webinar/collection.js +44 -0
  358. package/dist/webinar/collection.js.map +1 -0
  359. package/dist/webinar/index.js +69 -0
  360. package/dist/webinar/index.js.map +1 -0
  361. package/internal-README.md +7 -6
  362. package/package.json +29 -21
  363. package/src/annotation/annotation.types.ts +50 -0
  364. package/src/annotation/constants.ts +36 -0
  365. package/src/annotation/index.ts +328 -0
  366. package/src/breakouts/README.md +220 -0
  367. package/src/breakouts/breakout.ts +188 -0
  368. package/src/breakouts/collection.ts +19 -0
  369. package/src/breakouts/edit-lock-error.ts +25 -0
  370. package/src/breakouts/events.ts +56 -0
  371. package/src/breakouts/index.ts +925 -0
  372. package/src/breakouts/request.ts +55 -0
  373. package/src/breakouts/utils.ts +57 -0
  374. package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
  375. package/src/common/collection.ts +9 -7
  376. package/src/common/{config.js → config.ts} +1 -1
  377. package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
  378. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
  379. package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
  380. package/src/common/errors/{media.js → media.ts} +11 -7
  381. package/src/common/errors/no-meeting-info.ts +24 -0
  382. package/src/common/errors/parameter.ts +11 -7
  383. package/src/common/errors/{password-error.js → password-error.ts} +11 -7
  384. package/src/common/errors/{permission.js → permission.ts} +10 -6
  385. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  386. package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
  387. package/src/common/errors/{stats.js → stats.ts} +11 -7
  388. package/src/common/errors/{webex-errors.js → webex-errors.ts} +51 -8
  389. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
  390. package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
  391. package/src/common/events/{events.js → events.ts} +5 -1
  392. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
  393. package/src/common/events/{util.js → util.ts} +2 -3
  394. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  395. package/src/common/logs/logger-proxy.ts +44 -0
  396. package/src/common/logs/{request.js → request.ts} +26 -9
  397. package/src/common/queue.ts +22 -9
  398. package/src/{config.js → config.ts} +18 -19
  399. package/src/constants.ts +260 -22
  400. package/src/controls-options-manager/constants.ts +5 -0
  401. package/src/controls-options-manager/enums.ts +18 -0
  402. package/src/controls-options-manager/index.ts +278 -0
  403. package/src/controls-options-manager/types.ts +59 -0
  404. package/src/controls-options-manager/util.ts +300 -0
  405. package/src/index.ts +40 -0
  406. package/src/interpretation/README.md +60 -0
  407. package/src/interpretation/collection.ts +19 -0
  408. package/src/interpretation/index.ts +332 -0
  409. package/src/interpretation/siLanguage.ts +18 -0
  410. package/src/locus-info/controlsUtils.ts +222 -0
  411. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  412. package/src/locus-info/{fullState.js → fullState.ts} +16 -12
  413. package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
  414. package/src/locus-info/{index.js → index.ts} +557 -119
  415. package/src/locus-info/{infoUtils.js → infoUtils.ts} +29 -10
  416. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +81 -17
  417. package/src/locus-info/{parser.js → parser.ts} +303 -104
  418. package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
  419. package/src/media/index.ts +458 -0
  420. package/src/media/properties.ts +283 -0
  421. package/src/media/{util.js → util.ts} +2 -2
  422. package/src/mediaQualityMetrics/config.ts +384 -0
  423. package/src/meeting/in-meeting-actions.ts +191 -3
  424. package/src/meeting/index.ts +7882 -0
  425. package/src/meeting/locusMediaRequest.ts +313 -0
  426. package/src/meeting/muteState.ts +451 -0
  427. package/src/meeting/{request.js → request.ts} +421 -220
  428. package/src/meeting/request.type.ts +13 -0
  429. package/src/meeting/{state.js → state.ts} +50 -35
  430. package/src/meeting/util.ts +697 -0
  431. package/src/meeting-info/{collection.js → collection.ts} +6 -2
  432. package/src/meeting-info/index.ts +210 -0
  433. package/src/meeting-info/meeting-info-v2.ts +429 -0
  434. package/src/meeting-info/{request.js → request.ts} +14 -4
  435. package/src/meeting-info/{util.js → util.ts} +60 -51
  436. package/src/meeting-info/{utilv2.js → utilv2.ts} +78 -71
  437. package/src/meetings/{collection.js → collection.ts} +26 -3
  438. package/src/meetings/index.ts +1470 -0
  439. package/src/meetings/meetings.types.ts +12 -0
  440. package/src/meetings/{request.js → request.ts} +34 -25
  441. package/src/meetings/{util.js → util.ts} +132 -37
  442. package/src/member/{index.js → index.ts} +160 -56
  443. package/src/member/types.ts +38 -0
  444. package/src/member/util.ts +397 -0
  445. package/src/members/{collection.js → collection.ts} +10 -2
  446. package/src/members/{index.js → index.ts} +351 -146
  447. package/src/members/request.ts +255 -0
  448. package/src/members/types.ts +29 -0
  449. package/src/members/util.ts +353 -0
  450. package/src/metrics/{constants.js → constants.ts} +12 -6
  451. package/src/metrics/index.ts +73 -0
  452. package/src/multistream/mediaRequestManager.ts +337 -63
  453. package/src/multistream/receiveSlot.ts +69 -26
  454. package/src/multistream/receiveSlotManager.ts +66 -42
  455. package/src/multistream/remoteMedia.ts +40 -5
  456. package/src/multistream/remoteMediaGroup.ts +63 -3
  457. package/src/multistream/remoteMediaManager.ts +300 -66
  458. package/src/multistream/sendSlotManager.ts +170 -0
  459. package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
  460. package/src/personal-meeting-room/{index.js → index.ts} +28 -19
  461. package/src/personal-meeting-room/{request.js → request.ts} +13 -4
  462. package/src/personal-meeting-room/{util.js → util.ts} +4 -4
  463. package/src/reachability/index.ts +671 -0
  464. package/src/reachability/request.ts +50 -35
  465. package/src/reactions/constants.ts +4 -0
  466. package/src/reactions/reactions.ts +104 -0
  467. package/src/reactions/reactions.type.ts +62 -0
  468. package/src/reconnection-manager/{index.js → index.ts} +258 -138
  469. package/src/recording-controller/enums.ts +8 -0
  470. package/src/recording-controller/index.ts +332 -0
  471. package/src/recording-controller/util.ts +75 -0
  472. package/src/roap/{index.js → index.ts} +127 -79
  473. package/src/roap/request.ts +153 -0
  474. package/src/roap/turnDiscovery.ts +109 -47
  475. package/src/rtcMetrics/constants.ts +3 -0
  476. package/src/rtcMetrics/index.ts +100 -0
  477. package/src/statsAnalyzer/global.ts +37 -0
  478. package/src/statsAnalyzer/index.ts +1250 -0
  479. package/src/statsAnalyzer/mqaUtil.ts +292 -0
  480. package/src/transcription/{index.js → index.ts} +46 -39
  481. package/src/webinar/collection.ts +31 -0
  482. package/src/webinar/index.ts +62 -0
  483. package/test/integration/spec/converged-space-meetings.js +233 -0
  484. package/test/integration/spec/journey.js +790 -530
  485. package/test/integration/spec/space-meeting.js +391 -204
  486. package/test/integration/spec/transcription.js +7 -8
  487. package/test/unit/spec/annotation/index.ts +418 -0
  488. package/test/unit/spec/breakouts/breakout.ts +237 -0
  489. package/test/unit/spec/breakouts/collection.ts +15 -0
  490. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  491. package/test/unit/spec/breakouts/events.ts +89 -0
  492. package/test/unit/spec/breakouts/index.ts +1790 -0
  493. package/test/unit/spec/breakouts/request.ts +104 -0
  494. package/test/unit/spec/breakouts/utils.js +72 -0
  495. package/test/unit/spec/common/browser-detection.js +9 -28
  496. package/test/unit/spec/common/queue.js +31 -2
  497. package/test/unit/spec/controls-options-manager/index.js +287 -0
  498. package/test/unit/spec/controls-options-manager/util.js +582 -0
  499. package/test/unit/spec/fixture/locus.js +93 -90
  500. package/test/unit/spec/interpretation/collection.ts +15 -0
  501. package/test/unit/spec/interpretation/index.ts +589 -0
  502. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  503. package/test/unit/spec/locus-info/controlsUtils.js +325 -32
  504. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  505. package/test/unit/spec/locus-info/index.js +1390 -17
  506. package/test/unit/spec/locus-info/infoUtils.js +71 -40
  507. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  508. package/test/unit/spec/locus-info/lib/SeqCmp.json +529 -685
  509. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  510. package/test/unit/spec/locus-info/parser.js +119 -44
  511. package/test/unit/spec/locus-info/selfConstant.js +120 -103
  512. package/test/unit/spec/locus-info/selfUtils.js +296 -12
  513. package/test/unit/spec/media/index.ts +128 -77
  514. package/test/unit/spec/media/properties.ts +11 -11
  515. package/test/unit/spec/meeting/in-meeting-actions.ts +92 -3
  516. package/test/unit/spec/meeting/index.js +7433 -2752
  517. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  518. package/test/unit/spec/meeting/muteState.js +420 -211
  519. package/test/unit/spec/meeting/request.js +545 -79
  520. package/test/unit/spec/meeting/utils.js +722 -174
  521. package/test/unit/spec/meeting-info/index.js +300 -0
  522. package/test/unit/spec/meeting-info/meetinginfov2.js +624 -76
  523. package/test/unit/spec/meeting-info/request.js +7 -9
  524. package/test/unit/spec/meeting-info/util.js +11 -12
  525. package/test/unit/spec/meeting-info/utilv2.js +131 -74
  526. package/test/unit/spec/meetings/collection.js +15 -1
  527. package/test/unit/spec/meetings/index.js +1365 -377
  528. package/test/unit/spec/meetings/utils.js +216 -14
  529. package/test/unit/spec/member/index.js +61 -7
  530. package/test/unit/spec/member/util.js +526 -26
  531. package/test/unit/spec/members/index.js +536 -55
  532. package/test/unit/spec/members/request.js +228 -40
  533. package/test/unit/spec/members/utils.js +217 -4
  534. package/test/unit/spec/metrics/index.js +12 -66
  535. package/test/unit/spec/multistream/mediaRequestManager.ts +1012 -109
  536. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  537. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  538. package/test/unit/spec/multistream/remoteMedia.ts +40 -2
  539. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  540. package/test/unit/spec/multistream/remoteMediaManager.ts +738 -65
  541. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  542. package/test/unit/spec/networkQualityMonitor/index.js +24 -18
  543. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  544. package/test/unit/spec/reachability/index.ts +598 -26
  545. package/test/unit/spec/reachability/request.js +68 -0
  546. package/test/unit/spec/reconnection-manager/index.js +181 -12
  547. package/test/unit/spec/recording-controller/index.js +307 -0
  548. package/test/unit/spec/recording-controller/util.js +229 -0
  549. package/test/unit/spec/roap/index.ts +179 -64
  550. package/test/unit/spec/roap/request.ts +232 -0
  551. package/test/unit/spec/roap/turnDiscovery.ts +123 -58
  552. package/test/unit/spec/rtcMetrics/index.ts +73 -0
  553. package/test/unit/spec/stats-analyzer/index.js +199 -60
  554. package/test/unit/spec/webinar/collection.ts +13 -0
  555. package/test/unit/spec/webinar/index.ts +60 -0
  556. package/test/utils/cmr.js +44 -42
  557. package/test/utils/constants.js +9 -0
  558. package/test/utils/integrationTestUtils.js +46 -0
  559. package/test/utils/testUtils.js +63 -99
  560. package/test/utils/webex-config.js +22 -18
  561. package/test/utils/webex-test-users.js +57 -50
  562. package/tsconfig.json +6 -0
  563. package/dist/media/internal-media-core-wrapper.js +0 -22
  564. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  565. package/dist/meeting/effectsState.js +0 -327
  566. package/dist/meeting/effectsState.js.map +0 -1
  567. package/dist/metrics/config.js +0 -301
  568. package/dist/metrics/config.js.map +0 -1
  569. package/dist/multistream/multistreamMedia.js +0 -116
  570. package/dist/multistream/multistreamMedia.js.map +0 -1
  571. package/dist/peer-connection-manager/util.js +0 -124
  572. package/dist/peer-connection-manager/util.js.map +0 -1
  573. package/src/common/logs/logger-proxy.js +0 -33
  574. package/src/index.js +0 -15
  575. package/src/locus-info/controlsUtils.js +0 -102
  576. package/src/media/index.js +0 -459
  577. package/src/media/internal-media-core-wrapper.ts +0 -9
  578. package/src/media/properties.js +0 -289
  579. package/src/mediaQualityMetrics/config.js +0 -382
  580. package/src/meeting/effectsState.js +0 -205
  581. package/src/meeting/index.js +0 -6284
  582. package/src/meeting/muteState.js +0 -318
  583. package/src/meeting/util.js +0 -506
  584. package/src/meeting-info/index.js +0 -131
  585. package/src/meeting-info/meeting-info-v2.js +0 -255
  586. package/src/meetings/index.js +0 -1015
  587. package/src/member/util.js +0 -254
  588. package/src/members/request.js +0 -131
  589. package/src/members/util.js +0 -258
  590. package/src/metrics/config.js +0 -324
  591. package/src/metrics/index.js +0 -530
  592. package/src/multistream/multistreamMedia.ts +0 -92
  593. package/src/peer-connection-manager/util.ts +0 -117
  594. package/src/reachability/index.js +0 -464
  595. package/src/roap/request.js +0 -127
  596. package/src/statsAnalyzer/global.js +0 -133
  597. package/src/statsAnalyzer/index.js +0 -1006
  598. package/src/statsAnalyzer/mqaUtil.js +0 -173
  599. package/test/unit/spec/meeting/effectsState.js +0 -291
  600. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
  601. /package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
@@ -0,0 +1,1250 @@
1
+ /* eslint-disable prefer-destructuring */
2
+
3
+ import {cloneDeep} from 'lodash';
4
+ import {ConnectionState} from '@webex/internal-media-core';
5
+
6
+ import EventsScope from '../common/events/events-scope';
7
+ import {
8
+ DEFAULT_GET_STATS_FILTER,
9
+ STATS,
10
+ MQA_INTEVAL,
11
+ NETWORK_TYPE,
12
+ MEDIA_DEVICES,
13
+ _UNKNOWN_,
14
+ } from '../constants';
15
+ import {
16
+ emptyAudioReceive,
17
+ emptyAudioTransmit,
18
+ emptyMqaInterval,
19
+ emptyVideoReceive,
20
+ emptyVideoTransmit,
21
+ } from '../mediaQualityMetrics/config';
22
+ import LoggerProxy from '../common/logs/logger-proxy';
23
+
24
+ import defaultStats from './global';
25
+ import {
26
+ getAudioSenderMqa,
27
+ getAudioReceiverMqa,
28
+ getVideoSenderMqa,
29
+ getVideoReceiverMqa,
30
+ } from './mqaUtil';
31
+ import {ReceiveSlot} from '../multistream/receiveSlot';
32
+
33
+ export const EVENTS = {
34
+ MEDIA_QUALITY: 'MEDIA_QUALITY',
35
+ LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',
36
+ LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',
37
+ REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',
38
+ REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',
39
+ };
40
+
41
+ const emptySender = {
42
+ trackLabel: '',
43
+ maxPacketLossRatio: 0,
44
+ availableBandwidth: 0,
45
+ bytesSent: 0,
46
+ meanRemoteJitter: [],
47
+ meanRoundTripTime: [],
48
+ };
49
+
50
+ const emptyReceiver = {
51
+ availableBandwidth: 0,
52
+ bytesReceived: 0,
53
+ meanRtpJitter: [],
54
+ meanRoundTripTime: [],
55
+ };
56
+
57
+ type ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;
58
+
59
+ /**
60
+ * Stats Analyzer class that will emit events based on detected quality
61
+ *
62
+ * @export
63
+ * @class StatsAnalyzer
64
+ * @extends {EventsScope}
65
+ */
66
+ export class StatsAnalyzer extends EventsScope {
67
+ config: any;
68
+ correlationId: any;
69
+ lastEmittedStartStopEvent: any;
70
+ lastMqaDataSent: any;
71
+ lastStatsResults: any;
72
+ meetingMediaStatus: any;
73
+ mqaInterval: NodeJS.Timeout;
74
+ mqaSentCount: any;
75
+ networkQualityMonitor: any;
76
+ mediaConnection: any;
77
+ statsInterval: NodeJS.Timeout;
78
+ statsResults: any;
79
+ statsStarted: any;
80
+ successfulCandidatePair: any;
81
+ receiveSlotCallback: ReceiveSlotCallback;
82
+
83
+ /**
84
+ * Creates a new instance of StatsAnalyzer
85
+ * @constructor
86
+ * @public
87
+ * @param {Object} config SDK Configuration Object
88
+ * @param {Function} receiveSlotCallback Callback used to access receive slots.
89
+ * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
90
+ * @param {Object} statsResults Default properties for stats
91
+ */
92
+ constructor(
93
+ config: any,
94
+ receiveSlotCallback: ReceiveSlotCallback = () => undefined,
95
+ networkQualityMonitor: object = {},
96
+ statsResults: object = defaultStats
97
+ ) {
98
+ super();
99
+ this.statsStarted = false;
100
+ this.statsResults = statsResults;
101
+ this.lastStatsResults = null;
102
+ this.config = config;
103
+ this.networkQualityMonitor = networkQualityMonitor;
104
+ this.correlationId = config.correlationId;
105
+ this.mqaSentCount = -1;
106
+ this.lastMqaDataSent = {};
107
+ this.lastEmittedStartStopEvent = {};
108
+ this.receiveSlotCallback = receiveSlotCallback;
109
+ this.successfulCandidatePair = {};
110
+ }
111
+
112
+ /**
113
+ * Resets cumulative stats arrays.
114
+ *
115
+ * @public
116
+ * @memberof StatsAnalyzer
117
+ * @returns {void}
118
+ */
119
+ resetStatsResults() {
120
+ Object.keys(this.statsResults).forEach((mediaType) => {
121
+ if (mediaType.includes('recv')) {
122
+ this.statsResults[mediaType].recv.meanRtpJitter = [];
123
+ }
124
+
125
+ if (mediaType.includes('send')) {
126
+ this.statsResults[mediaType].send.meanRemoteJitter = [];
127
+ this.statsResults[mediaType].send.meanRoundTripTime = [];
128
+ }
129
+ });
130
+ }
131
+
132
+ /**
133
+ * sets mediaStatus status for analyzing metrics
134
+ *
135
+ * @public
136
+ * @param {Object} status for the audio and video
137
+ * @memberof StatsAnalyzer
138
+ * @returns {void}
139
+ */
140
+ public updateMediaStatus(status: object) {
141
+ this.meetingMediaStatus = status;
142
+ }
143
+
144
+ /**
145
+ * captures MQA data from media connection
146
+ *
147
+ * @public
148
+ * @memberof StatsAnalyzer
149
+ * @returns {void}
150
+ */
151
+ sendMqaData() {
152
+ const newMqa = cloneDeep(emptyMqaInterval);
153
+
154
+ Object.keys(this.statsResults).forEach((mediaType) => {
155
+ if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {
156
+ const audioSender = cloneDeep(emptyAudioTransmit);
157
+
158
+ getAudioSenderMqa({
159
+ audioSender,
160
+ statsResults: this.statsResults,
161
+ lastMqaDataSent: this.lastMqaDataSent,
162
+ mediaType,
163
+ });
164
+ newMqa.audioTransmit.push(audioSender);
165
+ } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
166
+ const audioReceiver = cloneDeep(emptyAudioReceive);
167
+
168
+ getAudioReceiverMqa({
169
+ audioReceiver,
170
+ statsResults: this.statsResults,
171
+ lastMqaDataSent: this.lastMqaDataSent,
172
+ mediaType,
173
+ });
174
+ newMqa.audioReceive.push(audioReceiver);
175
+ } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {
176
+ const videoSender = cloneDeep(emptyVideoTransmit);
177
+
178
+ getVideoSenderMqa({
179
+ videoSender,
180
+ statsResults: this.statsResults,
181
+ lastMqaDataSent: this.lastMqaDataSent,
182
+ mediaType,
183
+ });
184
+ newMqa.videoTransmit.push(videoSender);
185
+ } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
186
+ const videoReceiver = cloneDeep(emptyVideoReceive);
187
+
188
+ getVideoReceiverMqa({
189
+ videoReceiver,
190
+ statsResults: this.statsResults,
191
+ lastMqaDataSent: this.lastMqaDataSent,
192
+ mediaType,
193
+ });
194
+ newMqa.videoReceive.push(videoReceiver);
195
+ }
196
+ });
197
+
198
+ newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
199
+
200
+ // Adding peripheral information
201
+ newMqa.intervalMetadata.peripherals = [];
202
+
203
+ newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});
204
+ if (this.statsResults['audio-send']) {
205
+ newMqa.intervalMetadata.peripherals.push({
206
+ information: this.statsResults['audio-send']?.trackLabel,
207
+ name: MEDIA_DEVICES.MICROPHONE,
208
+ });
209
+ }
210
+ if (this.statsResults['video-send']) {
211
+ newMqa.intervalMetadata.peripherals.push({
212
+ information: this.statsResults['video-send']?.trackLabel,
213
+ name: MEDIA_DEVICES.CAMERA,
214
+ });
215
+ }
216
+
217
+ newMqa.networkType = this.statsResults.connectionType.local.networkType;
218
+
219
+ this.mqaSentCount += 1;
220
+
221
+ newMqa.intervalNumber = this.mqaSentCount;
222
+
223
+ this.resetStatsResults();
224
+
225
+ this.emit(
226
+ {
227
+ file: 'statsAnalyzer',
228
+ function: 'sendMqaData',
229
+ },
230
+ EVENTS.MEDIA_QUALITY,
231
+ {
232
+ data: newMqa,
233
+ // @ts-ignore
234
+ networkType: newMqa.networkType,
235
+ }
236
+ );
237
+ }
238
+
239
+ /**
240
+ * updated the media connection when changed
241
+ *
242
+ * @private
243
+ * @memberof StatsAnalyzer
244
+ * @param {RoapMediaConnection} mediaConnection
245
+ * @returns {void}
246
+ */
247
+ updateMediaConnection(mediaConnection: any) {
248
+ this.mediaConnection = mediaConnection;
249
+ }
250
+
251
+ /**
252
+ * Starts the stats analyzer on interval
253
+ *
254
+ * @public
255
+ * @memberof StatsAnalyzer
256
+ * @param {RoapMediaConnection} mediaConnection
257
+ * @returns {Promise}
258
+ */
259
+ public startAnalyzer(mediaConnection: any) {
260
+ if (!this.statsStarted) {
261
+ this.statsStarted = true;
262
+ this.mediaConnection = mediaConnection;
263
+
264
+ return this.getStatsAndParse().then(() => {
265
+ this.statsInterval = setInterval(() => {
266
+ this.getStatsAndParse();
267
+ }, this.config.analyzerInterval);
268
+ // Trigger initial fetch
269
+ this.sendMqaData();
270
+ this.mqaInterval = setInterval(() => {
271
+ this.sendMqaData();
272
+ }, MQA_INTEVAL);
273
+ });
274
+ }
275
+
276
+ return Promise.resolve();
277
+ }
278
+
279
+ /**
280
+ * Cleans up the analyzer when done
281
+ *
282
+ * @public
283
+ * @memberof StatsAnalyzer
284
+ * @returns {void}
285
+ */
286
+ public stopAnalyzer() {
287
+ const sendOneLastMqa = this.mqaInterval && this.statsInterval;
288
+
289
+ if (this.statsInterval) {
290
+ clearInterval(this.statsInterval);
291
+ this.statsInterval = undefined;
292
+ }
293
+
294
+ if (this.mqaInterval) {
295
+ clearInterval(this.mqaInterval);
296
+ this.mqaInterval = undefined;
297
+ }
298
+
299
+ if (sendOneLastMqa) {
300
+ return this.getStatsAndParse().then(() => {
301
+ this.sendMqaData();
302
+ this.mediaConnection = null;
303
+ });
304
+ }
305
+
306
+ return Promise.resolve();
307
+ }
308
+
309
+ /**
310
+ * Parse a single result of get stats
311
+ *
312
+ * @private
313
+ * @param {*} getStatsResult
314
+ * @param {String} type
315
+ * @param {boolean} isSender
316
+ * @returns {void}
317
+ * @memberof StatsAnalyzer
318
+ */
319
+ private parseGetStatsResult(getStatsResult: any, type: string, isSender: boolean) {
320
+ if (!getStatsResult) {
321
+ return;
322
+ }
323
+
324
+ // Generate empty stats results
325
+ if (!this.statsResults[type]) {
326
+ this.statsResults[type] = {};
327
+ }
328
+
329
+ if (isSender && !this.statsResults[type].send) {
330
+ this.statsResults[type].send = cloneDeep(emptySender);
331
+ } else if (!isSender && !this.statsResults[type].recv) {
332
+ this.statsResults[type].recv = cloneDeep(emptyReceiver);
333
+ }
334
+
335
+ if (!this.statsResults.resolutions[type]) {
336
+ this.statsResults.resolutions[type] = {};
337
+ }
338
+
339
+ if (isSender && !this.statsResults.resolutions[type].send) {
340
+ this.statsResults.resolutions[type].send = cloneDeep(emptySender);
341
+ } else if (!isSender && !this.statsResults.resolutions[type].recv) {
342
+ this.statsResults.resolutions[type].recv = cloneDeep(emptyReceiver);
343
+ }
344
+
345
+ if (!this.statsResults.internal[type]) {
346
+ this.statsResults.internal[type] = {};
347
+ }
348
+
349
+ if (isSender && !this.statsResults.internal[type].send) {
350
+ this.statsResults.internal[type].send = cloneDeep(emptySender);
351
+ } else if (!isSender && !this.statsResults.internal[type].recv) {
352
+ this.statsResults.internal[type].recv = cloneDeep(emptyReceiver);
353
+ }
354
+
355
+ switch (getStatsResult.type) {
356
+ case 'outbound-rtp':
357
+ this.processOutboundRTPResult(getStatsResult, type);
358
+ break;
359
+ case 'inbound-rtp':
360
+ this.processInboundRTPResult(getStatsResult, type);
361
+ break;
362
+ case 'track':
363
+ this.processTrackResult(getStatsResult, type);
364
+ break;
365
+ case 'remote-inbound-rtp':
366
+ case 'remote-outbound-rtp':
367
+ // @ts-ignore
368
+ this.compareSentAndReceived(getStatsResult, type, isSender);
369
+ break;
370
+ case 'remotecandidate':
371
+ case 'remote-candidate':
372
+ this.parseCandidate(getStatsResult, type, isSender, true);
373
+ break;
374
+ case 'local-candidate':
375
+ this.parseCandidate(getStatsResult, type, isSender, false);
376
+ break;
377
+ case 'media-source':
378
+ // @ts-ignore
379
+ this.parseAudioSource(getStatsResult, type);
380
+ break;
381
+ default:
382
+ break;
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Filters the get stats results for types
388
+ * @private
389
+ * @param {Array} statsItem
390
+ * @param {String} type
391
+ * @param {boolean} isSender
392
+ * @returns {void}
393
+ */
394
+ filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {
395
+ const {types} = DEFAULT_GET_STATS_FILTER;
396
+
397
+ // get the successful candidate pair before parsing stats.
398
+ statsItem.report.forEach((report) => {
399
+ if (report.type === 'candidate-pair' && report.state === 'succeeded') {
400
+ this.successfulCandidatePair = report;
401
+ }
402
+ });
403
+
404
+ statsItem.report.forEach((result) => {
405
+ if (types.includes(result.type)) {
406
+ this.parseGetStatsResult(result, type, isSender);
407
+ }
408
+ });
409
+
410
+ if (this.statsResults[type]) {
411
+ this.statsResults[type].direction = statsItem.currentDirection;
412
+ this.statsResults[type].trackLabel = statsItem.localTrackLabel;
413
+ this.statsResults[type].csi = statsItem.csi;
414
+ // reset the successful candidate pair.
415
+ this.successfulCandidatePair = {};
416
+ }
417
+ }
418
+
419
+ /**
420
+ * parse the audio
421
+ * @param {String} result
422
+ * @param {boolean} type
423
+ * @returns {void}
424
+ */
425
+ parseAudioSource(result: any, type: any) {
426
+ if (!result) {
427
+ return;
428
+ }
429
+
430
+ if (type.includes('audio-send')) {
431
+ this.statsResults[type].send.audioLevel = result.audioLevel;
432
+ this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;
433
+ }
434
+ }
435
+
436
+ /**
437
+ * emits started/stopped events for local/remote media by checking
438
+ * if given values are increasing or not. The previousValue, currentValue
439
+ * params can be any numerical value like number of receive packets or
440
+ * decoded frames, etc.
441
+ *
442
+ * @private
443
+ * @param {string} mediaType
444
+ * @param {number} previousValue - value to compare
445
+ * @param {number} currentValue - value to compare (must be same type of value as previousValue)
446
+ * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received
447
+ * @memberof StatsAnalyzer
448
+ * @returns {void}
449
+ */
450
+ emitStartStopEvents = (
451
+ mediaType: string,
452
+ previousValue: number,
453
+ currentValue: number,
454
+ isLocal: boolean
455
+ ) => {
456
+ if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {
457
+ throw new Error(`Unsupported mediaType: ${mediaType}`);
458
+ }
459
+
460
+ // eslint-disable-next-line no-param-reassign
461
+ if (previousValue === undefined) previousValue = 0;
462
+ // eslint-disable-next-line no-param-reassign
463
+ if (currentValue === undefined) currentValue = 0;
464
+
465
+ if (!this.lastEmittedStartStopEvent[mediaType]) {
466
+ this.lastEmittedStartStopEvent[mediaType] = {};
467
+ }
468
+
469
+ const lastEmittedEvent = isLocal
470
+ ? this.lastEmittedStartStopEvent[mediaType].local
471
+ : this.lastEmittedStartStopEvent[mediaType].remote;
472
+
473
+ let newEvent;
474
+
475
+ if (currentValue - previousValue > 0) {
476
+ newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
477
+ } else if (currentValue === previousValue && currentValue > 0) {
478
+ newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
479
+ }
480
+
481
+ if (newEvent && lastEmittedEvent !== newEvent) {
482
+ if (isLocal) {
483
+ this.lastEmittedStartStopEvent[mediaType].local = newEvent;
484
+ } else {
485
+ this.lastEmittedStartStopEvent[mediaType].remote = newEvent;
486
+ }
487
+ this.emit(
488
+ {
489
+ file: 'statsAnalyzer/index',
490
+ function: 'compareLastStatsResult',
491
+ },
492
+ newEvent,
493
+ {
494
+ type: mediaType,
495
+ }
496
+ );
497
+ }
498
+ };
499
+
500
+ /**
501
+ * compares current and previous stats to check if packets are not sent
502
+ *
503
+ * @private
504
+ * @memberof StatsAnalyzer
505
+ * @returns {void}
506
+ */
507
+ private compareLastStatsResult() {
508
+ if (this.lastStatsResults !== null && this.meetingMediaStatus) {
509
+ const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
510
+ Object.keys(this.statsResults)
511
+ .filter((key) => key.startsWith(keyPrefix))
512
+ .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
513
+
514
+ const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
515
+ Object.keys(this.statsResults)
516
+ .filter((key) => key.startsWith(keyPrefix))
517
+ .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
518
+
519
+ const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
520
+ Object.keys(this.statsResults)
521
+ .filter((key) => key.startsWith(keyPrefix))
522
+ .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]?.recv[value] || 0), 0);
523
+
524
+ const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
525
+ Object.keys(this.statsResults)
526
+ .filter((key) => key.startsWith(keyPrefix))
527
+ .reduce(
528
+ (prev, cur) => prev + (this.lastStatsResults.resolutions[cur]?.recv[value] || 0),
529
+ 0
530
+ );
531
+
532
+ if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
533
+ // compare audio stats sent
534
+ // NOTE: relies on there being only one sender.
535
+ const currentStats = this.statsResults['audio-send'].send;
536
+ const previousStats = this.lastStatsResults['audio-send'].send;
537
+
538
+ if (
539
+ currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
540
+ currentStats.totalPacketsSent === 0
541
+ ) {
542
+ LoggerProxy.logger.info(
543
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,
544
+ currentStats.totalPacketsSent
545
+ );
546
+ } else {
547
+ if (
548
+ currentStats.totalAudioEnergy === previousStats.totalAudioEnergy ||
549
+ currentStats.totalAudioEnergy === 0
550
+ ) {
551
+ LoggerProxy.logger.info(
552
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,
553
+ currentStats.totalAudioEnergy
554
+ );
555
+ }
556
+
557
+ if (currentStats.audioLevel === 0) {
558
+ LoggerProxy.logger.info(
559
+ `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`
560
+ );
561
+ }
562
+ }
563
+
564
+ this.emitStartStopEvents(
565
+ 'audio',
566
+ previousStats.totalPacketsSent,
567
+ currentStats.totalPacketsSent,
568
+ true
569
+ );
570
+ }
571
+
572
+ if (this.meetingMediaStatus.expected.receiveAudio) {
573
+ // compare audio stats received
574
+ const currentPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
575
+ const previousPacketsReceived = getPreviousStatsTotals(
576
+ 'audio-recv',
577
+ 'totalPacketsReceived'
578
+ );
579
+ const currentSamplesReceived = getCurrentStatsTotals('audio-recv', 'totalSamplesReceived');
580
+ const previousSamplesReceived = getPreviousStatsTotals(
581
+ 'audio-recv',
582
+ 'totalSamplesReceived'
583
+ );
584
+
585
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
586
+ LoggerProxy.logger.info(
587
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
588
+ currentPacketsReceived
589
+ );
590
+ } else if (
591
+ currentSamplesReceived === previousSamplesReceived ||
592
+ currentSamplesReceived === 0
593
+ ) {
594
+ LoggerProxy.logger.info(
595
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
596
+ currentSamplesReceived
597
+ );
598
+ }
599
+
600
+ this.emitStartStopEvents('audio', previousPacketsReceived, currentPacketsReceived, false);
601
+ }
602
+
603
+ if (this.meetingMediaStatus.expected.sendVideo && this.lastStatsResults['video-send']) {
604
+ // compare video stats sent
605
+ const currentStats = this.statsResults['video-send'].send;
606
+ const previousStats = this.lastStatsResults['video-send'].send;
607
+
608
+ if (
609
+ currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
610
+ currentStats.totalPacketsSent === 0
611
+ ) {
612
+ LoggerProxy.logger.info(
613
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
614
+ currentStats.totalPacketsSent
615
+ );
616
+ } else {
617
+ if (
618
+ currentStats.framesEncoded === previousStats.framesEncoded ||
619
+ currentStats.framesEncoded === 0
620
+ ) {
621
+ LoggerProxy.logger.info(
622
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
623
+ currentStats.framesEncoded
624
+ );
625
+ }
626
+
627
+ if (
628
+ this.statsResults.resolutions['video-send'].send.framesSent ===
629
+ this.lastStatsResults.resolutions['video-send'].send.framesSent ||
630
+ this.statsResults.resolutions['video-send'].send.framesSent === 0
631
+ ) {
632
+ LoggerProxy.logger.info(
633
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
634
+ this.statsResults.resolutions['video-send'].send.framesSent
635
+ );
636
+ }
637
+ }
638
+
639
+ this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);
640
+ }
641
+
642
+ if (this.meetingMediaStatus.expected.receiveVideo) {
643
+ // compare video stats received
644
+ const currentPacketsReceived = getCurrentStatsTotals('video-recv', 'totalPacketsReceived');
645
+ const previousPacketsReceived = getPreviousStatsTotals(
646
+ 'video-recv',
647
+ 'totalPacketsReceived'
648
+ );
649
+ const currentFramesReceived = getCurrentResolutionsStatsTotals(
650
+ 'video-recv',
651
+ 'framesReceived'
652
+ );
653
+ const previousFramesReceived = getPreviousResolutionsStatsTotals(
654
+ 'video-recv',
655
+ 'framesReceived'
656
+ );
657
+ const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
658
+ const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
659
+ const currentFramesDropped = getCurrentResolutionsStatsTotals(
660
+ 'video-recv',
661
+ 'framesDropped'
662
+ );
663
+ const previousFramesDropped = getPreviousResolutionsStatsTotals(
664
+ 'video-recv',
665
+ 'framesDropped'
666
+ );
667
+
668
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
669
+ LoggerProxy.logger.info(
670
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`,
671
+ currentPacketsReceived
672
+ );
673
+ } else {
674
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
675
+ LoggerProxy.logger.info(
676
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
677
+ currentFramesReceived
678
+ );
679
+ }
680
+
681
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
682
+ LoggerProxy.logger.info(
683
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
684
+ currentFramesDecoded
685
+ );
686
+ }
687
+
688
+ if (currentFramesDropped - previousFramesDropped > 10) {
689
+ LoggerProxy.logger.info(
690
+ `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
691
+ currentFramesDropped - previousFramesDropped
692
+ );
693
+ }
694
+ }
695
+
696
+ this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);
697
+ }
698
+
699
+ if (this.meetingMediaStatus.expected.sendShare && this.lastStatsResults['video-share-send']) {
700
+ // compare share stats sent
701
+
702
+ const currentStats = this.statsResults['video-share-send'].send;
703
+ const previousStats = this.lastStatsResults['video-share-send'].send;
704
+
705
+ if (
706
+ currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
707
+ currentStats.totalPacketsSent === 0
708
+ ) {
709
+ LoggerProxy.logger.info(
710
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
711
+ currentStats.totalPacketsSent
712
+ );
713
+ } else {
714
+ if (
715
+ currentStats.framesEncoded === previousStats.framesEncoded ||
716
+ currentStats.framesEncoded === 0
717
+ ) {
718
+ LoggerProxy.logger.info(
719
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
720
+ currentStats.framesEncoded
721
+ );
722
+ }
723
+
724
+ if (
725
+ this.statsResults.resolutions['video-share-send'].send.framesSent ===
726
+ this.lastStatsResults.resolutions['video-share-send'].send.framesSent ||
727
+ this.statsResults.resolutions['video-share-send'].send.framesSent === 0
728
+ ) {
729
+ LoggerProxy.logger.info(
730
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
731
+ this.statsResults.resolutions['video-share-send'].send.framesSent
732
+ );
733
+ }
734
+ }
735
+ }
736
+
737
+ if (this.meetingMediaStatus.expected.sendShare) {
738
+ // TODO:need to check receive share value
739
+ // compare share stats received
740
+ const currentPacketsReceived = getCurrentStatsTotals(
741
+ 'video-share-recv',
742
+ 'totalPacketsReceived'
743
+ );
744
+ const previousPacketsReceived = getPreviousStatsTotals(
745
+ 'video-share-recv',
746
+ 'totalPacketsReceived'
747
+ );
748
+ const currentFramesReceived = getCurrentResolutionsStatsTotals(
749
+ 'video-share-recv',
750
+ 'framesReceived'
751
+ );
752
+ const previousFramesReceived = getPreviousResolutionsStatsTotals(
753
+ 'video-share-recv',
754
+ 'framesReceived'
755
+ );
756
+ const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
757
+ const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
758
+ const currentFramesDropped = getCurrentResolutionsStatsTotals(
759
+ 'video-share-recv',
760
+ 'framesDropped'
761
+ );
762
+ const previousFramesDropped = getPreviousResolutionsStatsTotals(
763
+ 'video-share-recv',
764
+ 'framesDropped'
765
+ );
766
+
767
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
768
+ LoggerProxy.logger.info(
769
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
770
+ currentPacketsReceived
771
+ );
772
+ } else {
773
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
774
+ LoggerProxy.logger.info(
775
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
776
+ currentFramesReceived
777
+ );
778
+ }
779
+
780
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
781
+ LoggerProxy.logger.info(
782
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
783
+ currentFramesDecoded
784
+ );
785
+ }
786
+
787
+ if (currentFramesDropped - previousFramesDropped > 10) {
788
+ LoggerProxy.logger.info(
789
+ `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`,
790
+ currentFramesDropped - previousFramesDropped
791
+ );
792
+ }
793
+ }
794
+
795
+ // we are not calling emitStartStopEvents() for sending or receiving share because sharing is often started and stopped
796
+ // in meetings and this.meetingMediaStatus.expected values can be out of sync with the actual packet flow
797
+ // so we would send "sharing stopped" events incorrectly
798
+ }
799
+ }
800
+ }
801
+
802
+ /**
803
+ * Does a `getStats` on all the transceivers and parses the results
804
+ *
805
+ * @private
806
+ * @memberof StatsAnalyzer
807
+ * @returns {Promise}
808
+ */
809
+ private getStatsAndParse() {
810
+ if (!this.mediaConnection) {
811
+ return Promise.resolve();
812
+ }
813
+
814
+ if (
815
+ this.mediaConnection &&
816
+ this.mediaConnection.getConnectionState() === ConnectionState.Failed
817
+ ) {
818
+ LoggerProxy.logger.trace(
819
+ 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'
820
+ );
821
+
822
+ return Promise.resolve();
823
+ }
824
+
825
+ LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');
826
+
827
+ return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {
828
+ transceiverStats.video.receivers.forEach((receiver, i) =>
829
+ this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)
830
+ );
831
+ transceiverStats.audio.receivers.forEach((receiver, i) =>
832
+ this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)
833
+ );
834
+ transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>
835
+ this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)
836
+ );
837
+ transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>
838
+ this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)
839
+ );
840
+
841
+ transceiverStats.video.senders.forEach((sender, i) => {
842
+ if (i > 0) {
843
+ throw new Error('Stats Analyzer does not support multiple senders.');
844
+ }
845
+ this.filterAndParseGetStatsResults(sender, 'video-send', true);
846
+ });
847
+ transceiverStats.audio.senders.forEach((sender, i) => {
848
+ if (i > 0) {
849
+ throw new Error('Stats Analyzer does not support multiple senders.');
850
+ }
851
+ this.filterAndParseGetStatsResults(sender, 'audio-send', true);
852
+ });
853
+ transceiverStats.screenShareVideo.senders.forEach((sender, i) => {
854
+ if (i > 0) {
855
+ throw new Error('Stats Analyzer does not support multiple senders.');
856
+ }
857
+ this.filterAndParseGetStatsResults(sender, 'video-share-send', true);
858
+ });
859
+ transceiverStats.screenShareAudio.senders.forEach((sender, i) => {
860
+ if (i > 0) {
861
+ throw new Error('Stats Analyzer does not support multiple senders.');
862
+ }
863
+ this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);
864
+ });
865
+
866
+ this.compareLastStatsResult();
867
+
868
+ // Save the last results to compare with the current
869
+ // DO Deep copy, for some reason it takes the reference all the time rather then old value set
870
+ this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));
871
+
872
+ LoggerProxy.logger.trace(
873
+ 'StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats'
874
+ );
875
+ });
876
+ }
877
+
878
+ /**
879
+ * Processes OutboundRTP stats result and stores
880
+ * @private
881
+ * @param {*} result
882
+ * @param {*} mediaType
883
+ * @returns {void}
884
+ */
885
+ private processOutboundRTPResult(result: any, mediaType: any) {
886
+ const sendrecvType = STATS.SEND_DIRECTION;
887
+
888
+ if (result.bytesSent) {
889
+ let kilobytes = 0;
890
+
891
+ if (result.frameWidth && result.frameHeight) {
892
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
893
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
894
+ this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
895
+ this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent =
896
+ result.hugeFramesSent;
897
+ }
898
+
899
+ if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {
900
+ this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
901
+ }
902
+ if (!this.statsResults.internal[mediaType][sendrecvType].framesEncoded) {
903
+ this.statsResults.internal[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
904
+ }
905
+ if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {
906
+ this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =
907
+ result.keyFramesEncoded;
908
+ }
909
+
910
+ const bytes =
911
+ result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;
912
+
913
+ this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
914
+
915
+ kilobytes = bytes / 1024;
916
+
917
+ this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
918
+ this.statsResults[mediaType].bytesSent = kilobytes;
919
+
920
+ this.statsResults[mediaType][sendrecvType].framesEncoded =
921
+ result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
922
+ this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
923
+ result.keyFramesEncoded -
924
+ this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;
925
+ this.statsResults.internal[mediaType].outboundRtpId = result.id;
926
+
927
+ if (!this.statsResults.internal[mediaType][sendrecvType].packetsSent) {
928
+ this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
929
+ }
930
+
931
+ this.statsResults[mediaType][sendrecvType].packetsSent =
932
+ result.packetsSent - this.statsResults.internal[mediaType][sendrecvType].packetsSent;
933
+ this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
934
+
935
+ // Data saved to send MQA metrics
936
+
937
+ this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;
938
+ this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
939
+ this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
940
+ this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;
941
+ this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;
942
+ this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
943
+ this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
944
+ this.statsResults[mediaType][sendrecvType].encoderImplementation =
945
+ result.encoderImplementation;
946
+ this.statsResults[mediaType][sendrecvType].qualityLimitationReason =
947
+ result.qualityLimitationReason;
948
+ this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =
949
+ result.qualityLimitationResolutionChanges;
950
+ this.statsResults[mediaType][sendrecvType].retransmittedPacketsSent =
951
+ result.retransmittedPacketsSent;
952
+ this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;
953
+ this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;
954
+ this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =
955
+ result.retransmittedBytesSent;
956
+ }
957
+ }
958
+
959
+ /**
960
+ * Processes InboundRTP stats result and stores
961
+ * @private
962
+ * @param {*} result
963
+ * @param {*} mediaType
964
+ * @returns {void}
965
+ */
966
+ private processInboundRTPResult(result: any, mediaType: any) {
967
+ const sendrecvType = STATS.RECEIVE_DIRECTION;
968
+
969
+ if (result.bytesReceived) {
970
+ let kilobytes = 0;
971
+ const receiveSlot = this.receiveSlotCallback(result.ssrc);
972
+ const idAndCsi = receiveSlot
973
+ ? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
974
+ : '';
975
+
976
+ if (result.frameWidth && result.frameHeight) {
977
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
978
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
979
+ this.statsResults.resolutions[mediaType][sendrecvType].framesReceived =
980
+ result.framesReceived;
981
+ }
982
+
983
+ if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {
984
+ this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =
985
+ result.bytesReceived;
986
+ }
987
+
988
+ if (!this.statsResults.internal[mediaType][sendrecvType].pliCount) {
989
+ this.statsResults.internal[mediaType][sendrecvType].pliCount = result.pliCount;
990
+ }
991
+
992
+ if (!this.statsResults.internal[mediaType][sendrecvType].packetsLost) {
993
+ this.statsResults.internal[mediaType][sendrecvType].packetsLost = result.packetsLost;
994
+ }
995
+
996
+ if (!this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived) {
997
+ this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
998
+ result.packetsReceived;
999
+ }
1000
+
1001
+ if (!this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp) {
1002
+ this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp =
1003
+ result.lastPacketReceivedTimestamp;
1004
+ }
1005
+
1006
+ const bytes =
1007
+ result.bytesReceived -
1008
+ this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived;
1009
+
1010
+ this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived = result.bytesReceived;
1011
+
1012
+ kilobytes = bytes / 1024;
1013
+ this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
1014
+ this.statsResults[mediaType].bytesReceived = kilobytes.toFixed(1);
1015
+
1016
+ this.statsResults[mediaType][sendrecvType].pliCount =
1017
+ result.pliCount - this.statsResults.internal[mediaType][sendrecvType].pliCount;
1018
+ this.statsResults[mediaType][sendrecvType].currentPacketsLost =
1019
+ result.packetsLost - this.statsResults.internal[mediaType][sendrecvType].packetsLost;
1020
+ if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {
1021
+ this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;
1022
+ }
1023
+
1024
+ this.statsResults[mediaType][sendrecvType].packetsReceived =
1025
+ result.packetsReceived -
1026
+ this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived;
1027
+ this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
1028
+ result.packetsReceived;
1029
+
1030
+ if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {
1031
+ if (receiveSlot) {
1032
+ LoggerProxy.logger.info(
1033
+ `StatsAnalyzer:index#processInboundRTPResult --> No packets received for receive slot ${idAndCsi}`,
1034
+ this.statsResults[mediaType][sendrecvType].packetsReceived
1035
+ );
1036
+ }
1037
+ }
1038
+
1039
+ // Check the over all packet Lost ratio
1040
+ this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =
1041
+ this.statsResults[mediaType][sendrecvType].currentPacketsLost > 0
1042
+ ? this.statsResults[mediaType][sendrecvType].currentPacketsLost /
1043
+ (this.statsResults[mediaType][sendrecvType].packetsReceived +
1044
+ this.statsResults[mediaType][sendrecvType].currentPacketsLost)
1045
+ : 0;
1046
+ if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
1047
+ LoggerProxy.logger.info(
1048
+ `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,
1049
+ this.statsResults[mediaType][sendrecvType].currentPacketLossRatio
1050
+ );
1051
+ }
1052
+
1053
+ // TODO: check the packet loss value is negative values here
1054
+
1055
+ if (result.packetsLost) {
1056
+ this.statsResults[mediaType][sendrecvType].totalPacketsLost =
1057
+ result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;
1058
+ } else {
1059
+ this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;
1060
+ }
1061
+
1062
+ this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =
1063
+ result.lastPacketReceivedTimestamp;
1064
+
1065
+ // From Thin
1066
+ this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
1067
+ this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
1068
+ this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
1069
+ this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;
1070
+
1071
+ this.statsResults[mediaType][sendrecvType].decoderImplementation =
1072
+ result.decoderImplementation;
1073
+ this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
1074
+
1075
+ this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;
1076
+ this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;
1077
+ this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;
1078
+ this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;
1079
+
1080
+ this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);
1081
+
1082
+ // Audio stats
1083
+
1084
+ this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;
1085
+ this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;
1086
+ this.statsResults[mediaType][sendrecvType].totalSamplesReceived =
1087
+ result.totalSamplesReceived || 0;
1088
+ this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =
1089
+ result.totalSamplesDecoded || 0;
1090
+ this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;
1091
+ }
1092
+ }
1093
+
1094
+ /**
1095
+ * Processes remote and local candidate result and stores
1096
+ * @private
1097
+ * @param {*} result
1098
+ * @param {*} type
1099
+ * @param {boolean} isSender
1100
+ * @param {boolean} isRemote
1101
+ *
1102
+ * @returns {void}
1103
+ */
1104
+ parseCandidate = (result: any, type: any, isSender: boolean, isRemote: boolean) => {
1105
+ if (!result || !result.id) {
1106
+ return;
1107
+ }
1108
+
1109
+ // We only care about the successful local candidate
1110
+ if (this.successfulCandidatePair?.localCandidateId !== result.id) {
1111
+ return;
1112
+ }
1113
+
1114
+ let transport;
1115
+ if (result.relayProtocol) {
1116
+ transport = result.relayProtocol.toUpperCase();
1117
+ } else if (result.protocol) {
1118
+ transport = result.protocol.toUpperCase();
1119
+ }
1120
+
1121
+ const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
1122
+ const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
1123
+
1124
+ this.statsResults.internal.candidates[result.id] = {
1125
+ candidateType: result.candidateType,
1126
+ ipAddress: result.ip, // TODO: add ports
1127
+ portNumber: result.port,
1128
+ networkType: result.networkType,
1129
+ priority: result.priority,
1130
+ transport,
1131
+ timestamp: result.time,
1132
+ id: result.id,
1133
+ type: result.type,
1134
+ };
1135
+
1136
+ this.statsResults.connectionType[ipType].candidateType = result.candidateType;
1137
+ this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
1138
+
1139
+ this.statsResults.connectionType[ipType].networkType =
1140
+ result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;
1141
+ this.statsResults.connectionType[ipType].transport = transport;
1142
+
1143
+ this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
1144
+ };
1145
+
1146
+ /**
1147
+ * Process Track results
1148
+ *
1149
+ * @private
1150
+ * @param {*} result
1151
+ * @param {*} mediaType
1152
+ * @returns {void}
1153
+ * @memberof StatsAnalyzer
1154
+ */
1155
+ private processTrackResult(result: any, mediaType: any) {
1156
+ if (!result || result.type !== 'track') {
1157
+ return;
1158
+ }
1159
+
1160
+ const sendrecvType =
1161
+ result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
1162
+
1163
+ if (sendrecvType === STATS.RECEIVE_DIRECTION) {
1164
+ this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
1165
+ this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
1166
+ this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
1167
+ }
1168
+
1169
+ if (result.trackIdentifier && !mediaType.includes('audio')) {
1170
+ this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =
1171
+ result.trackIdentifier;
1172
+
1173
+ const jitterBufferDelay = result && result.jitterBufferDelay;
1174
+ const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;
1175
+
1176
+ this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =
1177
+ jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;
1178
+
1179
+ // Used to calculate the jitter
1180
+ this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =
1181
+ result.jitterBufferDelay;
1182
+ this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =
1183
+ result.jitterBufferEmittedCount;
1184
+ }
1185
+ }
1186
+
1187
+ /**
1188
+ *
1189
+ * @private
1190
+ * @param {*} result
1191
+ * @param {*} type
1192
+ * @returns {void}
1193
+ * @memberof StatsAnalyzer
1194
+ */
1195
+ compareSentAndReceived(result, type) {
1196
+ // Don't compare on transceivers without a sender.
1197
+ if (!type || !this.statsResults.internal[type].send) {
1198
+ return;
1199
+ }
1200
+
1201
+ const mediaType = type;
1202
+
1203
+ if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {
1204
+ this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1205
+ }
1206
+
1207
+ const currentPacketLoss =
1208
+ result.packetsLost - this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver;
1209
+
1210
+ this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1211
+ this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
1212
+ this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1213
+
1214
+ this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);
1215
+ this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);
1216
+
1217
+ this.statsResults[mediaType].send.timestamp = result.timestamp;
1218
+ this.statsResults[mediaType].send.ssrc = result.ssrc;
1219
+ this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;
1220
+
1221
+ // Total packloss ratio on this video section of the call
1222
+ this.statsResults[mediaType].send.overAllPacketLossRatio =
1223
+ this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0
1224
+ ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver /
1225
+ this.statsResults[mediaType].send.totalPacketsSent
1226
+ : 0;
1227
+ this.statsResults[mediaType].send.currentPacketLossRatio =
1228
+ this.statsResults[mediaType].send.packetsLostOnReceiver > 0
1229
+ ? (this.statsResults[mediaType].send.packetsLostOnReceiver * 100) /
1230
+ (this.statsResults[mediaType].send.packetsSent +
1231
+ this.statsResults[mediaType].send.packetsLostOnReceiver)
1232
+ : 0;
1233
+
1234
+ if (
1235
+ this.statsResults[mediaType].send.maxPacketLossRatio <
1236
+ this.statsResults[mediaType].send.currentPacketLossRatio
1237
+ ) {
1238
+ this.statsResults[mediaType].send.maxPacketLossRatio =
1239
+ this.statsResults[mediaType].send.currentPacketLossRatio;
1240
+ }
1241
+
1242
+ if (result.type === 'remote-inbound-rtp') {
1243
+ this.networkQualityMonitor.determineUplinkNetworkQuality({
1244
+ mediaType,
1245
+ remoteRtpResults: result,
1246
+ statsAnalyzerCurrentStats: this.statsResults,
1247
+ });
1248
+ }
1249
+ }
1250
+ }