@webex/plugin-meetings 3.0.0-stream-classes.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +6 -0
- package/README.md +12 -0
- package/babel.config.js +3 -0
- package/dist/annotation/constants.js +12 -20
- package/dist/annotation/constants.js.map +1 -1
- package/dist/annotation/index.js +25 -10
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +2 -3
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/collection.js +1 -2
- package/dist/breakouts/collection.js.map +1 -1
- package/dist/breakouts/edit-lock-error.js +1 -2
- package/dist/breakouts/edit-lock-error.js.map +1 -1
- package/dist/breakouts/events.js +1 -2
- package/dist/breakouts/events.js.map +1 -1
- package/dist/breakouts/index.js +13 -14
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/request.js +1 -2
- package/dist/breakouts/request.js.map +1 -1
- package/dist/breakouts/utils.js +3 -6
- package/dist/breakouts/utils.js.map +1 -1
- 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-errors.d.ts +60 -0
- package/dist/common/errors/reclaim-host-role-errors.js +154 -0
- 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/{types/common → common}/errors/webex-errors.d.ts +13 -1
- package/dist/common/errors/webex-errors.js +35 -16
- 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 +1 -2
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/{types/common → 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.js +2 -4
- package/dist/common/queue.js.map +1 -1
- package/dist/{types/config.d.ts → config.d.ts} +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/{types/constants.d.ts → constants.d.ts} +71 -15
- package/dist/constants.js +252 -371
- 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.js +7 -10
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +27 -32
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.js +1 -2
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +8 -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.js +1 -2
- package/dist/interpretation/collection.js.map +1 -1
- package/dist/interpretation/index.js +2 -3
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +2 -3
- package/dist/interpretation/siLanguage.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +12 -13
- 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/{types/locus-info → locus-info}/index.d.ts +1 -1
- package/dist/locus-info/index.js +38 -37
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +3 -4
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +16 -3
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/{types/locus-info → locus-info}/parser.d.ts +3 -2
- package/dist/locus-info/parser.js +43 -31
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +7 -6
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +15 -10
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +16 -7
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js +1 -2
- package/dist/media/util.js.map +1 -1
- package/dist/mediaQualityMetrics/config.d.ts +241 -0
- package/dist/mediaQualityMetrics/config.js +135 -339
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/{types/meeting → meeting}/in-meeting-actions.d.ts +4 -0
- package/dist/meeting/in-meeting-actions.js +18 -2
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/{types/meeting → meeting}/index.d.ts +318 -45
- package/dist/meeting/index.js +2620 -1405
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +4 -5
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +2 -4
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/{types/meeting → meeting}/request.d.ts +2 -0
- package/dist/meeting/request.js +46 -31
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/state.js +1 -2
- package/dist/meeting/state.js.map +1 -1
- package/dist/{types/meeting → meeting}/util.d.ts +17 -0
- package/dist/meeting/util.js +83 -10
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.d.ts +16 -0
- package/dist/meeting/voicea-meeting.js +169 -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/{types/meeting-info → meeting-info}/index.d.ts +7 -0
- package/dist/meeting-info/index.js +53 -27
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/{types/meeting-info → meeting-info}/meeting-info-v2.d.ts +1 -0
- package/dist/meeting-info/meeting-info-v2.js +52 -33
- 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 +8 -8
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +12 -9
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/{types/meetings → meetings}/collection.d.ts +9 -0
- package/dist/meetings/collection.js +21 -5
- package/dist/meetings/collection.js.map +1 -1
- package/dist/{types/meetings → meetings}/index.d.ts +45 -16
- package/dist/meetings/index.js +166 -74
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +2 -3
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +3 -10
- package/dist/meetings/util.js.map +1 -1
- package/dist/{types/member → member}/index.d.ts +1 -0
- package/dist/member/index.js +10 -3
- package/dist/member/index.js.map +1 -1
- package/dist/member/member.types.d.ts +11 -0
- package/dist/member/member.types.js +17 -0
- package/dist/member/member.types.js.map +1 -0
- package/dist/member/types.js +6 -8
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +12 -2
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +1 -2
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +25 -8
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +2 -3
- package/dist/members/request.js.map +1 -1
- package/dist/{types/members → members}/types.d.ts +1 -0
- package/dist/members/types.js +3 -4
- package/dist/members/types.js.map +1 -1
- package/dist/{types/members → members}/util.d.ts +6 -1
- package/dist/members/util.js +18 -8
- package/dist/members/util.js.map +1 -1
- package/dist/{types/metrics → metrics}/constants.d.ts +12 -0
- package/dist/metrics/constants.js +14 -3
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +3 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +9 -11
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +3 -5
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +7 -9
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +3 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +7 -6
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +28 -27
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +9 -6
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +1 -2
- 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 +105 -0
- package/dist/reachability/index.js +279 -436
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +14 -11
- 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.js +1 -2
- package/dist/reactions/constants.js.map +1 -1
- package/dist/reactions/reactions.js +2 -4
- package/dist/reactions/reactions.js.map +1 -1
- package/dist/reactions/reactions.type.js +6 -8
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/{types/reconnection-manager → reconnection-manager}/index.d.ts +10 -0
- package/dist/reconnection-manager/index.js +129 -106
- 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.js +43 -51
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +1 -2
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/{types/roap → roap}/index.d.ts +2 -1
- package/dist/roap/index.js +59 -28
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +14 -22
- package/dist/roap/request.js.map +1 -1
- package/dist/{types/roap → roap}/turnDiscovery.d.ts +21 -4
- package/dist/roap/turnDiscovery.js +182 -89
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +1 -2
- package/dist/rtcMetrics/constants.js.map +1 -1
- package/dist/{types/rtcMetrics → rtcMetrics}/index.d.ts +15 -1
- package/dist/rtcMetrics/index.js +72 -12
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/statsAnalyzer/global.js +1 -2
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/{types/statsAnalyzer → statsAnalyzer}/index.d.ts +28 -11
- package/dist/statsAnalyzer/index.js +371 -318
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +48 -0
- package/dist/statsAnalyzer/mqaUtil.js +295 -162
- 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/jest.config.js +3 -0
- package/package.json +44 -24
- package/process +1 -0
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/common/errors/reclaim-host-role-errors.ts +134 -0
- package/src/common/errors/webex-errors.ts +19 -2
- package/src/common/logs/request.ts +5 -1
- package/src/config.ts +3 -5
- package/src/constants.ts +77 -8
- package/src/index.ts +4 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/locus-info/index.ts +19 -14
- package/src/locus-info/mediaSharesUtils.ts +16 -0
- package/src/locus-info/parser.ts +40 -21
- package/src/media/index.ts +8 -6
- package/src/media/properties.ts +17 -2
- package/src/mediaQualityMetrics/config.ts +103 -238
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +1664 -642
- package/src/meeting/request.ts +18 -0
- package/src/meeting/util.ts +102 -1
- package/src/meeting/voicea-meeting.ts +122 -0
- package/src/meeting-info/index.ts +47 -20
- package/src/meeting-info/meeting-info-v2.ts +32 -16
- package/src/meeting-info/util.ts +12 -9
- package/src/meeting-info/utilv2.ts +25 -15
- package/src/meetings/collection.ts +13 -0
- package/src/meetings/index.ts +112 -31
- package/src/meetings/util.ts +2 -8
- package/src/member/index.ts +9 -1
- package/src/member/member.types.ts +13 -0
- package/src/member/util.ts +14 -0
- package/src/members/index.ts +29 -2
- package/src/members/types.ts +1 -0
- package/src/members/util.ts +15 -1
- package/src/metrics/constants.ts +12 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +221 -382
- package/src/reachability/request.ts +1 -1
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +87 -83
- package/src/roap/index.ts +60 -24
- package/src/roap/request.ts +4 -17
- package/src/roap/turnDiscovery.ts +112 -39
- package/src/rtcMetrics/index.ts +71 -5
- package/src/statsAnalyzer/index.ts +430 -427
- package/src/statsAnalyzer/mqaUtil.ts +317 -168
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/journey.js +12 -12
- package/test/integration/spec/space-meeting.js +1 -1
- package/test/unit/spec/breakouts/breakout.ts +2 -1
- package/test/unit/spec/breakouts/index.ts +7 -4
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/locus-info/index.js +88 -12
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +10 -0
- package/test/unit/spec/locus-info/parser.js +54 -13
- package/test/unit/spec/locus-info/selfUtils.js +1 -1
- package/test/unit/spec/media/index.ts +25 -4
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +4388 -1382
- package/test/unit/spec/meeting/request.js +63 -12
- package/test/unit/spec/meeting/utils.js +145 -10
- package/test/unit/spec/meeting/voicea-meeting.ts +266 -0
- package/test/unit/spec/meeting-info/index.js +180 -61
- package/test/unit/spec/meeting-info/meetinginfov2.js +216 -68
- package/test/unit/spec/meetings/collection.js +12 -0
- package/test/unit/spec/meetings/index.js +674 -193
- package/test/unit/spec/meetings/utils.js +35 -12
- package/test/unit/spec/member/index.js +8 -7
- package/test/unit/spec/member/util.js +32 -0
- package/test/unit/spec/members/index.js +130 -17
- package/test/unit/spec/members/utils.js +26 -0
- package/test/unit/spec/metrics/index.js +1 -2
- package/test/unit/spec/multistream/mediaRequestManager.ts +1 -0
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +505 -135
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +74 -17
- package/test/unit/spec/recording-controller/index.js +0 -1
- package/test/unit/spec/roap/index.ts +181 -61
- package/test/unit/spec/roap/request.ts +27 -3
- package/test/unit/spec/roap/turnDiscovery.ts +363 -102
- package/test/unit/spec/rtcMetrics/index.ts +57 -3
- package/test/unit/spec/stats-analyzer/index.js +1225 -12
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/webex-test-users.js +12 -4
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -365
- package/dist/types/reachability/index.d.ts +0 -152
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -24
- /package/dist/{types/annotation → annotation}/annotation.types.d.ts +0 -0
- /package/dist/{types/annotation → annotation}/constants.d.ts +0 -0
- /package/dist/{types/annotation → annotation}/index.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/breakout.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/collection.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/edit-lock-error.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/events.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/index.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/request.d.ts +0 -0
- /package/dist/{types/breakouts → breakouts}/utils.d.ts +0 -0
- /package/dist/{types/common → common}/browser-detection.d.ts +0 -0
- /package/dist/{types/common → common}/collection.d.ts +0 -0
- /package/dist/{types/common → common}/config.d.ts +0 -0
- /package/dist/{types/common → common}/errors/captcha-error.d.ts +0 -0
- /package/dist/{types/common → common}/errors/intent-to-join.d.ts +0 -0
- /package/dist/{types/common → common}/errors/join-meeting.d.ts +0 -0
- /package/dist/{types/common → common}/errors/media.d.ts +0 -0
- /package/dist/{types/common → common}/errors/parameter.d.ts +0 -0
- /package/dist/{types/common → common}/errors/password-error.d.ts +0 -0
- /package/dist/{types/common → common}/errors/permission.d.ts +0 -0
- /package/dist/{types/common → common}/errors/reconnection-in-progress.d.ts +0 -0
- /package/dist/{types/common → common}/errors/reconnection.d.ts +0 -0
- /package/dist/{types/common → common}/errors/stats.d.ts +0 -0
- /package/dist/{types/common → common}/errors/webex-meetings-error.d.ts +0 -0
- /package/dist/{types/common → common}/events/events-scope.d.ts +0 -0
- /package/dist/{types/common → common}/events/events.d.ts +0 -0
- /package/dist/{types/common → common}/events/trigger-proxy.d.ts +0 -0
- /package/dist/{types/common → common}/events/util.d.ts +0 -0
- /package/dist/{types/common → common}/logs/logger-config.d.ts +0 -0
- /package/dist/{types/common → common}/logs/logger-proxy.d.ts +0 -0
- /package/dist/{types/common → common}/queue.d.ts +0 -0
- /package/dist/{types/controls-options-manager → controls-options-manager}/constants.d.ts +0 -0
- /package/dist/{types/controls-options-manager → controls-options-manager}/enums.d.ts +0 -0
- /package/dist/{types/controls-options-manager → controls-options-manager}/index.d.ts +0 -0
- /package/dist/{types/controls-options-manager → controls-options-manager}/types.d.ts +0 -0
- /package/dist/{types/controls-options-manager → controls-options-manager}/util.d.ts +0 -0
- /package/dist/{types/index.d.ts → index.d.ts} +0 -0
- /package/dist/{types/interpretation → interpretation}/collection.d.ts +0 -0
- /package/dist/{types/interpretation → interpretation}/index.d.ts +0 -0
- /package/dist/{types/interpretation → interpretation}/siLanguage.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/controlsUtils.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/embeddedAppsUtils.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/fullState.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/hostUtils.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/infoUtils.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/mediaSharesUtils.d.ts +0 -0
- /package/dist/{types/locus-info → locus-info}/selfUtils.d.ts +0 -0
- /package/dist/{types/media → media}/index.d.ts +0 -0
- /package/dist/{types/media → media}/properties.d.ts +0 -0
- /package/dist/{types/media → media}/util.d.ts +0 -0
- /package/dist/{types/meeting → meeting}/locusMediaRequest.d.ts +0 -0
- /package/dist/{types/meeting → meeting}/muteState.d.ts +0 -0
- /package/dist/{types/meeting → meeting}/request.type.d.ts +0 -0
- /package/dist/{types/meeting → meeting}/state.d.ts +0 -0
- /package/dist/{types/meeting-info → meeting-info}/collection.d.ts +0 -0
- /package/dist/{types/meeting-info → meeting-info}/request.d.ts +0 -0
- /package/dist/{types/meeting-info → meeting-info}/util.d.ts +0 -0
- /package/dist/{types/meeting-info → meeting-info}/utilv2.d.ts +0 -0
- /package/dist/{types/meetings → meetings}/meetings.types.d.ts +0 -0
- /package/dist/{types/meetings → meetings}/request.d.ts +0 -0
- /package/dist/{types/meetings → meetings}/util.d.ts +0 -0
- /package/dist/{types/member → member}/types.d.ts +0 -0
- /package/dist/{types/member → member}/util.d.ts +0 -0
- /package/dist/{types/members → members}/collection.d.ts +0 -0
- /package/dist/{types/members → members}/index.d.ts +0 -0
- /package/dist/{types/members → members}/request.d.ts +0 -0
- /package/dist/{types/metrics → metrics}/index.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/mediaRequestManager.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/receiveSlot.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/receiveSlotManager.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/remoteMedia.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/remoteMediaGroup.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/remoteMediaManager.d.ts +0 -0
- /package/dist/{types/multistream → multistream}/sendSlotManager.d.ts +0 -0
- /package/dist/{types/networkQualityMonitor → networkQualityMonitor}/index.d.ts +0 -0
- /package/dist/{types/personal-meeting-room → personal-meeting-room}/index.d.ts +0 -0
- /package/dist/{types/personal-meeting-room → personal-meeting-room}/request.d.ts +0 -0
- /package/dist/{types/personal-meeting-room → personal-meeting-room}/util.d.ts +0 -0
- /package/dist/{types/reachability → reachability}/request.d.ts +0 -0
- /package/dist/{types/reactions → reactions}/constants.d.ts +0 -0
- /package/dist/{types/reactions → reactions}/reactions.d.ts +0 -0
- /package/dist/{types/reactions → reactions}/reactions.type.d.ts +0 -0
- /package/dist/{types/recording-controller → recording-controller}/enums.d.ts +0 -0
- /package/dist/{types/recording-controller → recording-controller}/index.d.ts +0 -0
- /package/dist/{types/recording-controller → recording-controller}/util.d.ts +0 -0
- /package/dist/{types/roap → roap}/request.d.ts +0 -0
- /package/dist/{types/rtcMetrics → rtcMetrics}/constants.d.ts +0 -0
- /package/dist/{types/statsAnalyzer → statsAnalyzer}/global.d.ts +0 -0
- /package/dist/{types/transcription → transcription}/index.d.ts +0 -0
- /package/test/unit/spec/locus-info/{selfConstant.js → lib/selfConstant.js} +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* eslint-disable prefer-destructuring */
|
|
2
2
|
|
|
3
|
-
import {cloneDeep} from 'lodash';
|
|
3
|
+
import {cloneDeep, isEmpty} from 'lodash';
|
|
4
4
|
import {ConnectionState} from '@webex/internal-media-core';
|
|
5
5
|
|
|
6
6
|
import EventsScope from '../common/events/events-scope';
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_GET_STATS_FILTER,
|
|
9
9
|
STATS,
|
|
10
|
-
|
|
10
|
+
MQA_INTERVAL,
|
|
11
11
|
NETWORK_TYPE,
|
|
12
12
|
MEDIA_DEVICES,
|
|
13
13
|
_UNKNOWN_,
|
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
emptyMqaInterval,
|
|
19
19
|
emptyVideoReceive,
|
|
20
20
|
emptyVideoTransmit,
|
|
21
|
+
emptyAudioReceiveStream,
|
|
22
|
+
emptyAudioTransmitStream,
|
|
23
|
+
emptyVideoReceiveStream,
|
|
24
|
+
emptyVideoTransmitStream,
|
|
21
25
|
} from '../mediaQualityMetrics/config';
|
|
22
26
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
23
27
|
|
|
@@ -27,6 +31,10 @@ import {
|
|
|
27
31
|
getAudioReceiverMqa,
|
|
28
32
|
getVideoSenderMqa,
|
|
29
33
|
getVideoReceiverMqa,
|
|
34
|
+
getAudioSenderStreamMqa,
|
|
35
|
+
getAudioReceiverStreamMqa,
|
|
36
|
+
getVideoSenderStreamMqa,
|
|
37
|
+
getVideoReceiverStreamMqa,
|
|
30
38
|
} from './mqaUtil';
|
|
31
39
|
import {ReceiveSlot} from '../multistream/receiveSlot';
|
|
32
40
|
|
|
@@ -55,7 +63,10 @@ const emptyReceiver = {
|
|
|
55
63
|
};
|
|
56
64
|
|
|
57
65
|
type ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;
|
|
58
|
-
|
|
66
|
+
type MediaStatus = {
|
|
67
|
+
actual?: any;
|
|
68
|
+
expected?: any;
|
|
69
|
+
};
|
|
59
70
|
/**
|
|
60
71
|
* Stats Analyzer class that will emit events based on detected quality
|
|
61
72
|
*
|
|
@@ -77,6 +88,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
77
88
|
statsInterval: NodeJS.Timeout;
|
|
78
89
|
statsResults: any;
|
|
79
90
|
statsStarted: any;
|
|
91
|
+
successfulCandidatePair: any;
|
|
92
|
+
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
|
|
80
93
|
receiveSlotCallback: ReceiveSlotCallback;
|
|
81
94
|
|
|
82
95
|
/**
|
|
@@ -105,6 +118,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
105
118
|
this.lastMqaDataSent = {};
|
|
106
119
|
this.lastEmittedStartStopEvent = {};
|
|
107
120
|
this.receiveSlotCallback = receiveSlotCallback;
|
|
121
|
+
this.successfulCandidatePair = {};
|
|
122
|
+
this.localIpAddress = '';
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
/**
|
|
@@ -135,8 +150,17 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
135
150
|
* @memberof StatsAnalyzer
|
|
136
151
|
* @returns {void}
|
|
137
152
|
*/
|
|
138
|
-
public updateMediaStatus(status:
|
|
139
|
-
this.meetingMediaStatus =
|
|
153
|
+
public updateMediaStatus(status: MediaStatus) {
|
|
154
|
+
this.meetingMediaStatus = {
|
|
155
|
+
actual: {
|
|
156
|
+
...this.meetingMediaStatus?.actual,
|
|
157
|
+
...status?.actual,
|
|
158
|
+
},
|
|
159
|
+
expected: {
|
|
160
|
+
...this.meetingMediaStatus?.expected,
|
|
161
|
+
...status?.expected,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
140
164
|
}
|
|
141
165
|
|
|
142
166
|
/**
|
|
@@ -149,65 +173,209 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
149
173
|
sendMqaData() {
|
|
150
174
|
const newMqa = cloneDeep(emptyMqaInterval);
|
|
151
175
|
|
|
176
|
+
// Fill in empty stats items for lastMqaDataSent
|
|
152
177
|
Object.keys(this.statsResults).forEach((mediaType) => {
|
|
153
|
-
if (
|
|
154
|
-
|
|
178
|
+
if (!this.lastMqaDataSent[mediaType]) {
|
|
179
|
+
this.lastMqaDataSent[mediaType] = {};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
|
|
183
|
+
this.lastMqaDataSent[mediaType].send = {};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
|
|
187
|
+
this.lastMqaDataSent[mediaType].recv = {};
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Create stats the first level, totals for senders and receivers
|
|
192
|
+
const audioSender = cloneDeep(emptyAudioTransmit);
|
|
193
|
+
const audioShareSender = cloneDeep(emptyAudioTransmit);
|
|
194
|
+
const audioReceiver = cloneDeep(emptyAudioReceive);
|
|
195
|
+
const audioShareReceiver = cloneDeep(emptyAudioReceive);
|
|
196
|
+
const videoSender = cloneDeep(emptyVideoTransmit);
|
|
197
|
+
const videoShareSender = cloneDeep(emptyVideoTransmit);
|
|
198
|
+
const videoReceiver = cloneDeep(emptyVideoReceive);
|
|
199
|
+
const videoShareReceiver = cloneDeep(emptyVideoReceive);
|
|
200
|
+
|
|
201
|
+
getAudioSenderMqa({
|
|
202
|
+
audioSender,
|
|
203
|
+
statsResults: this.statsResults,
|
|
204
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
205
|
+
baseMediaType: 'audio-send',
|
|
206
|
+
});
|
|
207
|
+
newMqa.audioTransmit.push(audioSender);
|
|
208
|
+
|
|
209
|
+
getAudioSenderMqa({
|
|
210
|
+
audioSender: audioShareSender,
|
|
211
|
+
statsResults: this.statsResults,
|
|
212
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
213
|
+
baseMediaType: 'audio-share-send',
|
|
214
|
+
});
|
|
215
|
+
newMqa.audioTransmit.push(audioShareSender);
|
|
216
|
+
|
|
217
|
+
getAudioReceiverMqa({
|
|
218
|
+
audioReceiver,
|
|
219
|
+
statsResults: this.statsResults,
|
|
220
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
221
|
+
baseMediaType: 'audio-recv',
|
|
222
|
+
});
|
|
223
|
+
newMqa.audioReceive.push(audioReceiver);
|
|
224
|
+
|
|
225
|
+
getAudioReceiverMqa({
|
|
226
|
+
audioReceiver: audioShareReceiver,
|
|
227
|
+
statsResults: this.statsResults,
|
|
228
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
229
|
+
baseMediaType: 'audio-share-recv',
|
|
230
|
+
});
|
|
231
|
+
newMqa.audioReceive.push(audioShareReceiver);
|
|
232
|
+
|
|
233
|
+
getVideoSenderMqa({
|
|
234
|
+
videoSender,
|
|
235
|
+
statsResults: this.statsResults,
|
|
236
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
237
|
+
baseMediaType: 'video-send',
|
|
238
|
+
});
|
|
239
|
+
newMqa.videoTransmit.push(videoSender);
|
|
240
|
+
|
|
241
|
+
getVideoSenderMqa({
|
|
242
|
+
videoSender: videoShareSender,
|
|
243
|
+
statsResults: this.statsResults,
|
|
244
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
245
|
+
baseMediaType: 'video-share-send',
|
|
246
|
+
});
|
|
247
|
+
newMqa.videoTransmit.push(videoShareSender);
|
|
248
|
+
|
|
249
|
+
getVideoReceiverMqa({
|
|
250
|
+
videoReceiver,
|
|
251
|
+
statsResults: this.statsResults,
|
|
252
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
253
|
+
baseMediaType: 'video-recv',
|
|
254
|
+
});
|
|
255
|
+
newMqa.videoReceive.push(videoReceiver);
|
|
256
|
+
|
|
257
|
+
getVideoReceiverMqa({
|
|
258
|
+
videoReceiver: videoShareReceiver,
|
|
259
|
+
statsResults: this.statsResults,
|
|
260
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
261
|
+
baseMediaType: 'video-share-recv',
|
|
262
|
+
});
|
|
263
|
+
newMqa.videoReceive.push(videoShareReceiver);
|
|
264
|
+
|
|
265
|
+
// Add stats for individual streams
|
|
266
|
+
Object.keys(this.statsResults).forEach((mediaType) => {
|
|
267
|
+
if (mediaType.includes('audio-send')) {
|
|
268
|
+
const audioSenderStream = cloneDeep(emptyAudioTransmitStream);
|
|
269
|
+
|
|
270
|
+
getAudioSenderStreamMqa({
|
|
271
|
+
audioSenderStream,
|
|
272
|
+
statsResults: this.statsResults,
|
|
273
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
274
|
+
mediaType,
|
|
275
|
+
});
|
|
276
|
+
newMqa.audioTransmit[0].streams.push(audioSenderStream);
|
|
277
|
+
|
|
278
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
279
|
+
} else if (mediaType.includes('audio-share-send')) {
|
|
280
|
+
const audioSenderStream = cloneDeep(emptyAudioTransmitStream);
|
|
281
|
+
|
|
282
|
+
getAudioSenderStreamMqa({
|
|
283
|
+
audioSenderStream,
|
|
284
|
+
statsResults: this.statsResults,
|
|
285
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
286
|
+
mediaType,
|
|
287
|
+
});
|
|
288
|
+
newMqa.audioTransmit[1].streams.push(audioSenderStream);
|
|
289
|
+
|
|
290
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
291
|
+
} else if (mediaType.includes('audio-recv')) {
|
|
292
|
+
const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);
|
|
155
293
|
|
|
156
|
-
|
|
157
|
-
|
|
294
|
+
getAudioReceiverStreamMqa({
|
|
295
|
+
audioReceiverStream,
|
|
158
296
|
statsResults: this.statsResults,
|
|
159
297
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
160
298
|
mediaType,
|
|
161
299
|
});
|
|
162
|
-
newMqa.
|
|
163
|
-
} else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
|
|
164
|
-
const audioReceiver = cloneDeep(emptyAudioReceive);
|
|
300
|
+
newMqa.audioReceive[0].streams.push(audioReceiverStream);
|
|
165
301
|
|
|
166
|
-
|
|
167
|
-
|
|
302
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
303
|
+
} else if (mediaType.includes('audio-share-recv')) {
|
|
304
|
+
const audioReceiverStream = cloneDeep(emptyAudioReceiveStream);
|
|
305
|
+
|
|
306
|
+
getAudioReceiverStreamMqa({
|
|
307
|
+
audioReceiverStream,
|
|
168
308
|
statsResults: this.statsResults,
|
|
169
309
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
170
310
|
mediaType,
|
|
171
311
|
});
|
|
172
|
-
newMqa.audioReceive.push(
|
|
173
|
-
|
|
174
|
-
|
|
312
|
+
newMqa.audioReceive[1].streams.push(audioReceiverStream);
|
|
313
|
+
|
|
314
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
315
|
+
} else if (mediaType.includes('video-send')) {
|
|
316
|
+
const videoSenderStream = cloneDeep(emptyVideoTransmitStream);
|
|
175
317
|
|
|
176
|
-
|
|
177
|
-
|
|
318
|
+
getVideoSenderStreamMqa({
|
|
319
|
+
videoSenderStream,
|
|
178
320
|
statsResults: this.statsResults,
|
|
179
321
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
180
322
|
mediaType,
|
|
181
323
|
});
|
|
182
|
-
newMqa.videoTransmit.push(
|
|
183
|
-
} else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
|
|
184
|
-
const videoReceiver = cloneDeep(emptyVideoReceive);
|
|
324
|
+
newMqa.videoTransmit[0].streams.push(videoSenderStream);
|
|
185
325
|
|
|
186
|
-
|
|
187
|
-
|
|
326
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
327
|
+
} else if (mediaType.includes('video-share-send')) {
|
|
328
|
+
const videoSenderStream = cloneDeep(emptyVideoTransmitStream);
|
|
329
|
+
|
|
330
|
+
getVideoSenderStreamMqa({
|
|
331
|
+
videoSenderStream,
|
|
188
332
|
statsResults: this.statsResults,
|
|
189
333
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
190
334
|
mediaType,
|
|
191
335
|
});
|
|
192
|
-
newMqa.
|
|
336
|
+
newMqa.videoTransmit[1].streams.push(videoSenderStream);
|
|
337
|
+
|
|
338
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
339
|
+
} else if (mediaType.includes('video-recv')) {
|
|
340
|
+
const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);
|
|
341
|
+
|
|
342
|
+
getVideoReceiverStreamMqa({
|
|
343
|
+
videoReceiverStream,
|
|
344
|
+
statsResults: this.statsResults,
|
|
345
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
346
|
+
mediaType,
|
|
347
|
+
});
|
|
348
|
+
newMqa.videoReceive[0].streams.push(videoReceiverStream);
|
|
349
|
+
|
|
350
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
351
|
+
} else if (mediaType.includes('video-share-recv')) {
|
|
352
|
+
const videoReceiverStream = cloneDeep(emptyVideoReceiveStream);
|
|
353
|
+
|
|
354
|
+
getVideoReceiverStreamMqa({
|
|
355
|
+
videoReceiverStream,
|
|
356
|
+
statsResults: this.statsResults,
|
|
357
|
+
lastMqaDataSent: this.lastMqaDataSent,
|
|
358
|
+
mediaType,
|
|
359
|
+
});
|
|
360
|
+
newMqa.videoReceive[1].streams.push(videoReceiverStream);
|
|
361
|
+
|
|
362
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
193
363
|
}
|
|
194
364
|
});
|
|
195
365
|
|
|
196
|
-
newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress
|
|
366
|
+
newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
|
|
197
367
|
|
|
198
368
|
// Adding peripheral information
|
|
199
|
-
newMqa.intervalMetadata.peripherals = [];
|
|
200
|
-
|
|
201
369
|
newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});
|
|
202
370
|
if (this.statsResults['audio-send']) {
|
|
203
371
|
newMqa.intervalMetadata.peripherals.push({
|
|
204
|
-
information: this.statsResults['audio-send']
|
|
372
|
+
information: this.statsResults['audio-send'].trackLabel || _UNKNOWN_,
|
|
205
373
|
name: MEDIA_DEVICES.MICROPHONE,
|
|
206
374
|
});
|
|
207
375
|
}
|
|
208
376
|
if (this.statsResults['video-send']) {
|
|
209
377
|
newMqa.intervalMetadata.peripherals.push({
|
|
210
|
-
information: this.statsResults['video-send']
|
|
378
|
+
information: this.statsResults['video-send'].trackLabel || _UNKNOWN_,
|
|
211
379
|
name: MEDIA_DEVICES.CAMERA,
|
|
212
380
|
});
|
|
213
381
|
}
|
|
@@ -246,6 +414,16 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
246
414
|
this.mediaConnection = mediaConnection;
|
|
247
415
|
}
|
|
248
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Returns the local IP address for diagnostics.
|
|
419
|
+
* this is the local IP of the interface used for the current media connection
|
|
420
|
+
* a host can have many local Ip Addresses
|
|
421
|
+
* @returns {string | undefined} The local IP address.
|
|
422
|
+
*/
|
|
423
|
+
getLocalIpAddress(): string {
|
|
424
|
+
return this.localIpAddress;
|
|
425
|
+
}
|
|
426
|
+
|
|
249
427
|
/**
|
|
250
428
|
* Starts the stats analyzer on interval
|
|
251
429
|
*
|
|
@@ -267,7 +445,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
267
445
|
this.sendMqaData();
|
|
268
446
|
this.mqaInterval = setInterval(() => {
|
|
269
447
|
this.sendMqaData();
|
|
270
|
-
},
|
|
448
|
+
}, MQA_INTERVAL);
|
|
271
449
|
});
|
|
272
450
|
}
|
|
273
451
|
|
|
@@ -330,26 +508,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
330
508
|
this.statsResults[type].recv = cloneDeep(emptyReceiver);
|
|
331
509
|
}
|
|
332
510
|
|
|
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
|
-
|
|
353
511
|
switch (getStatsResult.type) {
|
|
354
512
|
case 'outbound-rtp':
|
|
355
513
|
this.processOutboundRTPResult(getStatsResult, type);
|
|
@@ -357,13 +515,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
357
515
|
case 'inbound-rtp':
|
|
358
516
|
this.processInboundRTPResult(getStatsResult, type);
|
|
359
517
|
break;
|
|
360
|
-
case 'track':
|
|
361
|
-
this.processTrackResult(getStatsResult, type);
|
|
362
|
-
break;
|
|
363
518
|
case 'remote-inbound-rtp':
|
|
364
519
|
case 'remote-outbound-rtp':
|
|
365
|
-
|
|
366
|
-
this.compareSentAndReceived(getStatsResult, type, isSender);
|
|
520
|
+
this.compareSentAndReceived(getStatsResult, type);
|
|
367
521
|
break;
|
|
368
522
|
case 'remotecandidate':
|
|
369
523
|
case 'remote-candidate':
|
|
@@ -373,7 +527,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
373
527
|
this.parseCandidate(getStatsResult, type, isSender, false);
|
|
374
528
|
break;
|
|
375
529
|
case 'media-source':
|
|
376
|
-
// @ts-ignore
|
|
377
530
|
this.parseAudioSource(getStatsResult, type);
|
|
378
531
|
break;
|
|
379
532
|
default:
|
|
@@ -392,6 +545,13 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
392
545
|
filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {
|
|
393
546
|
const {types} = DEFAULT_GET_STATS_FILTER;
|
|
394
547
|
|
|
548
|
+
// get the successful candidate pair before parsing stats.
|
|
549
|
+
statsItem.report.forEach((report) => {
|
|
550
|
+
if (report.type === 'candidate-pair' && report.state === 'succeeded') {
|
|
551
|
+
this.successfulCandidatePair = report;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
|
|
395
555
|
statsItem.report.forEach((result) => {
|
|
396
556
|
if (types.includes(result.type)) {
|
|
397
557
|
this.parseGetStatsResult(result, type, isSender);
|
|
@@ -402,6 +562,12 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
402
562
|
this.statsResults[type].direction = statsItem.currentDirection;
|
|
403
563
|
this.statsResults[type].trackLabel = statsItem.localTrackLabel;
|
|
404
564
|
this.statsResults[type].csi = statsItem.csi;
|
|
565
|
+
this.extractAndSetLocalIpAddressInfoForDiagnostics(
|
|
566
|
+
this.successfulCandidatePair?.localCandidateId,
|
|
567
|
+
this.statsResults?.candidates
|
|
568
|
+
);
|
|
569
|
+
// reset the successful candidate pair.
|
|
570
|
+
this.successfulCandidatePair = {};
|
|
405
571
|
}
|
|
406
572
|
}
|
|
407
573
|
|
|
@@ -505,27 +671,16 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
505
671
|
.filter((key) => key.startsWith(keyPrefix))
|
|
506
672
|
.reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
|
|
507
673
|
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
);
|
|
520
|
-
|
|
521
|
-
if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
|
|
674
|
+
// Audio Transmit
|
|
675
|
+
if (this.lastStatsResults['audio-send']) {
|
|
522
676
|
// compare audio stats sent
|
|
523
677
|
// NOTE: relies on there being only one sender.
|
|
524
678
|
const currentStats = this.statsResults['audio-send'].send;
|
|
525
679
|
const previousStats = this.lastStatsResults['audio-send'].send;
|
|
526
680
|
|
|
527
681
|
if (
|
|
528
|
-
|
|
682
|
+
(this.meetingMediaStatus.expected.sendAudio &&
|
|
683
|
+
currentStats.totalPacketsSent === previousStats.totalPacketsSent) ||
|
|
529
684
|
currentStats.totalPacketsSent === 0
|
|
530
685
|
) {
|
|
531
686
|
LoggerProxy.logger.info(
|
|
@@ -534,7 +689,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
534
689
|
);
|
|
535
690
|
} else {
|
|
536
691
|
if (
|
|
537
|
-
|
|
692
|
+
(this.meetingMediaStatus.expected.sendAudio &&
|
|
693
|
+
currentStats.totalAudioEnergy === previousStats.totalAudioEnergy) ||
|
|
538
694
|
currentStats.totalAudioEnergy === 0
|
|
539
695
|
) {
|
|
540
696
|
LoggerProxy.logger.info(
|
|
@@ -543,7 +699,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
543
699
|
);
|
|
544
700
|
}
|
|
545
701
|
|
|
546
|
-
if (currentStats.audioLevel === 0) {
|
|
702
|
+
if (this.meetingMediaStatus.expected.sendAudio && currentStats.audioLevel === 0) {
|
|
547
703
|
LoggerProxy.logger.info(
|
|
548
704
|
`StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`
|
|
549
705
|
);
|
|
@@ -558,45 +714,33 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
558
714
|
);
|
|
559
715
|
}
|
|
560
716
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
'audio-recv',
|
|
571
|
-
'totalSamplesReceived'
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
|
|
575
|
-
LoggerProxy.logger.info(
|
|
576
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
|
|
577
|
-
currentPacketsReceived
|
|
578
|
-
);
|
|
579
|
-
} else if (
|
|
580
|
-
currentSamplesReceived === previousSamplesReceived ||
|
|
581
|
-
currentSamplesReceived === 0
|
|
582
|
-
) {
|
|
583
|
-
LoggerProxy.logger.info(
|
|
584
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
|
|
585
|
-
currentSamplesReceived
|
|
586
|
-
);
|
|
587
|
-
}
|
|
717
|
+
// Audio Receive
|
|
718
|
+
const currentAudioPacketsReceived = getCurrentStatsTotals(
|
|
719
|
+
'audio-recv',
|
|
720
|
+
'totalPacketsReceived'
|
|
721
|
+
);
|
|
722
|
+
const previousAudioPacketsReceived = getPreviousStatsTotals(
|
|
723
|
+
'audio-recv',
|
|
724
|
+
'totalPacketsReceived'
|
|
725
|
+
);
|
|
588
726
|
|
|
589
|
-
|
|
590
|
-
|
|
727
|
+
this.emitStartStopEvents(
|
|
728
|
+
'audio',
|
|
729
|
+
previousAudioPacketsReceived,
|
|
730
|
+
currentAudioPacketsReceived,
|
|
731
|
+
false
|
|
732
|
+
);
|
|
591
733
|
|
|
592
|
-
|
|
734
|
+
// Video Transmit
|
|
735
|
+
if (this.lastStatsResults['video-send']) {
|
|
593
736
|
// compare video stats sent
|
|
594
737
|
const currentStats = this.statsResults['video-send'].send;
|
|
595
738
|
const previousStats = this.lastStatsResults['video-send'].send;
|
|
596
739
|
|
|
597
740
|
if (
|
|
598
|
-
|
|
599
|
-
currentStats.totalPacketsSent ===
|
|
741
|
+
this.meetingMediaStatus.expected.sendVideo &&
|
|
742
|
+
(currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
|
|
743
|
+
currentStats.totalPacketsSent === 0)
|
|
600
744
|
) {
|
|
601
745
|
LoggerProxy.logger.info(
|
|
602
746
|
`StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
|
|
@@ -604,8 +748,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
604
748
|
);
|
|
605
749
|
} else {
|
|
606
750
|
if (
|
|
607
|
-
|
|
608
|
-
currentStats.framesEncoded ===
|
|
751
|
+
this.meetingMediaStatus.expected.sendVideo &&
|
|
752
|
+
(currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
753
|
+
currentStats.framesEncoded === 0)
|
|
609
754
|
) {
|
|
610
755
|
LoggerProxy.logger.info(
|
|
611
756
|
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
|
|
@@ -614,13 +759,14 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
614
759
|
}
|
|
615
760
|
|
|
616
761
|
if (
|
|
617
|
-
this.
|
|
618
|
-
|
|
619
|
-
|
|
762
|
+
this.meetingMediaStatus.expected.sendVideo &&
|
|
763
|
+
(this.statsResults['video-send'].send.framesSent ===
|
|
764
|
+
this.lastStatsResults['video-send'].send.framesSent ||
|
|
765
|
+
this.statsResults['video-send'].send.framesSent === 0)
|
|
620
766
|
) {
|
|
621
767
|
LoggerProxy.logger.info(
|
|
622
768
|
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
|
|
623
|
-
this.statsResults
|
|
769
|
+
this.statsResults['video-send'].send.framesSent
|
|
624
770
|
);
|
|
625
771
|
}
|
|
626
772
|
}
|
|
@@ -628,72 +774,28 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
628
774
|
this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);
|
|
629
775
|
}
|
|
630
776
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
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
|
-
);
|
|
777
|
+
// Video Receive
|
|
778
|
+
const currentVideoFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
|
|
779
|
+
const previousVideoFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
|
|
656
780
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
|
|
664
|
-
LoggerProxy.logger.info(
|
|
665
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
|
|
666
|
-
currentFramesReceived
|
|
667
|
-
);
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
|
|
671
|
-
LoggerProxy.logger.info(
|
|
672
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
|
|
673
|
-
currentFramesDecoded
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
if (currentFramesDropped - previousFramesDropped > 10) {
|
|
678
|
-
LoggerProxy.logger.info(
|
|
679
|
-
`StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
|
|
680
|
-
currentFramesDropped - previousFramesDropped
|
|
681
|
-
);
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);
|
|
686
|
-
}
|
|
781
|
+
this.emitStartStopEvents(
|
|
782
|
+
'video',
|
|
783
|
+
previousVideoFramesDecoded,
|
|
784
|
+
currentVideoFramesDecoded,
|
|
785
|
+
false
|
|
786
|
+
);
|
|
687
787
|
|
|
688
|
-
|
|
788
|
+
// Share Transmit
|
|
789
|
+
if (this.lastStatsResults['video-share-send']) {
|
|
689
790
|
// compare share stats sent
|
|
690
791
|
|
|
691
792
|
const currentStats = this.statsResults['video-share-send'].send;
|
|
692
793
|
const previousStats = this.lastStatsResults['video-share-send'].send;
|
|
693
794
|
|
|
694
795
|
if (
|
|
695
|
-
|
|
696
|
-
currentStats.totalPacketsSent ===
|
|
796
|
+
this.meetingMediaStatus.expected.sendShare &&
|
|
797
|
+
(currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
|
|
798
|
+
currentStats.totalPacketsSent === 0)
|
|
697
799
|
) {
|
|
698
800
|
LoggerProxy.logger.info(
|
|
699
801
|
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
|
|
@@ -701,8 +803,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
701
803
|
);
|
|
702
804
|
} else {
|
|
703
805
|
if (
|
|
704
|
-
|
|
705
|
-
currentStats.framesEncoded ===
|
|
806
|
+
this.meetingMediaStatus.expected.sendShare &&
|
|
807
|
+
(currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
808
|
+
currentStats.framesEncoded === 0)
|
|
706
809
|
) {
|
|
707
810
|
LoggerProxy.logger.info(
|
|
708
811
|
`StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
|
|
@@ -711,80 +814,34 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
711
814
|
}
|
|
712
815
|
|
|
713
816
|
if (
|
|
714
|
-
this.
|
|
715
|
-
|
|
716
|
-
|
|
817
|
+
this.meetingMediaStatus.expected.sendShare &&
|
|
818
|
+
(this.statsResults['video-share-send'].send.framesSent ===
|
|
819
|
+
this.lastStatsResults['video-share-send'].send.framesSent ||
|
|
820
|
+
this.statsResults['video-share-send'].send.framesSent === 0)
|
|
717
821
|
) {
|
|
718
822
|
LoggerProxy.logger.info(
|
|
719
823
|
`StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
|
|
720
|
-
this.statsResults
|
|
824
|
+
this.statsResults['video-share-send'].send.framesSent
|
|
721
825
|
);
|
|
722
826
|
}
|
|
723
827
|
}
|
|
724
|
-
}
|
|
725
828
|
|
|
726
|
-
|
|
727
|
-
|
|
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
|
-
);
|
|
755
|
-
|
|
756
|
-
if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
|
|
757
|
-
LoggerProxy.logger.info(
|
|
758
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
|
|
759
|
-
currentPacketsReceived
|
|
760
|
-
);
|
|
761
|
-
} else {
|
|
762
|
-
if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
|
|
763
|
-
LoggerProxy.logger.info(
|
|
764
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
|
|
765
|
-
currentFramesReceived
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
|
|
770
|
-
LoggerProxy.logger.info(
|
|
771
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
|
|
772
|
-
currentFramesDecoded
|
|
773
|
-
);
|
|
774
|
-
}
|
|
829
|
+
this.emitStartStopEvents('share', previousStats.framesSent, currentStats.framesSent, true);
|
|
830
|
+
}
|
|
775
831
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
}
|
|
832
|
+
// Share receive
|
|
833
|
+
const currentShareFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
|
|
834
|
+
const previousShareFramesDecoded = getPreviousStatsTotals(
|
|
835
|
+
'video-share-recv',
|
|
836
|
+
'framesDecoded'
|
|
837
|
+
);
|
|
783
838
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
839
|
+
this.emitStartStopEvents(
|
|
840
|
+
'share',
|
|
841
|
+
previousShareFramesDecoded,
|
|
842
|
+
currentShareFramesDecoded,
|
|
843
|
+
false
|
|
844
|
+
);
|
|
788
845
|
}
|
|
789
846
|
}
|
|
790
847
|
|
|
@@ -875,51 +932,20 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
875
932
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
876
933
|
|
|
877
934
|
if (result.bytesSent) {
|
|
878
|
-
|
|
935
|
+
const kilobytes = 0;
|
|
879
936
|
|
|
880
937
|
if (result.frameWidth && result.frameHeight) {
|
|
881
|
-
this.statsResults
|
|
882
|
-
this.statsResults
|
|
883
|
-
this.statsResults
|
|
884
|
-
this.statsResults
|
|
885
|
-
result.hugeFramesSent;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {
|
|
889
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
|
|
890
|
-
}
|
|
891
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].framesEncoded) {
|
|
892
|
-
this.statsResults.internal[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
|
|
938
|
+
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
939
|
+
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
940
|
+
this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
941
|
+
this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
893
942
|
}
|
|
894
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {
|
|
895
|
-
this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =
|
|
896
|
-
result.keyFramesEncoded;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
const bytes =
|
|
900
|
-
result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;
|
|
901
|
-
|
|
902
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
|
|
903
|
-
|
|
904
|
-
kilobytes = bytes / 1024;
|
|
905
943
|
|
|
906
944
|
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
907
|
-
this.statsResults[mediaType].bytesSent = kilobytes;
|
|
908
|
-
|
|
909
|
-
this.statsResults[mediaType][sendrecvType].framesEncoded =
|
|
910
|
-
result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
|
|
911
|
-
this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
|
|
912
|
-
result.keyFramesEncoded -
|
|
913
|
-
this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;
|
|
914
|
-
this.statsResults.internal[mediaType].outboundRtpId = result.id;
|
|
915
945
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
this.statsResults[mediaType][sendrecvType].packetsSent =
|
|
921
|
-
result.packetsSent - this.statsResults.internal[mediaType][sendrecvType].packetsSent;
|
|
922
|
-
this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
|
|
946
|
+
this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
|
|
947
|
+
this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;
|
|
948
|
+
this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;
|
|
923
949
|
|
|
924
950
|
// Data saved to send MQA metrics
|
|
925
951
|
|
|
@@ -958,79 +984,77 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
958
984
|
if (result.bytesReceived) {
|
|
959
985
|
let kilobytes = 0;
|
|
960
986
|
const receiveSlot = this.receiveSlotCallback(result.ssrc);
|
|
987
|
+
const sourceState = receiveSlot?.sourceState;
|
|
961
988
|
const idAndCsi = receiveSlot
|
|
962
989
|
? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
|
|
963
990
|
: '';
|
|
964
991
|
|
|
965
|
-
|
|
966
|
-
this.statsResults
|
|
967
|
-
this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
|
|
968
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesReceived =
|
|
969
|
-
result.framesReceived;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {
|
|
973
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =
|
|
974
|
-
result.bytesReceived;
|
|
975
|
-
}
|
|
992
|
+
const bytes =
|
|
993
|
+
result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;
|
|
976
994
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
995
|
+
kilobytes = bytes / 1024;
|
|
996
|
+
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
980
997
|
|
|
981
|
-
|
|
982
|
-
this.statsResults
|
|
998
|
+
let currentPacketsLost =
|
|
999
|
+
result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;
|
|
1000
|
+
if (currentPacketsLost < 0) {
|
|
1001
|
+
currentPacketsLost = 0;
|
|
983
1002
|
}
|
|
1003
|
+
const packetsReceivedDiff =
|
|
1004
|
+
result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;
|
|
1005
|
+
this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
|
|
984
1006
|
|
|
985
|
-
if (
|
|
986
|
-
|
|
987
|
-
|
|
1007
|
+
if (packetsReceivedDiff === 0) {
|
|
1008
|
+
if (receiveSlot && sourceState === 'live') {
|
|
1009
|
+
LoggerProxy.logger.info(
|
|
1010
|
+
`StatsAnalyzer:index#processInboundRTPResult --> No packets received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total packets received on slot: `,
|
|
1011
|
+
result.packetsReceived
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
988
1014
|
}
|
|
989
1015
|
|
|
990
|
-
if (
|
|
991
|
-
|
|
992
|
-
result.
|
|
993
|
-
}
|
|
1016
|
+
if (mediaType.startsWith('video') || mediaType.startsWith('share')) {
|
|
1017
|
+
const videoFramesReceivedDiff =
|
|
1018
|
+
result.framesReceived - this.statsResults[mediaType][sendrecvType].framesReceived;
|
|
994
1019
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1020
|
+
if (videoFramesReceivedDiff === 0) {
|
|
1021
|
+
if (receiveSlot && sourceState === 'live') {
|
|
1022
|
+
LoggerProxy.logger.info(
|
|
1023
|
+
`StatsAnalyzer:index#processInboundRTPResult --> No frames received for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames received on slot: `,
|
|
1024
|
+
result.framesReceived
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
998
1028
|
|
|
999
|
-
|
|
1029
|
+
const videoFramesDecodedDiff =
|
|
1030
|
+
result.framesDecoded - this.statsResults[mediaType][sendrecvType].framesDecoded;
|
|
1000
1031
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {
|
|
1010
|
-
this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;
|
|
1011
|
-
}
|
|
1032
|
+
if (videoFramesDecodedDiff === 0) {
|
|
1033
|
+
if (receiveSlot && sourceState === 'live') {
|
|
1034
|
+
LoggerProxy.logger.info(
|
|
1035
|
+
`StatsAnalyzer:index#processInboundRTPResult --> No frames decoded for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames decoded on slot: `,
|
|
1036
|
+
result.framesDecoded
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1012
1040
|
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived;
|
|
1016
|
-
this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
|
|
1017
|
-
result.packetsReceived;
|
|
1041
|
+
const videoFramesDroppedDiff =
|
|
1042
|
+
result.framesDropped - this.statsResults[mediaType][sendrecvType].framesDropped;
|
|
1018
1043
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1044
|
+
if (videoFramesDroppedDiff > 10) {
|
|
1045
|
+
if (receiveSlot && sourceState === 'live') {
|
|
1046
|
+
LoggerProxy.logger.info(
|
|
1047
|
+
`StatsAnalyzer:index#processInboundRTPResult --> Frames dropped for mediaType: ${mediaType}, receive slot ${idAndCsi}. Total frames dropped on slot: `,
|
|
1048
|
+
result.framesDropped
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1025
1051
|
}
|
|
1026
1052
|
}
|
|
1027
1053
|
|
|
1028
1054
|
// Check the over all packet Lost ratio
|
|
1029
1055
|
this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =
|
|
1030
|
-
|
|
1031
|
-
?
|
|
1032
|
-
(this.statsResults[mediaType][sendrecvType].packetsReceived +
|
|
1033
|
-
this.statsResults[mediaType][sendrecvType].currentPacketsLost)
|
|
1056
|
+
currentPacketsLost > 0
|
|
1057
|
+
? currentPacketsLost / (packetsReceivedDiff + currentPacketsLost)
|
|
1034
1058
|
: 0;
|
|
1035
1059
|
if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
|
|
1036
1060
|
LoggerProxy.logger.info(
|
|
@@ -1039,6 +1063,12 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1039
1063
|
);
|
|
1040
1064
|
}
|
|
1041
1065
|
|
|
1066
|
+
if (result.frameWidth && result.frameHeight) {
|
|
1067
|
+
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
1068
|
+
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
1069
|
+
this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1042
1072
|
// TODO: check the packet loss value is negative values here
|
|
1043
1073
|
|
|
1044
1074
|
if (result.packetsLost) {
|
|
@@ -1056,6 +1086,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1056
1086
|
this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
|
|
1057
1087
|
this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
|
|
1058
1088
|
this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;
|
|
1089
|
+
this.statsResults[mediaType][sendrecvType].framesDropped = result.framesDropped;
|
|
1059
1090
|
|
|
1060
1091
|
this.statsResults[mediaType][sendrecvType].decoderImplementation =
|
|
1061
1092
|
result.decoderImplementation;
|
|
@@ -1080,6 +1111,48 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1080
1111
|
}
|
|
1081
1112
|
}
|
|
1082
1113
|
|
|
1114
|
+
/**
|
|
1115
|
+
* extracts the local Ip address from the statsResult object by looking at stats results candidates
|
|
1116
|
+
* and matches that ID with the successful candidate pair. It looks at the type of local candidate it is
|
|
1117
|
+
* and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc
|
|
1118
|
+
* 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
|
|
1119
|
+
* for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP
|
|
1120
|
+
* @private
|
|
1121
|
+
* @param {string} successfulCandidatePairId - The ID of the successful candidate pair.
|
|
1122
|
+
* @param {Object} candidates - the stats result candidates
|
|
1123
|
+
* @returns {void}
|
|
1124
|
+
*/
|
|
1125
|
+
extractAndSetLocalIpAddressInfoForDiagnostics = (
|
|
1126
|
+
successfulCandidatePairId: string,
|
|
1127
|
+
candidates: {[key: string]: Record<string, unknown>}
|
|
1128
|
+
) => {
|
|
1129
|
+
let newIpAddress = '';
|
|
1130
|
+
if (successfulCandidatePairId && !isEmpty(candidates)) {
|
|
1131
|
+
const localCandidate = candidates[successfulCandidatePairId];
|
|
1132
|
+
if (localCandidate) {
|
|
1133
|
+
if (localCandidate.candidateType === 'host') {
|
|
1134
|
+
// if it's a host candidate, use the address property - it will be the local IP
|
|
1135
|
+
newIpAddress = `${localCandidate.address}`;
|
|
1136
|
+
} else if (localCandidate.candidateType === 'prflx') {
|
|
1137
|
+
// if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)
|
|
1138
|
+
// then look at the relatedAddress - it will be the local
|
|
1139
|
+
//
|
|
1140
|
+
// Firefox doesn't populate the relayProtocol property
|
|
1141
|
+
if (!localCandidate.relayProtocol) {
|
|
1142
|
+
newIpAddress = `${localCandidate.relatedAddress}`;
|
|
1143
|
+
} else {
|
|
1144
|
+
// if it's a peer reflexive candidate and we are using a relay -
|
|
1145
|
+
// in that case the relatedAddress will be the IP of the TURN server (Linus),
|
|
1146
|
+
// so we can only look at the address, but it might be local IP or public IP,
|
|
1147
|
+
// depending on if the user is behind a NAT or not
|
|
1148
|
+
newIpAddress = `${localCandidate.address}`;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
this.localIpAddress = newIpAddress;
|
|
1154
|
+
};
|
|
1155
|
+
|
|
1083
1156
|
/**
|
|
1084
1157
|
* Processes remote and local candidate result and stores
|
|
1085
1158
|
* @private
|
|
@@ -1094,118 +1167,53 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1094
1167
|
if (!result || !result.id) {
|
|
1095
1168
|
return;
|
|
1096
1169
|
}
|
|
1097
|
-
const RemoteCandidateType = {};
|
|
1098
|
-
const RemoteTransport = {};
|
|
1099
|
-
const RemoteIpAddress = {};
|
|
1100
|
-
const RemoteNetworkType = {};
|
|
1101
|
-
|
|
1102
|
-
if (!result.id) return;
|
|
1103
|
-
|
|
1104
|
-
const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
|
|
1105
|
-
const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
|
|
1106
|
-
|
|
1107
|
-
if (!RemoteCandidateType[result.id]) {
|
|
1108
|
-
RemoteCandidateType[result.id] = [];
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
if (!RemoteTransport[result.id]) {
|
|
1112
|
-
RemoteTransport[result.id] = [];
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
if (!RemoteIpAddress[result.id]) {
|
|
1116
|
-
RemoteIpAddress[result.id] = [];
|
|
1117
|
-
}
|
|
1118
|
-
if (!RemoteNetworkType[result.id]) {
|
|
1119
|
-
RemoteNetworkType[result.id] = [];
|
|
1120
|
-
}
|
|
1121
1170
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
) {
|
|
1126
|
-
RemoteCandidateType[result.id].push(result.candidateType);
|
|
1171
|
+
// We only care about the successful local candidate
|
|
1172
|
+
if (this.successfulCandidatePair?.localCandidateId !== result.id) {
|
|
1173
|
+
return;
|
|
1127
1174
|
}
|
|
1128
1175
|
|
|
1129
|
-
|
|
1130
|
-
|
|
1176
|
+
let transport;
|
|
1177
|
+
if (result.relayProtocol) {
|
|
1178
|
+
transport = result.relayProtocol.toUpperCase();
|
|
1179
|
+
} else if (result.protocol) {
|
|
1180
|
+
transport = result.protocol.toUpperCase();
|
|
1131
1181
|
}
|
|
1132
1182
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
RemoteIpAddress[result.id].indexOf(`${result.ip}:${result.portNumber}`) === -1
|
|
1136
|
-
) {
|
|
1137
|
-
RemoteIpAddress[result.id].push(`${result.ip}`); // TODO: Add ports
|
|
1138
|
-
}
|
|
1183
|
+
const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
|
|
1184
|
+
const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
|
|
1139
1185
|
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1186
|
+
if (!this.statsResults.candidates) {
|
|
1187
|
+
this.statsResults.candidates = {};
|
|
1142
1188
|
}
|
|
1143
1189
|
|
|
1144
|
-
this.statsResults.
|
|
1145
|
-
candidateType:
|
|
1146
|
-
ipAddress:
|
|
1190
|
+
this.statsResults.candidates[result.id] = {
|
|
1191
|
+
candidateType: result.candidateType,
|
|
1192
|
+
ipAddress: result.ip, // TODO: add ports
|
|
1193
|
+
relatedAddress: result.relatedAddress,
|
|
1194
|
+
relatedPort: result.relatedPort,
|
|
1195
|
+
relayProtocol: result.relayProtocol,
|
|
1196
|
+
protocol: result.protocol,
|
|
1197
|
+
address: result.address,
|
|
1147
1198
|
portNumber: result.port,
|
|
1148
|
-
networkType:
|
|
1199
|
+
networkType: result.networkType,
|
|
1149
1200
|
priority: result.priority,
|
|
1150
|
-
transport
|
|
1201
|
+
transport,
|
|
1151
1202
|
timestamp: result.time,
|
|
1152
1203
|
id: result.id,
|
|
1153
1204
|
type: result.type,
|
|
1154
1205
|
};
|
|
1155
1206
|
|
|
1156
|
-
this.statsResults.connectionType[ipType].candidateType =
|
|
1157
|
-
this.statsResults.connectionType[ipType].ipAddress =
|
|
1207
|
+
this.statsResults.connectionType[ipType].candidateType = result.candidateType;
|
|
1208
|
+
this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
|
|
1158
1209
|
|
|
1159
1210
|
this.statsResults.connectionType[ipType].networkType =
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
: RemoteNetworkType[result.id][0];
|
|
1163
|
-
this.statsResults.connectionType[ipType].transport = RemoteTransport[result.id];
|
|
1211
|
+
result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;
|
|
1212
|
+
this.statsResults.connectionType[ipType].transport = transport;
|
|
1164
1213
|
|
|
1165
1214
|
this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
|
|
1166
1215
|
};
|
|
1167
1216
|
|
|
1168
|
-
/**
|
|
1169
|
-
* Process Track results
|
|
1170
|
-
*
|
|
1171
|
-
* @private
|
|
1172
|
-
* @param {*} result
|
|
1173
|
-
* @param {*} mediaType
|
|
1174
|
-
* @returns {void}
|
|
1175
|
-
* @memberof StatsAnalyzer
|
|
1176
|
-
*/
|
|
1177
|
-
private processTrackResult(result: any, mediaType: any) {
|
|
1178
|
-
if (!result || result.type !== 'track') {
|
|
1179
|
-
return;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
const sendrecvType =
|
|
1183
|
-
result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
|
|
1184
|
-
|
|
1185
|
-
if (sendrecvType === STATS.RECEIVE_DIRECTION) {
|
|
1186
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
1187
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
|
|
1188
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
if (result.trackIdentifier && !mediaType.includes('audio')) {
|
|
1192
|
-
this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =
|
|
1193
|
-
result.trackIdentifier;
|
|
1194
|
-
|
|
1195
|
-
const jitterBufferDelay = result && result.jitterBufferDelay;
|
|
1196
|
-
const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;
|
|
1197
|
-
|
|
1198
|
-
this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =
|
|
1199
|
-
jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;
|
|
1200
|
-
|
|
1201
|
-
// Used to calculate the jitter
|
|
1202
|
-
this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =
|
|
1203
|
-
result.jitterBufferDelay;
|
|
1204
|
-
this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =
|
|
1205
|
-
result.jitterBufferEmittedCount;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
1217
|
/**
|
|
1210
1218
|
*
|
|
1211
1219
|
* @private
|
|
@@ -1216,20 +1224,15 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1216
1224
|
*/
|
|
1217
1225
|
compareSentAndReceived(result, type) {
|
|
1218
1226
|
// Don't compare on transceivers without a sender.
|
|
1219
|
-
if (!type || !this.statsResults
|
|
1227
|
+
if (!type || !this.statsResults[type].send) {
|
|
1220
1228
|
return;
|
|
1221
1229
|
}
|
|
1222
1230
|
|
|
1223
1231
|
const mediaType = type;
|
|
1224
1232
|
|
|
1225
|
-
if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {
|
|
1226
|
-
this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
1233
|
const currentPacketLoss =
|
|
1230
|
-
result.packetsLost - this.statsResults
|
|
1234
|
+
result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;
|
|
1231
1235
|
|
|
1232
|
-
this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1233
1236
|
this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
|
|
1234
1237
|
this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1235
1238
|
|