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