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