@webex/plugin-meetings 3.0.0-beta.21 → 3.0.0-beta.211

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 (422) hide show
  1. package/README.md +45 -7
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +114 -14
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +841 -19
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/request.js +78 -0
  17. package/dist/breakouts/request.js.map +1 -0
  18. package/dist/breakouts/utils.js +67 -0
  19. package/dist/breakouts/utils.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +3 -2
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/queue.js +24 -9
  25. package/dist/common/queue.js.map +1 -1
  26. package/dist/config.js +3 -8
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +179 -30
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/constants.js +14 -0
  31. package/dist/controls-options-manager/constants.js.map +1 -0
  32. package/dist/controls-options-manager/enums.js +27 -0
  33. package/dist/controls-options-manager/enums.js.map +1 -0
  34. package/dist/controls-options-manager/index.js +297 -0
  35. package/dist/controls-options-manager/index.js.map +1 -0
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +319 -0
  39. package/dist/controls-options-manager/util.js.map +1 -0
  40. package/dist/index.js +106 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/interpretation/collection.js +23 -0
  43. package/dist/interpretation/collection.js.map +1 -0
  44. package/dist/interpretation/index.js +366 -0
  45. package/dist/interpretation/index.js.map +1 -0
  46. package/dist/interpretation/siLanguage.js +25 -0
  47. package/dist/interpretation/siLanguage.js.map +1 -0
  48. package/dist/locus-info/controlsUtils.js +91 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +359 -64
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/infoUtils.js +7 -1
  53. package/dist/locus-info/infoUtils.js.map +1 -1
  54. package/dist/locus-info/mediaSharesUtils.js +43 -1
  55. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  56. package/dist/locus-info/parser.js +219 -63
  57. package/dist/locus-info/parser.js.map +1 -1
  58. package/dist/locus-info/selfUtils.js +89 -14
  59. package/dist/locus-info/selfUtils.js.map +1 -1
  60. package/dist/media/index.js +48 -135
  61. package/dist/media/index.js.map +1 -1
  62. package/dist/media/properties.js +29 -90
  63. package/dist/media/properties.js.map +1 -1
  64. package/dist/mediaQualityMetrics/config.js +505 -493
  65. package/dist/mediaQualityMetrics/config.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +90 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +2770 -2547
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +291 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +229 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +199 -193
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +532 -414
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +48 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +171 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/utilv2.js +20 -5
  83. package/dist/meeting-info/utilv2.js.map +1 -1
  84. package/dist/meetings/collection.js +22 -0
  85. package/dist/meetings/collection.js.map +1 -1
  86. package/dist/meetings/index.js +357 -66
  87. package/dist/meetings/index.js.map +1 -1
  88. package/dist/meetings/meetings.types.js +7 -0
  89. package/dist/meetings/meetings.types.js.map +1 -0
  90. package/dist/meetings/request.js +2 -0
  91. package/dist/meetings/request.js.map +1 -1
  92. package/dist/meetings/util.js +88 -1
  93. package/dist/meetings/util.js.map +1 -1
  94. package/dist/member/index.js +49 -0
  95. package/dist/member/index.js.map +1 -1
  96. package/dist/member/types.js +25 -0
  97. package/dist/member/types.js.map +1 -0
  98. package/dist/member/util.js +121 -25
  99. package/dist/member/util.js.map +1 -1
  100. package/dist/members/collection.js +10 -0
  101. package/dist/members/collection.js.map +1 -1
  102. package/dist/members/index.js +86 -5
  103. package/dist/members/index.js.map +1 -1
  104. package/dist/members/request.js +106 -38
  105. package/dist/members/request.js.map +1 -1
  106. package/dist/members/types.js +15 -0
  107. package/dist/members/types.js.map +1 -0
  108. package/dist/members/util.js +316 -233
  109. package/dist/members/util.js.map +1 -1
  110. package/dist/metrics/constants.js +3 -5
  111. package/dist/metrics/constants.js.map +1 -1
  112. package/dist/metrics/index.js +1 -468
  113. package/dist/metrics/index.js.map +1 -1
  114. package/dist/multistream/mediaRequestManager.js +238 -49
  115. package/dist/multistream/mediaRequestManager.js.map +1 -1
  116. package/dist/multistream/receiveSlot.js +49 -16
  117. package/dist/multistream/receiveSlot.js.map +1 -1
  118. package/dist/multistream/receiveSlotManager.js +52 -34
  119. package/dist/multistream/receiveSlotManager.js.map +1 -1
  120. package/dist/multistream/remoteMedia.js +44 -18
  121. package/dist/multistream/remoteMedia.js.map +1 -1
  122. package/dist/multistream/remoteMediaGroup.js +60 -3
  123. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  124. package/dist/multistream/remoteMediaManager.js +173 -59
  125. package/dist/multistream/remoteMediaManager.js.map +1 -1
  126. package/dist/networkQualityMonitor/index.js +4 -2
  127. package/dist/networkQualityMonitor/index.js.map +1 -1
  128. package/dist/reachability/index.js +72 -27
  129. package/dist/reachability/index.js.map +1 -1
  130. package/dist/reachability/request.js +12 -5
  131. package/dist/reachability/request.js.map +1 -1
  132. package/dist/reconnection-manager/index.js +196 -155
  133. package/dist/reconnection-manager/index.js.map +1 -1
  134. package/dist/recording-controller/index.js +21 -2
  135. package/dist/recording-controller/index.js.map +1 -1
  136. package/dist/recording-controller/util.js +9 -8
  137. package/dist/recording-controller/util.js.map +1 -1
  138. package/dist/roap/index.js +21 -29
  139. package/dist/roap/index.js.map +1 -1
  140. package/dist/roap/request.js +110 -89
  141. package/dist/roap/request.js.map +1 -1
  142. package/dist/roap/turnDiscovery.js +93 -36
  143. package/dist/roap/turnDiscovery.js.map +1 -1
  144. package/dist/rtcMetrics/constants.js +12 -0
  145. package/dist/rtcMetrics/constants.js.map +1 -0
  146. package/dist/rtcMetrics/index.js +117 -0
  147. package/dist/rtcMetrics/index.js.map +1 -0
  148. package/dist/statsAnalyzer/global.js +1 -93
  149. package/dist/statsAnalyzer/global.js.map +1 -1
  150. package/dist/statsAnalyzer/index.js +326 -311
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +90 -53
  153. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  154. package/dist/types/annotation/annotation.types.d.ts +42 -0
  155. package/dist/types/annotation/constants.d.ts +31 -0
  156. package/dist/types/annotation/index.d.ts +117 -0
  157. package/dist/types/breakouts/breakout.d.ts +8 -0
  158. package/dist/types/breakouts/collection.d.ts +5 -0
  159. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  160. package/dist/types/breakouts/events.d.ts +8 -0
  161. package/dist/types/breakouts/index.d.ts +5 -0
  162. package/dist/types/breakouts/request.d.ts +22 -0
  163. package/dist/types/breakouts/utils.d.ts +15 -0
  164. package/dist/types/common/browser-detection.d.ts +9 -0
  165. package/dist/types/common/collection.d.ts +48 -0
  166. package/dist/types/common/config.d.ts +2 -0
  167. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  168. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  169. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  170. package/dist/types/common/errors/media.d.ts +15 -0
  171. package/dist/types/common/errors/parameter.d.ts +15 -0
  172. package/dist/types/common/errors/password-error.d.ts +15 -0
  173. package/dist/types/common/errors/permission.d.ts +14 -0
  174. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  175. package/dist/types/common/errors/reconnection.d.ts +15 -0
  176. package/dist/types/common/errors/stats.d.ts +15 -0
  177. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  178. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  179. package/dist/types/common/events/events-scope.d.ts +17 -0
  180. package/dist/types/common/events/events.d.ts +12 -0
  181. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  182. package/dist/types/common/events/util.d.ts +2 -0
  183. package/dist/types/common/logs/logger-config.d.ts +2 -0
  184. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  185. package/dist/types/common/logs/request.d.ts +34 -0
  186. package/dist/types/common/queue.d.ts +34 -0
  187. package/dist/types/config.d.ts +72 -0
  188. package/dist/types/constants.d.ts +1020 -0
  189. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  190. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  191. package/dist/types/controls-options-manager/index.d.ts +136 -0
  192. package/dist/types/controls-options-manager/types.d.ts +43 -0
  193. package/dist/types/controls-options-manager/util.d.ts +1 -0
  194. package/dist/types/index.d.ts +7 -0
  195. package/dist/types/interpretation/collection.d.ts +5 -0
  196. package/dist/types/interpretation/index.d.ts +5 -0
  197. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  198. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  199. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  200. package/dist/types/locus-info/fullState.d.ts +2 -0
  201. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  202. package/dist/types/locus-info/index.d.ts +322 -0
  203. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  204. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  205. package/dist/types/locus-info/parser.d.ts +271 -0
  206. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  207. package/dist/types/media/index.d.ts +34 -0
  208. package/dist/types/media/properties.d.ts +93 -0
  209. package/dist/types/media/util.d.ts +2 -0
  210. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  211. package/dist/types/meeting/in-meeting-actions.d.ts +163 -0
  212. package/dist/types/meeting/index.d.ts +1482 -0
  213. package/dist/types/meeting/locusMediaRequest.d.ts +72 -0
  214. package/dist/types/meeting/muteState.d.ts +184 -0
  215. package/dist/types/meeting/request.d.ts +257 -0
  216. package/dist/types/meeting/request.type.d.ts +11 -0
  217. package/dist/types/meeting/state.d.ts +9 -0
  218. package/dist/types/meeting/util.d.ts +79 -0
  219. package/dist/types/meeting-info/collection.d.ts +20 -0
  220. package/dist/types/meeting-info/index.d.ts +62 -0
  221. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  222. package/dist/types/meeting-info/request.d.ts +22 -0
  223. package/dist/types/meeting-info/util.d.ts +2 -0
  224. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  225. package/dist/types/meetings/collection.d.ts +31 -0
  226. package/dist/types/meetings/index.d.ts +367 -0
  227. package/dist/types/meetings/meetings.types.d.ts +4 -0
  228. package/dist/types/meetings/request.d.ts +27 -0
  229. package/dist/types/meetings/util.d.ts +18 -0
  230. package/dist/types/member/index.d.ts +159 -0
  231. package/dist/types/member/types.d.ts +32 -0
  232. package/dist/types/member/util.d.ts +2 -0
  233. package/dist/types/members/collection.d.ts +29 -0
  234. package/dist/types/members/index.d.ts +353 -0
  235. package/dist/types/members/request.d.ts +114 -0
  236. package/dist/types/members/types.d.ts +24 -0
  237. package/dist/types/members/util.d.ts +210 -0
  238. package/dist/types/metrics/constants.d.ts +55 -0
  239. package/dist/types/metrics/index.d.ts +45 -0
  240. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  241. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  242. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  243. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  244. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  245. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  246. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  247. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  248. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  249. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  250. package/dist/types/reachability/index.d.ts +152 -0
  251. package/dist/types/reachability/request.d.ts +37 -0
  252. package/dist/types/reactions/constants.d.ts +3 -0
  253. package/dist/types/reactions/reactions.d.ts +4 -0
  254. package/dist/types/reactions/reactions.type.d.ts +52 -0
  255. package/dist/types/reconnection-manager/index.d.ts +126 -0
  256. package/dist/types/recording-controller/enums.d.ts +7 -0
  257. package/dist/types/recording-controller/index.d.ts +207 -0
  258. package/dist/types/recording-controller/util.d.ts +14 -0
  259. package/dist/types/roap/index.d.ts +77 -0
  260. package/dist/types/roap/request.d.ts +36 -0
  261. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  262. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  263. package/dist/types/rtcMetrics/index.d.ts +46 -0
  264. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  265. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  266. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  267. package/dist/types/transcription/index.d.ts +64 -0
  268. package/package.json +23 -20
  269. package/src/annotation/annotation.types.ts +50 -0
  270. package/src/annotation/constants.ts +36 -0
  271. package/src/annotation/index.ts +328 -0
  272. package/src/breakouts/README.md +44 -14
  273. package/src/breakouts/breakout.ts +87 -9
  274. package/src/breakouts/edit-lock-error.ts +25 -0
  275. package/src/breakouts/events.ts +56 -0
  276. package/src/breakouts/index.ts +710 -10
  277. package/src/breakouts/request.ts +55 -0
  278. package/src/breakouts/utils.ts +57 -0
  279. package/src/common/errors/webex-errors.ts +6 -2
  280. package/src/common/logs/logger-proxy.ts +1 -1
  281. package/src/common/queue.ts +22 -8
  282. package/src/config.ts +2 -7
  283. package/src/constants.ts +165 -21
  284. package/src/controls-options-manager/constants.ts +5 -0
  285. package/src/controls-options-manager/enums.ts +18 -0
  286. package/src/controls-options-manager/index.ts +278 -0
  287. package/src/controls-options-manager/types.ts +59 -0
  288. package/src/controls-options-manager/util.ts +300 -0
  289. package/src/index.ts +39 -0
  290. package/src/interpretation/README.md +60 -0
  291. package/src/interpretation/collection.ts +19 -0
  292. package/src/interpretation/index.ts +332 -0
  293. package/src/interpretation/siLanguage.ts +18 -0
  294. package/src/locus-info/controlsUtils.ts +108 -0
  295. package/src/locus-info/index.ts +383 -61
  296. package/src/locus-info/infoUtils.ts +10 -2
  297. package/src/locus-info/mediaSharesUtils.ts +48 -0
  298. package/src/locus-info/parser.ts +224 -39
  299. package/src/locus-info/selfUtils.ts +81 -5
  300. package/src/media/index.ts +87 -140
  301. package/src/media/properties.ts +49 -90
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +179 -3
  304. package/src/meeting/index.ts +2099 -2083
  305. package/src/meeting/locusMediaRequest.ts +311 -0
  306. package/src/meeting/muteState.ts +228 -132
  307. package/src/meeting/request.ts +105 -115
  308. package/src/meeting/util.ts +511 -397
  309. package/src/meeting-info/index.ts +54 -8
  310. package/src/meeting-info/meeting-info-v2.ts +148 -14
  311. package/src/meeting-info/utilv2.ts +13 -3
  312. package/src/meetings/collection.ts +20 -0
  313. package/src/meetings/index.ts +392 -84
  314. package/src/meetings/meetings.types.ts +12 -0
  315. package/src/meetings/request.ts +2 -0
  316. package/src/meetings/util.ts +103 -4
  317. package/src/member/index.ts +49 -0
  318. package/src/member/types.ts +38 -0
  319. package/src/member/util.ts +127 -25
  320. package/src/members/collection.ts +8 -0
  321. package/src/members/index.ts +107 -6
  322. package/src/members/request.ts +97 -17
  323. package/src/members/types.ts +28 -0
  324. package/src/members/util.ts +319 -240
  325. package/src/metrics/constants.ts +2 -4
  326. package/src/metrics/index.ts +1 -490
  327. package/src/multistream/mediaRequestManager.ts +289 -79
  328. package/src/multistream/receiveSlot.ts +55 -18
  329. package/src/multistream/receiveSlotManager.ts +46 -24
  330. package/src/multistream/remoteMedia.ts +27 -2
  331. package/src/multistream/remoteMediaGroup.ts +59 -0
  332. package/src/multistream/remoteMediaManager.ts +113 -32
  333. package/src/networkQualityMonitor/index.ts +6 -6
  334. package/src/reachability/index.ts +62 -15
  335. package/src/reachability/request.ts +10 -5
  336. package/src/reconnection-manager/index.ts +68 -43
  337. package/src/recording-controller/index.ts +20 -3
  338. package/src/recording-controller/util.ts +26 -9
  339. package/src/roap/index.ts +21 -30
  340. package/src/roap/request.ts +101 -95
  341. package/src/roap/turnDiscovery.ts +47 -25
  342. package/src/rtcMetrics/constants.ts +3 -0
  343. package/src/rtcMetrics/index.ts +100 -0
  344. package/src/statsAnalyzer/global.ts +1 -94
  345. package/src/statsAnalyzer/index.ts +376 -386
  346. package/src/statsAnalyzer/mqaUtil.ts +100 -99
  347. package/test/integration/spec/converged-space-meetings.js +233 -0
  348. package/test/integration/spec/journey.js +336 -259
  349. package/test/integration/spec/space-meeting.js +77 -4
  350. package/test/unit/spec/annotation/index.ts +418 -0
  351. package/test/unit/spec/breakouts/breakout.ts +142 -24
  352. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  353. package/test/unit/spec/breakouts/events.ts +89 -0
  354. package/test/unit/spec/breakouts/index.ts +1545 -48
  355. package/test/unit/spec/breakouts/request.ts +104 -0
  356. package/test/unit/spec/breakouts/utils.js +72 -0
  357. package/test/unit/spec/common/queue.js +31 -2
  358. package/test/unit/spec/controls-options-manager/index.js +287 -0
  359. package/test/unit/spec/controls-options-manager/util.js +582 -0
  360. package/test/unit/spec/fixture/locus.js +1 -0
  361. package/test/unit/spec/interpretation/collection.ts +15 -0
  362. package/test/unit/spec/interpretation/index.ts +589 -0
  363. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  364. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  365. package/test/unit/spec/locus-info/index.js +1169 -36
  366. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  367. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  368. package/test/unit/spec/locus-info/parser.js +62 -22
  369. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  370. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  371. package/test/unit/spec/media/index.ts +138 -28
  372. package/test/unit/spec/meeting/in-meeting-actions.ts +89 -3
  373. package/test/unit/spec/meeting/index.js +3573 -1663
  374. package/test/unit/spec/meeting/locusMediaRequest.ts +438 -0
  375. package/test/unit/spec/meeting/muteState.js +370 -208
  376. package/test/unit/spec/meeting/request.js +339 -44
  377. package/test/unit/spec/meeting/utils.js +456 -53
  378. package/test/unit/spec/meeting-info/index.js +181 -0
  379. package/test/unit/spec/meeting-info/meetinginfov2.js +383 -5
  380. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  381. package/test/unit/spec/meetings/collection.js +14 -0
  382. package/test/unit/spec/meetings/index.js +867 -125
  383. package/test/unit/spec/meetings/utils.js +206 -2
  384. package/test/unit/spec/member/index.js +58 -4
  385. package/test/unit/spec/member/util.js +479 -35
  386. package/test/unit/spec/members/index.js +319 -1
  387. package/test/unit/spec/members/request.js +206 -27
  388. package/test/unit/spec/members/utils.js +184 -0
  389. package/test/unit/spec/metrics/index.js +1 -50
  390. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  391. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  392. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  393. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  394. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  395. package/test/unit/spec/multistream/remoteMediaManager.ts +318 -0
  396. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  397. package/test/unit/spec/reachability/index.ts +125 -8
  398. package/test/unit/spec/reachability/request.js +66 -0
  399. package/test/unit/spec/reconnection-manager/index.js +59 -6
  400. package/test/unit/spec/recording-controller/index.js +294 -218
  401. package/test/unit/spec/recording-controller/util.js +223 -96
  402. package/test/unit/spec/roap/index.ts +26 -51
  403. package/test/unit/spec/roap/request.ts +196 -85
  404. package/test/unit/spec/roap/turnDiscovery.ts +30 -7
  405. package/test/unit/spec/rtcMetrics/index.ts +60 -0
  406. package/test/unit/spec/stats-analyzer/index.js +92 -41
  407. package/test/utils/constants.js +9 -0
  408. package/test/utils/integrationTestUtils.js +46 -0
  409. package/test/utils/testUtils.js +0 -45
  410. package/test/utils/webex-config.js +4 -0
  411. package/test/utils/webex-test-users.js +6 -3
  412. package/dist/meeting/effectsState.js +0 -262
  413. package/dist/meeting/effectsState.js.map +0 -1
  414. package/dist/metrics/config.js +0 -299
  415. package/dist/metrics/config.js.map +0 -1
  416. package/dist/multistream/multistreamMedia.js +0 -110
  417. package/dist/multistream/multistreamMedia.js.map +0 -1
  418. package/src/index.js +0 -16
  419. package/src/meeting/effectsState.ts +0 -211
  420. package/src/metrics/config.ts +0 -495
  421. package/src/multistream/multistreamMedia.ts +0 -97
  422. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -12,7 +12,13 @@ import {
12
12
  MEDIA_DEVICES,
13
13
  _UNKNOWN_,
14
14
  } from '../constants';
15
- import mqaData from '../mediaQualityMetrics/config';
15
+ import {
16
+ emptyAudioReceive,
17
+ emptyAudioTransmit,
18
+ emptyMqaInterval,
19
+ emptyVideoReceive,
20
+ emptyVideoTransmit,
21
+ } from '../mediaQualityMetrics/config';
16
22
  import LoggerProxy from '../common/logs/logger-proxy';
17
23
 
18
24
  import defaultStats from './global';
@@ -22,6 +28,7 @@ import {
22
28
  getVideoSenderMqa,
23
29
  getVideoReceiverMqa,
24
30
  } from './mqaUtil';
31
+ import {ReceiveSlot} from '../multistream/receiveSlot';
25
32
 
26
33
  export const EVENTS = {
27
34
  MEDIA_QUALITY: 'MEDIA_QUALITY',
@@ -31,6 +38,24 @@ export const EVENTS = {
31
38
  REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',
32
39
  };
33
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
+
34
59
  /**
35
60
  * Stats Analyzer class that will emit events based on detected quality
36
61
  *
@@ -44,7 +69,6 @@ export class StatsAnalyzer extends EventsScope {
44
69
  lastEmittedStartStopEvent: any;
45
70
  lastMqaDataSent: any;
46
71
  lastStatsResults: any;
47
- localMQEStats: any;
48
72
  meetingMediaStatus: any;
49
73
  mqaInterval: NodeJS.Timeout;
50
74
  mqaSentCount: any;
@@ -53,17 +77,20 @@ export class StatsAnalyzer extends EventsScope {
53
77
  statsInterval: NodeJS.Timeout;
54
78
  statsResults: any;
55
79
  statsStarted: any;
80
+ receiveSlotCallback: ReceiveSlotCallback;
56
81
 
57
82
  /**
58
83
  * Creates a new instance of StatsAnalyzer
59
84
  * @constructor
60
85
  * @public
61
86
  * @param {Object} config SDK Configuration Object
87
+ * @param {Function} receiveSlotCallback Callback used to access receive slots.
62
88
  * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
63
89
  * @param {Object} statsResults Default properties for stats
64
90
  */
65
91
  constructor(
66
92
  config: any,
93
+ receiveSlotCallback: ReceiveSlotCallback = () => undefined,
67
94
  networkQualityMonitor: object = {},
68
95
  statsResults: object = defaultStats
69
96
  ) {
@@ -75,147 +102,29 @@ export class StatsAnalyzer extends EventsScope {
75
102
  this.networkQualityMonitor = networkQualityMonitor;
76
103
  this.correlationId = config.correlationId;
77
104
  this.mqaSentCount = -1;
78
- this.lastMqaDataSent = {
79
- resolutions: {
80
- video: {send: {}, recv: {}},
81
- audio: {send: {}, recv: {}},
82
- share: {send: {}, recv: {}},
83
- },
84
- video: {send: {}, recv: {}},
85
- audio: {send: {}, recv: {}},
86
- share: {send: {}, recv: {}},
87
- };
88
- this.localMQEStats = {
89
- audio: {
90
- RX: {
91
- packetsLost: [],
92
- jitter: [],
93
- latency: [],
94
- bitRate: [],
95
- },
96
- TX: {
97
- packetsLost: [],
98
- jitter: [],
99
- latency: [],
100
- bitRate: [],
101
- },
102
- },
103
- video: {
104
- RX: {
105
- packetsLost: [],
106
- jitter: [],
107
- latency: [],
108
- bitRate: [],
109
- frameRate: [],
110
- resolutionWidth: [],
111
- resolutionHeight: [],
112
- requestedKeyFrame: [],
113
- receivedKeyFrame: [],
114
- },
115
- TX: {
116
- packetsLost: [],
117
- jitter: [],
118
- latency: [],
119
- bitRate: [],
120
- frameRate: [],
121
- resolutionWidth: [],
122
- resolutionHeight: [],
123
- requestedKeyFrame: [],
124
- receivedKeyFrame: [],
125
- },
126
- },
127
- };
128
- this.lastEmittedStartStopEvent = {
129
- audio: {
130
- local: undefined,
131
- remote: undefined,
132
- },
133
- video: {
134
- local: undefined,
135
- remote: undefined,
136
- },
137
- share: {
138
- local: undefined,
139
- remote: undefined,
140
- },
141
- };
142
- }
143
-
144
- populateResults(lastMqa) {
145
- // Audio
146
-
147
- this.localMQEStats.audio.RX.packetsLost.push(lastMqa.audioReceive[0].common.mediaHopByHopLost);
148
- this.localMQEStats.audio.RX.jitter.push(lastMqa.audioReceive[0].streams[0].common.rtpJitter);
149
- this.localMQEStats.audio.RX.latency.push(lastMqa.audioReceive[0].common.roundTripTime);
150
- this.localMQEStats.audio.RX.bitRate.push(
151
- lastMqa.audioReceive[0].streams[0].common.receivedBitrate
152
- );
153
-
154
- this.localMQEStats.audio.TX.packetsLost.push(lastMqa.audioTransmit[0].common.remoteLossRate);
155
- this.localMQEStats.audio.TX.jitter.push(lastMqa.audioTransmit[0].common.remoteJitter);
156
- this.localMQEStats.audio.TX.latency.push(lastMqa.audioTransmit[0].common.roundTripTime);
157
- this.localMQEStats.audio.TX.bitRate.push(
158
- lastMqa.audioTransmit[0].streams[0].common.transmittedBitrate
159
- );
160
-
161
- // Video
162
-
163
- this.localMQEStats.video.RX.packetsLost.push(lastMqa.videoReceive[0].common.mediaHopByHopLost);
164
- this.localMQEStats.video.RX.jitter.push(lastMqa.videoReceive[0].streams[0].common.rtpJitter);
165
- this.localMQEStats.video.RX.latency.push(
166
- lastMqa.videoReceive[0].streams[0].common.roundTripTime
167
- );
168
- this.localMQEStats.video.RX.bitRate.push(
169
- lastMqa.videoReceive[0].streams[0].common.receivedBitrate
170
- );
171
- this.localMQEStats.video.RX.frameRate.push(
172
- lastMqa.videoReceive[0].streams[0].common.receivedFrameRate
173
- );
174
- this.localMQEStats.video.RX.resolutionWidth.push(
175
- lastMqa.videoReceive[0].streams[0].receivedWidth
176
- );
177
- this.localMQEStats.video.RX.resolutionHeight.push(
178
- lastMqa.videoReceive[0].streams[0].receivedHeight
179
- );
180
- this.localMQEStats.video.RX.requestedKeyFrame.push();
181
- this.localMQEStats.video.RX.receivedKeyFrame.push();
182
-
183
- this.localMQEStats.video.TX.packetsLost.push(lastMqa.videoTransmit[0].common.remoteLossRate);
184
- this.localMQEStats.video.TX.jitter.push(lastMqa.videoTransmit[0].common.remoteJitter);
185
- this.localMQEStats.video.TX.latency.push(lastMqa.videoTransmit[0].common.roundTripTime);
186
- this.localMQEStats.video.TX.bitRate.push(
187
- lastMqa.videoTransmit[0].streams[0].common.transmittedBitrate
188
- );
189
- this.localMQEStats.video.TX.frameRate.push(
190
- lastMqa.videoTransmit[0].streams[0].common.transmittedFrameRate
191
- );
192
- this.localMQEStats.video.TX.resolutionWidth.push(
193
- lastMqa.videoTransmit[0].streams[0].transmittedWidth
194
- );
195
- this.localMQEStats.video.TX.resolutionHeight.push(
196
- lastMqa.videoTransmit[0].streams[0].transmittedHeight
197
- );
198
- this.localMQEStats.video.TX.requestedKeyFrame.push(
199
- lastMqa.videoTransmit[0].streams[0].requestedKeyFrames
200
- );
201
- this.localMQEStats.video.TX.receivedKeyFrame.push();
105
+ this.lastMqaDataSent = {};
106
+ this.lastEmittedStartStopEvent = {};
107
+ this.receiveSlotCallback = receiveSlotCallback;
202
108
  }
203
109
 
110
+ /**
111
+ * Resets cumulative stats arrays.
112
+ *
113
+ * @public
114
+ * @memberof StatsAnalyzer
115
+ * @returns {void}
116
+ */
204
117
  resetStatsResults() {
205
- this.statsResults.audio.send.meanRemoteJitter = [];
206
- this.statsResults.video.send.meanRemoteJitter = [];
207
- this.statsResults.share.send.meanRemoteJitter = [];
208
-
209
- this.statsResults.audio.recv.meanRtpJitter = [];
210
-
211
- // TODO: currently no values are present
212
- this.statsResults.video.recv.meanRtpJitter = [];
213
- this.statsResults.share.recv.meanRtpJitter = [];
118
+ Object.keys(this.statsResults).forEach((mediaType) => {
119
+ if (mediaType.includes('recv')) {
120
+ this.statsResults[mediaType].recv.meanRtpJitter = [];
121
+ }
214
122
 
215
- // Reset the roundTripTime
216
- this.statsResults.audio.send.meanRoundTripTime = [];
217
- this.statsResults.video.send.meanRoundTripTime = [];
218
- this.statsResults.share.send.meanRoundTripTime = [];
123
+ if (mediaType.includes('send')) {
124
+ this.statsResults[mediaType].send.meanRemoteJitter = [];
125
+ this.statsResults[mediaType].send.meanRoundTripTime = [];
126
+ }
127
+ });
219
128
  }
220
129
 
221
130
  /**
@@ -237,82 +146,77 @@ export class StatsAnalyzer extends EventsScope {
237
146
  * @memberof StatsAnalyzer
238
147
  * @returns {void}
239
148
  */
240
- public sendMqaData() {
241
- const audioReceiver = mqaData.intervals[0].audioReceive[0];
242
- const audioSender = mqaData.intervals[0].audioTransmit[0];
243
- const videoReceiver = mqaData.intervals[0].videoReceive[0];
244
- const videoSender = mqaData.intervals[0].videoTransmit[0];
245
- const shareSender = mqaData.intervals[0].videoTransmit[1];
246
- const shareReceiver = mqaData.intervals[0].videoReceive[1];
247
-
248
- getAudioSenderMqa({
249
- audioSender,
250
- statsResults: this.statsResults,
251
- lastMqaDataSent: this.lastMqaDataSent,
252
- });
253
- getAudioReceiverMqa({
254
- audioReceiver,
255
- statsResults: this.statsResults,
256
- lastMqaDataSent: this.lastMqaDataSent,
257
- });
149
+ sendMqaData() {
150
+ const newMqa = cloneDeep(emptyMqaInterval);
258
151
 
259
- getVideoReceiverMqa({
260
- videoReceiver,
261
- statsResults: this.statsResults,
262
- lastMqaDataSent: this.lastMqaDataSent,
263
- });
264
- getVideoSenderMqa({
265
- videoSender,
266
- statsResults: this.statsResults,
267
- lastMqaDataSent: this.lastMqaDataSent,
268
- });
269
-
270
- // Capture mqa for share scenario
152
+ Object.keys(this.statsResults).forEach((mediaType) => {
153
+ if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {
154
+ const audioSender = cloneDeep(emptyAudioTransmit);
271
155
 
272
- getVideoSenderMqa({
273
- videoSender: shareSender,
274
- statsResults: this.statsResults,
275
- lastMqaDataSent: this.lastMqaDataSent,
276
- isShareStream: true,
156
+ getAudioSenderMqa({
157
+ audioSender,
158
+ statsResults: this.statsResults,
159
+ lastMqaDataSent: this.lastMqaDataSent,
160
+ mediaType,
161
+ });
162
+ newMqa.audioTransmit.push(audioSender);
163
+ } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
164
+ const audioReceiver = cloneDeep(emptyAudioReceive);
165
+
166
+ getAudioReceiverMqa({
167
+ audioReceiver,
168
+ statsResults: this.statsResults,
169
+ lastMqaDataSent: this.lastMqaDataSent,
170
+ mediaType,
171
+ });
172
+ newMqa.audioReceive.push(audioReceiver);
173
+ } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {
174
+ const videoSender = cloneDeep(emptyVideoTransmit);
175
+
176
+ getVideoSenderMqa({
177
+ videoSender,
178
+ statsResults: this.statsResults,
179
+ lastMqaDataSent: this.lastMqaDataSent,
180
+ mediaType,
181
+ });
182
+ newMqa.videoTransmit.push(videoSender);
183
+ } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
184
+ const videoReceiver = cloneDeep(emptyVideoReceive);
185
+
186
+ getVideoReceiverMqa({
187
+ videoReceiver,
188
+ statsResults: this.statsResults,
189
+ lastMqaDataSent: this.lastMqaDataSent,
190
+ mediaType,
191
+ });
192
+ newMqa.videoReceive.push(videoReceiver);
193
+ }
277
194
  });
278
195
 
279
- getVideoReceiverMqa({
280
- videoReceiver: shareReceiver,
281
- statsResults: this.statsResults,
282
- lastMqaDataSent: this.lastMqaDataSent,
283
- isShareStream: true,
284
- });
285
- mqaData.intervals[0].intervalMetadata.peerReflexiveIP =
286
- this.statsResults.connectionType.local.ipAddress[0];
196
+ newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress[0];
287
197
 
288
198
  // Adding peripheral information
289
- mqaData.intervals[0].intervalMetadata.peripherals = [];
290
- mqaData.intervals[0].intervalMetadata.peripherals.push({
291
- information: _UNKNOWN_,
292
- name: MEDIA_DEVICES.SPEAKER,
293
- });
294
- mqaData.intervals[0].intervalMetadata.peripherals.push({
295
- information:
296
- this.statsResults[STATS.AUDIO_CORRELATE][STATS.SEND_DIRECTION].trackLabel || _UNKNOWN_,
297
- name: MEDIA_DEVICES.MICROPHONE,
298
- });
299
- mqaData.intervals[0].intervalMetadata.peripherals.push({
300
- information:
301
- this.statsResults[STATS.VIDEO_CORRELATE][STATS.SEND_DIRECTION].trackLabel || _UNKNOWN_,
302
- name: MEDIA_DEVICES.CAMERA,
303
- });
304
-
305
- // @ts-ignore
306
- mqaData.networkType = this.statsResults.connectionType.local.networkType;
199
+ newMqa.intervalMetadata.peripherals = [];
307
200
 
308
- this.mqaSentCount += 1;
201
+ newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});
202
+ if (this.statsResults['audio-send']) {
203
+ newMqa.intervalMetadata.peripherals.push({
204
+ information: this.statsResults['audio-send']?.trackLabel,
205
+ name: MEDIA_DEVICES.MICROPHONE,
206
+ });
207
+ }
208
+ if (this.statsResults['video-send']) {
209
+ newMqa.intervalMetadata.peripherals.push({
210
+ information: this.statsResults['video-send']?.trackLabel,
211
+ name: MEDIA_DEVICES.CAMERA,
212
+ });
213
+ }
309
214
 
310
- mqaData.intervals[0].intervalNumber = this.mqaSentCount;
215
+ newMqa.networkType = this.statsResults.connectionType.local.networkType;
311
216
 
312
- // DO Deep copy, for some reason it takes the reference all the time rather then old value set
313
- this.lastMqaDataSent = cloneDeep(this.statsResults);
217
+ this.mqaSentCount += 1;
314
218
 
315
- this.populateResults(mqaData.intervals[0]);
219
+ newMqa.intervalNumber = this.mqaSentCount;
316
220
 
317
221
  this.resetStatsResults();
318
222
 
@@ -323,9 +227,9 @@ export class StatsAnalyzer extends EventsScope {
323
227
  },
324
228
  EVENTS.MEDIA_QUALITY,
325
229
  {
326
- data: mqaData.intervals[0],
230
+ data: newMqa,
327
231
  // @ts-ignore
328
- networkType: mqaData.networkType,
232
+ networkType: newMqa.networkType,
329
233
  }
330
234
  );
331
235
  }
@@ -396,7 +300,6 @@ export class StatsAnalyzer extends EventsScope {
396
300
  this.mediaConnection = null;
397
301
  });
398
302
  }
399
- this.mediaConnection = null;
400
303
 
401
304
  return Promise.resolve();
402
305
  }
@@ -416,6 +319,37 @@ export class StatsAnalyzer extends EventsScope {
416
319
  return;
417
320
  }
418
321
 
322
+ // Generate empty stats results
323
+ if (!this.statsResults[type]) {
324
+ this.statsResults[type] = {};
325
+ }
326
+
327
+ if (isSender && !this.statsResults[type].send) {
328
+ this.statsResults[type].send = cloneDeep(emptySender);
329
+ } else if (!isSender && !this.statsResults[type].recv) {
330
+ this.statsResults[type].recv = cloneDeep(emptyReceiver);
331
+ }
332
+
333
+ if (!this.statsResults.resolutions[type]) {
334
+ this.statsResults.resolutions[type] = {};
335
+ }
336
+
337
+ if (isSender && !this.statsResults.resolutions[type].send) {
338
+ this.statsResults.resolutions[type].send = cloneDeep(emptySender);
339
+ } else if (!isSender && !this.statsResults.resolutions[type].recv) {
340
+ this.statsResults.resolutions[type].recv = cloneDeep(emptyReceiver);
341
+ }
342
+
343
+ if (!this.statsResults.internal[type]) {
344
+ this.statsResults.internal[type] = {};
345
+ }
346
+
347
+ if (isSender && !this.statsResults.internal[type].send) {
348
+ this.statsResults.internal[type].send = cloneDeep(emptySender);
349
+ } else if (!isSender && !this.statsResults.internal[type].recv) {
350
+ this.statsResults.internal[type].recv = cloneDeep(emptyReceiver);
351
+ }
352
+
419
353
  switch (getStatsResult.type) {
420
354
  case 'outbound-rtp':
421
355
  this.processOutboundRTPResult(getStatsResult, type);
@@ -450,23 +384,25 @@ export class StatsAnalyzer extends EventsScope {
450
384
  /**
451
385
  * Filters the get stats results for types
452
386
  * @private
453
- * @param {Array} getStatsResults
387
+ * @param {Array} statsItem
454
388
  * @param {String} type
455
389
  * @param {boolean} isSender
456
390
  * @returns {void}
457
391
  */
458
- private filterAndParseGetStatsResults(
459
- getStatsResults: Array<any>,
460
- type: string,
461
- isSender: boolean
462
- ) {
392
+ filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {
463
393
  const {types} = DEFAULT_GET_STATS_FILTER;
464
394
 
465
- getStatsResults.forEach((result) => {
395
+ statsItem.report.forEach((result) => {
466
396
  if (types.includes(result.type)) {
467
397
  this.parseGetStatsResult(result, type, isSender);
468
398
  }
469
399
  });
400
+
401
+ if (this.statsResults[type]) {
402
+ this.statsResults[type].direction = statsItem.currentDirection;
403
+ this.statsResults[type].trackLabel = statsItem.localTrackLabel;
404
+ this.statsResults[type].csi = statsItem.csi;
405
+ }
470
406
  }
471
407
 
472
408
  /**
@@ -480,7 +416,7 @@ export class StatsAnalyzer extends EventsScope {
480
416
  return;
481
417
  }
482
418
 
483
- if (type === STATS.AUDIO_CORRELATE) {
419
+ if (type.includes('audio-send')) {
484
420
  this.statsResults[type].send.audioLevel = result.audioLevel;
485
421
  this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;
486
422
  }
@@ -515,6 +451,10 @@ export class StatsAnalyzer extends EventsScope {
515
451
  // eslint-disable-next-line no-param-reassign
516
452
  if (currentValue === undefined) currentValue = 0;
517
453
 
454
+ if (!this.lastEmittedStartStopEvent[mediaType]) {
455
+ this.lastEmittedStartStopEvent[mediaType] = {};
456
+ }
457
+
518
458
  const lastEmittedEvent = isLocal
519
459
  ? this.lastEmittedStartStopEvent[mediaType].local
520
460
  : this.lastEmittedStartStopEvent[mediaType].remote;
@@ -555,21 +495,42 @@ export class StatsAnalyzer extends EventsScope {
555
495
  */
556
496
  private compareLastStatsResult() {
557
497
  if (this.lastStatsResults !== null && this.meetingMediaStatus) {
558
- // compare audio stats sent
559
- let mediaType = STATS.AUDIO_CORRELATE;
560
- let currentStats = null;
561
- let previousStats = null;
498
+ const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
499
+ Object.keys(this.statsResults)
500
+ .filter((key) => key.startsWith(keyPrefix))
501
+ .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
502
+
503
+ const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
504
+ Object.keys(this.statsResults)
505
+ .filter((key) => key.startsWith(keyPrefix))
506
+ .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
507
+
508
+ const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
509
+ Object.keys(this.statsResults)
510
+ .filter((key) => key.startsWith(keyPrefix))
511
+ .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]?.recv[value] || 0), 0);
512
+
513
+ const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
514
+ Object.keys(this.statsResults)
515
+ .filter((key) => key.startsWith(keyPrefix))
516
+ .reduce(
517
+ (prev, cur) => prev + (this.lastStatsResults.resolutions[cur]?.recv[value] || 0),
518
+ 0
519
+ );
562
520
 
563
- if (this.meetingMediaStatus.expected.sendAudio) {
564
- currentStats = this.statsResults[mediaType].send;
565
- previousStats = this.lastStatsResults[mediaType].send;
521
+ if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
522
+ // compare audio stats sent
523
+ // NOTE: relies on there being only one sender.
524
+ const currentStats = this.statsResults['audio-send'].send;
525
+ const previousStats = this.lastStatsResults['audio-send'].send;
566
526
 
567
527
  if (
568
528
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
569
529
  currentStats.totalPacketsSent === 0
570
530
  ) {
571
531
  LoggerProxy.logger.info(
572
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
532
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,
533
+ currentStats.totalPacketsSent
573
534
  );
574
535
  } else {
575
536
  if (
@@ -577,19 +538,20 @@ export class StatsAnalyzer extends EventsScope {
577
538
  currentStats.totalAudioEnergy === 0
578
539
  ) {
579
540
  LoggerProxy.logger.info(
580
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Energy present`
541
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,
542
+ currentStats.totalAudioEnergy
581
543
  );
582
544
  }
583
545
 
584
546
  if (currentStats.audioLevel === 0) {
585
547
  LoggerProxy.logger.info(
586
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} level is 0 for the user`
548
+ `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`
587
549
  );
588
550
  }
589
551
  }
590
552
 
591
553
  this.emitStartStopEvents(
592
- mediaType,
554
+ 'audio',
593
555
  previousStats.totalPacketsSent,
594
556
  currentStats.totalPacketsSent,
595
557
  true
@@ -598,45 +560,47 @@ export class StatsAnalyzer extends EventsScope {
598
560
 
599
561
  if (this.meetingMediaStatus.expected.receiveAudio) {
600
562
  // compare audio stats received
601
- currentStats = this.statsResults[mediaType].recv;
602
- previousStats = this.lastStatsResults[mediaType].recv;
563
+ const currentPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
564
+ const previousPacketsReceived = getPreviousStatsTotals(
565
+ 'audio-recv',
566
+ 'totalPacketsReceived'
567
+ );
568
+ const currentSamplesReceived = getCurrentStatsTotals('audio-recv', 'totalSamplesReceived');
569
+ const previousSamplesReceived = getPreviousStatsTotals(
570
+ 'audio-recv',
571
+ 'totalSamplesReceived'
572
+ );
603
573
 
604
- if (
605
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
606
- currentStats.totalPacketsReceived === 0
607
- ) {
574
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
608
575
  LoggerProxy.logger.info(
609
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
576
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
577
+ currentPacketsReceived
610
578
  );
611
579
  } else if (
612
- currentStats.totalSamplesReceived === previousStats.totalSamplesReceived ||
613
- currentStats.totalSamplesReceived === 0
580
+ currentSamplesReceived === previousSamplesReceived ||
581
+ currentSamplesReceived === 0
614
582
  ) {
615
583
  LoggerProxy.logger.info(
616
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} samples received`
584
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
585
+ currentSamplesReceived
617
586
  );
618
587
  }
619
588
 
620
- this.emitStartStopEvents(
621
- mediaType,
622
- previousStats.totalPacketsReceived,
623
- currentStats.totalPacketsReceived,
624
- false
625
- );
589
+ this.emitStartStopEvents('audio', previousPacketsReceived, currentPacketsReceived, false);
626
590
  }
627
591
 
628
- mediaType = STATS.VIDEO_CORRELATE;
629
- if (this.meetingMediaStatus.expected.sendVideo) {
592
+ if (this.meetingMediaStatus.expected.sendVideo && this.lastStatsResults['video-send']) {
630
593
  // compare video stats sent
631
- currentStats = this.statsResults[mediaType].send;
632
- previousStats = this.lastStatsResults[mediaType].send;
594
+ const currentStats = this.statsResults['video-send'].send;
595
+ const previousStats = this.lastStatsResults['video-send'].send;
633
596
 
634
597
  if (
635
598
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
636
599
  currentStats.totalPacketsSent === 0
637
600
  ) {
638
601
  LoggerProxy.logger.info(
639
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
602
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
603
+ currentStats.totalPacketsSent
640
604
  );
641
605
  } else {
642
606
  if (
@@ -644,95 +608,96 @@ export class StatsAnalyzer extends EventsScope {
644
608
  currentStats.framesEncoded === 0
645
609
  ) {
646
610
  LoggerProxy.logger.info(
647
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames Encoded`
611
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
612
+ currentStats.framesEncoded
648
613
  );
649
614
  }
650
615
 
651
616
  if (
652
- this.statsResults.resolutions[mediaType].send.framesSent ===
653
- this.lastStatsResults.resolutions[mediaType].send.framesSent ||
654
- this.statsResults.resolutions[mediaType].send.framesSent === 0
617
+ this.statsResults.resolutions['video-send'].send.framesSent ===
618
+ this.lastStatsResults.resolutions['video-send'].send.framesSent ||
619
+ this.statsResults.resolutions['video-send'].send.framesSent === 0
655
620
  ) {
656
621
  LoggerProxy.logger.info(
657
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent`
622
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
623
+ this.statsResults.resolutions['video-send'].send.framesSent
658
624
  );
659
625
  }
660
626
  }
661
627
 
662
- this.emitStartStopEvents(
663
- mediaType,
664
- previousStats.framesSent,
665
- currentStats.framesSent,
666
- true
667
- );
628
+ this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);
668
629
  }
669
630
 
670
631
  if (this.meetingMediaStatus.expected.receiveVideo) {
671
- // compare video stats reveived
672
-
673
- currentStats = this.statsResults[mediaType].recv;
674
- previousStats = this.lastStatsResults[mediaType].recv;
632
+ // compare video stats received
633
+ const currentPacketsReceived = getCurrentStatsTotals('video-recv', 'totalPacketsReceived');
634
+ const previousPacketsReceived = getPreviousStatsTotals(
635
+ 'video-recv',
636
+ 'totalPacketsReceived'
637
+ );
638
+ const currentFramesReceived = getCurrentResolutionsStatsTotals(
639
+ 'video-recv',
640
+ 'framesReceived'
641
+ );
642
+ const previousFramesReceived = getPreviousResolutionsStatsTotals(
643
+ 'video-recv',
644
+ 'framesReceived'
645
+ );
646
+ const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
647
+ const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
648
+ const currentFramesDropped = getCurrentResolutionsStatsTotals(
649
+ 'video-recv',
650
+ 'framesDropped'
651
+ );
652
+ const previousFramesDropped = getPreviousResolutionsStatsTotals(
653
+ 'video-recv',
654
+ 'framesDropped'
655
+ );
675
656
 
676
- if (
677
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
678
- currentStats.totalPacketsReceived === 0
679
- ) {
657
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
680
658
  LoggerProxy.logger.info(
681
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
659
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`,
660
+ currentPacketsReceived
682
661
  );
683
662
  } else {
684
- if (
685
- this.statsResults.resolutions[mediaType].recv.framesReceived ===
686
- this.lastStatsResults.resolutions[mediaType].recv.framesReceived ||
687
- this.statsResults.resolutions[mediaType].recv.framesReceived === 0
688
- ) {
663
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
689
664
  LoggerProxy.logger.info(
690
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames received`
665
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
666
+ currentFramesReceived
691
667
  );
692
668
  }
693
669
 
694
- if (
695
- this.statsResults[mediaType].recv.framesDecoded ===
696
- this.lastStatsResults[mediaType].recv.framesDecoded ||
697
- this.statsResults.resolutions[mediaType].send.framesDecoded === 0
698
- ) {
670
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
699
671
  LoggerProxy.logger.info(
700
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames decoded`
672
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
673
+ currentFramesDecoded
701
674
  );
702
675
  }
703
676
 
704
- if (
705
- this.statsResults.resolutions[mediaType].recv.framesDropped -
706
- this.lastStatsResults.resolutions[mediaType].recv.framesDropped >
707
- 10
708
- ) {
677
+ if (currentFramesDropped - previousFramesDropped > 10) {
709
678
  LoggerProxy.logger.info(
710
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} frames are getting dropped`
679
+ `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
680
+ currentFramesDropped - previousFramesDropped
711
681
  );
712
682
  }
713
683
  }
714
684
 
715
- this.emitStartStopEvents(
716
- mediaType,
717
- previousStats.framesDecoded,
718
- currentStats.framesDecoded,
719
- false
720
- );
685
+ this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);
721
686
  }
722
687
 
723
- mediaType = STATS.SHARE_CORRELATE;
724
- if (this.meetingMediaStatus.expected.sendShare) {
688
+ if (this.meetingMediaStatus.expected.sendShare && this.lastStatsResults['video-share-send']) {
725
689
  // compare share stats sent
726
690
 
727
- currentStats = this.statsResults[mediaType].send;
728
- previousStats = this.lastStatsResults[mediaType].send;
691
+ const currentStats = this.statsResults['video-share-send'].send;
692
+ const previousStats = this.lastStatsResults['video-share-send'].send;
729
693
 
730
694
  if (
731
695
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
732
696
  currentStats.totalPacketsSent === 0
733
697
  ) {
734
698
  LoggerProxy.logger.info(
735
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
699
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
700
+ currentStats.totalPacketsSent
736
701
  );
737
702
  } else {
738
703
  if (
@@ -740,61 +705,78 @@ export class StatsAnalyzer extends EventsScope {
740
705
  currentStats.framesEncoded === 0
741
706
  ) {
742
707
  LoggerProxy.logger.info(
743
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames getting encoded`
708
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
709
+ currentStats.framesEncoded
744
710
  );
745
711
  }
746
712
 
747
713
  if (
748
- this.statsResults.resolutions[mediaType].send.framesSent ===
749
- this.lastStatsResults.resolutions[mediaType].send.framesSent ||
750
- this.statsResults.resolutions[mediaType].send.framesSent === 0
714
+ this.statsResults.resolutions['video-share-send'].send.framesSent ===
715
+ this.lastStatsResults.resolutions['video-share-send'].send.framesSent ||
716
+ this.statsResults.resolutions['video-share-send'].send.framesSent === 0
751
717
  ) {
752
718
  LoggerProxy.logger.info(
753
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent`
719
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
720
+ this.statsResults.resolutions['video-share-send'].send.framesSent
754
721
  );
755
722
  }
756
723
  }
724
+ }
757
725
 
726
+ if (this.meetingMediaStatus.expected.sendShare) {
758
727
  // TODO:need to check receive share value
759
- // compare share stats reveived
760
- currentStats = this.statsResults[mediaType].recv;
761
- previousStats = this.lastStatsResults[mediaType].recv;
728
+ // compare share stats received
729
+ const currentPacketsReceived = getCurrentStatsTotals(
730
+ 'video-share-recv',
731
+ 'totalPacketsReceived'
732
+ );
733
+ const previousPacketsReceived = getPreviousStatsTotals(
734
+ 'video-share-recv',
735
+ 'totalPacketsReceived'
736
+ );
737
+ const currentFramesReceived = getCurrentResolutionsStatsTotals(
738
+ 'video-share-recv',
739
+ 'framesReceived'
740
+ );
741
+ const previousFramesReceived = getPreviousResolutionsStatsTotals(
742
+ 'video-share-recv',
743
+ 'framesReceived'
744
+ );
745
+ const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
746
+ const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
747
+ const currentFramesDropped = getCurrentResolutionsStatsTotals(
748
+ 'video-share-recv',
749
+ 'framesDropped'
750
+ );
751
+ const previousFramesDropped = getPreviousResolutionsStatsTotals(
752
+ 'video-share-recv',
753
+ 'framesDropped'
754
+ );
762
755
 
763
- if (
764
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
765
- currentStats.totalPacketsSent === 0
766
- ) {
756
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
767
757
  LoggerProxy.logger.info(
768
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
758
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
759
+ currentPacketsReceived
769
760
  );
770
761
  } else {
771
- if (
772
- this.statsResults.resolutions[mediaType].recv.framesReceived ===
773
- this.lastStatsResults.resolutions[mediaType].recv.framesReceived ||
774
- this.statsResults.resolutions[mediaType].recv.framesReceived === 0
775
- ) {
762
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
776
763
  LoggerProxy.logger.info(
777
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames received`
764
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
765
+ currentFramesReceived
778
766
  );
779
767
  }
780
768
 
781
- if (
782
- this.statsResults[mediaType].recv.framesDecoded ===
783
- this.lastStatsResults[mediaType].recv.framesDecoded ||
784
- this.statsResults.resolutions[mediaType].send.framesDecoded === 0
785
- ) {
769
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
786
770
  LoggerProxy.logger.info(
787
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames decoded`
771
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
772
+ currentFramesDecoded
788
773
  );
789
774
  }
790
775
 
791
- if (
792
- this.statsResults.resolutions[mediaType].recv.framesDropped -
793
- this.lastStatsResults.resolutions[mediaType].recv.framesDropped >
794
- 10
795
- ) {
776
+ if (currentFramesDropped - previousFramesDropped > 10) {
796
777
  LoggerProxy.logger.info(
797
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} frames are getting dropped`
778
+ `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`,
779
+ currentFramesDropped - previousFramesDropped
798
780
  );
799
781
  }
800
782
  }
@@ -832,47 +814,43 @@ export class StatsAnalyzer extends EventsScope {
832
814
  LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');
833
815
 
834
816
  return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {
835
- this.filterAndParseGetStatsResults(
836
- transceiverStats.video.sender,
837
- STATS.VIDEO_CORRELATE,
838
- true
839
- );
840
- this.filterAndParseGetStatsResults(
841
- transceiverStats.video.receiver,
842
- STATS.VIDEO_CORRELATE,
843
- false
817
+ transceiverStats.video.receivers.forEach((receiver, i) =>
818
+ this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)
844
819
  );
845
- this.filterAndParseGetStatsResults(
846
- transceiverStats.audio.sender,
847
- STATS.AUDIO_CORRELATE,
848
- true
820
+ transceiverStats.audio.receivers.forEach((receiver, i) =>
821
+ this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)
849
822
  );
850
- this.filterAndParseGetStatsResults(
851
- transceiverStats.audio.receiver,
852
- STATS.AUDIO_CORRELATE,
853
- false
823
+ transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>
824
+ this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)
854
825
  );
855
- this.filterAndParseGetStatsResults(
856
- transceiverStats.screenShareVideo.sender,
857
- STATS.SHARE_CORRELATE,
858
- true
826
+ transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>
827
+ this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)
859
828
  );
860
- this.filterAndParseGetStatsResults(
861
- transceiverStats.screenShareVideo.receiver,
862
- STATS.SHARE_CORRELATE,
863
- false
864
- );
865
-
866
- // updates the current direction of media
867
- this.statsResults[STATS.AUDIO_CORRELATE].direction = transceiverStats.audio.currentDirection;
868
- this.statsResults[STATS.VIDEO_CORRELATE].direction = transceiverStats.video.currentDirection;
869
- this.statsResults[STATS.SHARE_CORRELATE].direction =
870
- transceiverStats.screenShareVideo.currentDirection;
871
829
 
872
- this.statsResults[STATS.AUDIO_CORRELATE][STATS.SEND_DIRECTION].trackLabel =
873
- transceiverStats.audio.localTrackLabel;
874
- this.statsResults[STATS.VIDEO_CORRELATE][STATS.SEND_DIRECTION].trackLabel =
875
- transceiverStats.video.localTrackLabel;
830
+ transceiverStats.video.senders.forEach((sender, i) => {
831
+ if (i > 0) {
832
+ throw new Error('Stats Analyzer does not support multiple senders.');
833
+ }
834
+ this.filterAndParseGetStatsResults(sender, 'video-send', true);
835
+ });
836
+ transceiverStats.audio.senders.forEach((sender, i) => {
837
+ if (i > 0) {
838
+ throw new Error('Stats Analyzer does not support multiple senders.');
839
+ }
840
+ this.filterAndParseGetStatsResults(sender, 'audio-send', true);
841
+ });
842
+ transceiverStats.screenShareVideo.senders.forEach((sender, i) => {
843
+ if (i > 0) {
844
+ throw new Error('Stats Analyzer does not support multiple senders.');
845
+ }
846
+ this.filterAndParseGetStatsResults(sender, 'video-share-send', true);
847
+ });
848
+ transceiverStats.screenShareAudio.senders.forEach((sender, i) => {
849
+ if (i > 0) {
850
+ throw new Error('Stats Analyzer does not support multiple senders.');
851
+ }
852
+ this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);
853
+ });
876
854
 
877
855
  this.compareLastStatsResult();
878
856
 
@@ -890,16 +868,23 @@ export class StatsAnalyzer extends EventsScope {
890
868
  * Processes OutboundRTP stats result and stores
891
869
  * @private
892
870
  * @param {*} result
893
- * @param {*} type
871
+ * @param {*} mediaType
894
872
  * @returns {void}
895
873
  */
896
- private processOutboundRTPResult(result: any, type: any) {
897
- const mediaType = type || STATS.AUDIO_CORRELATE;
874
+ private processOutboundRTPResult(result: any, mediaType: any) {
898
875
  const sendrecvType = STATS.SEND_DIRECTION;
899
876
 
900
877
  if (result.bytesSent) {
901
878
  let kilobytes = 0;
902
879
 
880
+ if (result.frameWidth && result.frameHeight) {
881
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
882
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
883
+ this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
884
+ this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent =
885
+ result.hugeFramesSent;
886
+ }
887
+
903
888
  if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {
904
889
  this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
905
890
  }
@@ -964,15 +949,25 @@ export class StatsAnalyzer extends EventsScope {
964
949
  * Processes InboundRTP stats result and stores
965
950
  * @private
966
951
  * @param {*} result
967
- * @param {*} type
952
+ * @param {*} mediaType
968
953
  * @returns {void}
969
954
  */
970
- private processInboundRTPResult(result: any, type: any) {
971
- const mediaType = type || STATS.AUDIO_CORRELATE;
955
+ private processInboundRTPResult(result: any, mediaType: any) {
972
956
  const sendrecvType = STATS.RECEIVE_DIRECTION;
973
957
 
974
958
  if (result.bytesReceived) {
975
959
  let kilobytes = 0;
960
+ const receiveSlot = this.receiveSlotCallback(result.ssrc);
961
+ const idAndCsi = receiveSlot
962
+ ? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
963
+ : '';
964
+
965
+ if (result.frameWidth && result.frameHeight) {
966
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
967
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
968
+ this.statsResults.resolutions[mediaType][sendrecvType].framesReceived =
969
+ result.framesReceived;
970
+ }
976
971
 
977
972
  if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {
978
973
  this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =
@@ -1022,10 +1017,12 @@ export class StatsAnalyzer extends EventsScope {
1022
1017
  result.packetsReceived;
1023
1018
 
1024
1019
  if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {
1025
- LoggerProxy.logger.info(
1026
- `StatsAnalyzer:index#processInboundRTPResult --> No packets received for ${mediaType} `,
1027
- this.statsResults[mediaType][sendrecvType].packetsReceived
1028
- );
1020
+ if (receiveSlot) {
1021
+ LoggerProxy.logger.info(
1022
+ `StatsAnalyzer:index#processInboundRTPResult --> No packets received for receive slot ${idAndCsi}`,
1023
+ this.statsResults[mediaType][sendrecvType].packetsReceived
1024
+ );
1025
+ }
1029
1026
  }
1030
1027
 
1031
1028
  // Check the over all packet Lost ratio
@@ -1037,7 +1034,7 @@ export class StatsAnalyzer extends EventsScope {
1037
1034
  : 0;
1038
1035
  if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
1039
1036
  LoggerProxy.logger.info(
1040
- 'StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver ',
1037
+ `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,
1041
1038
  this.statsResults[mediaType][sendrecvType].currentPacketLossRatio
1042
1039
  );
1043
1040
  }
@@ -1181,25 +1178,17 @@ export class StatsAnalyzer extends EventsScope {
1181
1178
  if (!result || result.type !== 'track') {
1182
1179
  return;
1183
1180
  }
1184
- if (result.type !== 'track') return;
1185
1181
 
1186
1182
  const sendrecvType =
1187
1183
  result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
1188
1184
 
1189
- if (result.frameWidth && result.frameHeight) {
1190
- this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
1191
- this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
1192
- this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
1193
- this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
1194
- }
1195
-
1196
1185
  if (sendrecvType === STATS.RECEIVE_DIRECTION) {
1197
1186
  this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
1198
1187
  this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
1199
1188
  this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
1200
1189
  }
1201
1190
 
1202
- if (result.trackIdentifier && mediaType !== STATS.AUDIO_CORRELATE) {
1191
+ if (result.trackIdentifier && !mediaType.includes('audio')) {
1203
1192
  this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =
1204
1193
  result.trackIdentifier;
1205
1194
 
@@ -1225,8 +1214,9 @@ export class StatsAnalyzer extends EventsScope {
1225
1214
  * @returns {void}
1226
1215
  * @memberof StatsAnalyzer
1227
1216
  */
1228
- private compareSentAndReceived(result: any, type: any) {
1229
- if (!type) {
1217
+ compareSentAndReceived(result, type) {
1218
+ // Don't compare on transceivers without a sender.
1219
+ if (!type || !this.statsResults.internal[type].send) {
1230
1220
  return;
1231
1221
  }
1232
1222