@webex/plugin-meetings 3.3.1-next.1 → 3.3.1-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -6
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/index.js +9 -5
- package/dist/meeting/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +74 -26
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +32 -7
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/mediaQualityMetrics/config.d.ts +6 -0
- package/dist/types/statsAnalyzer/index.d.ts +14 -6
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +17 -4
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/mediaQualityMetrics/config.ts +9 -3
- package/src/meeting/index.ts +6 -5
- package/src/statsAnalyzer/index.ts +78 -21
- package/src/statsAnalyzer/mqaUtil.ts +50 -4
- package/test/unit/spec/stats-analyzer/index.js +545 -310
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
getAudioReceiverStreamMqa,
|
|
36
36
|
getVideoSenderStreamMqa,
|
|
37
37
|
getVideoReceiverStreamMqa,
|
|
38
|
+
isStreamRequested,
|
|
38
39
|
} from './mqaUtil';
|
|
39
40
|
import {ReceiveSlot} from '../multistream/receiveSlot';
|
|
40
41
|
|
|
@@ -91,22 +92,31 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
91
92
|
successfulCandidatePair: any;
|
|
92
93
|
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
|
|
93
94
|
receiveSlotCallback: ReceiveSlotCallback;
|
|
95
|
+
isMultistream: boolean;
|
|
94
96
|
|
|
95
97
|
/**
|
|
96
98
|
* Creates a new instance of StatsAnalyzer
|
|
97
99
|
* @constructor
|
|
98
100
|
* @public
|
|
99
|
-
* @param {Object} config SDK Configuration Object
|
|
100
|
-
* @param {Function} receiveSlotCallback Callback used to access receive slots.
|
|
101
|
-
* @param {Object} networkQualityMonitor
|
|
102
|
-
* @param {Object} statsResults Default properties for stats
|
|
101
|
+
* @param {Object} config - SDK Configuration Object
|
|
102
|
+
* @param {Function} receiveSlotCallback - Callback used to access receive slots.
|
|
103
|
+
* @param {Object} networkQualityMonitor - Class for assessing network characteristics (jitter, packetLoss, latency)
|
|
104
|
+
* @param {Object} statsResults - Default properties for stats
|
|
105
|
+
* @param {boolean | undefined} isMultistream - Param indicating if the media connection is multistream or not
|
|
103
106
|
*/
|
|
104
|
-
constructor(
|
|
105
|
-
config
|
|
106
|
-
receiveSlotCallback
|
|
107
|
-
networkQualityMonitor
|
|
108
|
-
statsResults
|
|
109
|
-
|
|
107
|
+
constructor({
|
|
108
|
+
config,
|
|
109
|
+
receiveSlotCallback = () => undefined,
|
|
110
|
+
networkQualityMonitor = {},
|
|
111
|
+
statsResults = defaultStats,
|
|
112
|
+
isMultistream = false,
|
|
113
|
+
}: {
|
|
114
|
+
config: any;
|
|
115
|
+
receiveSlotCallback: ReceiveSlotCallback;
|
|
116
|
+
networkQualityMonitor: any;
|
|
117
|
+
statsResults?: any;
|
|
118
|
+
isMultistream?: boolean;
|
|
119
|
+
}) {
|
|
110
120
|
super();
|
|
111
121
|
this.statsStarted = false;
|
|
112
122
|
this.statsResults = statsResults;
|
|
@@ -120,6 +130,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
120
130
|
this.receiveSlotCallback = receiveSlotCallback;
|
|
121
131
|
this.successfulCandidatePair = {};
|
|
122
132
|
this.localIpAddress = '';
|
|
133
|
+
this.isMultistream = isMultistream;
|
|
123
134
|
}
|
|
124
135
|
|
|
125
136
|
/**
|
|
@@ -203,6 +214,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
203
214
|
statsResults: this.statsResults,
|
|
204
215
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
205
216
|
baseMediaType: 'audio-send',
|
|
217
|
+
isMultistream: this.isMultistream,
|
|
206
218
|
});
|
|
207
219
|
newMqa.audioTransmit.push(audioSender);
|
|
208
220
|
|
|
@@ -211,6 +223,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
211
223
|
statsResults: this.statsResults,
|
|
212
224
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
213
225
|
baseMediaType: 'audio-share-send',
|
|
226
|
+
isMultistream: this.isMultistream,
|
|
214
227
|
});
|
|
215
228
|
newMqa.audioTransmit.push(audioShareSender);
|
|
216
229
|
|
|
@@ -219,6 +232,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
219
232
|
statsResults: this.statsResults,
|
|
220
233
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
221
234
|
baseMediaType: 'audio-recv',
|
|
235
|
+
isMultistream: this.isMultistream,
|
|
222
236
|
});
|
|
223
237
|
newMqa.audioReceive.push(audioReceiver);
|
|
224
238
|
|
|
@@ -227,6 +241,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
227
241
|
statsResults: this.statsResults,
|
|
228
242
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
229
243
|
baseMediaType: 'audio-share-recv',
|
|
244
|
+
isMultistream: this.isMultistream,
|
|
230
245
|
});
|
|
231
246
|
newMqa.audioReceive.push(audioShareReceiver);
|
|
232
247
|
|
|
@@ -235,6 +250,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
235
250
|
statsResults: this.statsResults,
|
|
236
251
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
237
252
|
baseMediaType: 'video-send',
|
|
253
|
+
isMultistream: this.isMultistream,
|
|
238
254
|
});
|
|
239
255
|
newMqa.videoTransmit.push(videoSender);
|
|
240
256
|
|
|
@@ -243,6 +259,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
243
259
|
statsResults: this.statsResults,
|
|
244
260
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
245
261
|
baseMediaType: 'video-share-send',
|
|
262
|
+
isMultistream: this.isMultistream,
|
|
246
263
|
});
|
|
247
264
|
newMqa.videoTransmit.push(videoShareSender);
|
|
248
265
|
|
|
@@ -251,6 +268,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
251
268
|
statsResults: this.statsResults,
|
|
252
269
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
253
270
|
baseMediaType: 'video-recv',
|
|
271
|
+
isMultistream: this.isMultistream,
|
|
254
272
|
});
|
|
255
273
|
newMqa.videoReceive.push(videoReceiver);
|
|
256
274
|
|
|
@@ -259,6 +277,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
259
277
|
statsResults: this.statsResults,
|
|
260
278
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
261
279
|
baseMediaType: 'video-share-recv',
|
|
280
|
+
isMultistream: this.isMultistream,
|
|
262
281
|
});
|
|
263
282
|
newMqa.videoReceive.push(videoShareReceiver);
|
|
264
283
|
|
|
@@ -273,7 +292,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
273
292
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
274
293
|
mediaType,
|
|
275
294
|
});
|
|
276
|
-
|
|
295
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.SEND_DIRECTION)) {
|
|
296
|
+
newMqa.audioTransmit[0].streams.push(audioSenderStream);
|
|
297
|
+
}
|
|
277
298
|
|
|
278
299
|
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
279
300
|
} else if (mediaType.startsWith('audio-share-send')) {
|
|
@@ -285,7 +306,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
285
306
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
286
307
|
mediaType,
|
|
287
308
|
});
|
|
288
|
-
|
|
309
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.SEND_DIRECTION)) {
|
|
310
|
+
newMqa.audioTransmit[1].streams.push(audioSenderStream);
|
|
311
|
+
}
|
|
289
312
|
|
|
290
313
|
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
291
314
|
} else if (mediaType.startsWith('audio-recv')) {
|
|
@@ -297,7 +320,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
297
320
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
298
321
|
mediaType,
|
|
299
322
|
});
|
|
300
|
-
|
|
323
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.RECEIVE_DIRECTION)) {
|
|
324
|
+
newMqa.audioReceive[0].streams.push(audioReceiverStream);
|
|
325
|
+
}
|
|
301
326
|
|
|
302
327
|
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
303
328
|
} else if (mediaType.startsWith('audio-share-recv')) {
|
|
@@ -309,8 +334,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
309
334
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
310
335
|
mediaType,
|
|
311
336
|
});
|
|
312
|
-
|
|
313
|
-
|
|
337
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.RECEIVE_DIRECTION)) {
|
|
338
|
+
newMqa.audioReceive[1].streams.push(audioReceiverStream);
|
|
339
|
+
}
|
|
314
340
|
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
315
341
|
} else if (mediaType.startsWith('video-send-layer')) {
|
|
316
342
|
// We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.
|
|
@@ -322,8 +348,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
322
348
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
323
349
|
mediaType,
|
|
324
350
|
});
|
|
325
|
-
|
|
326
|
-
|
|
351
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.SEND_DIRECTION)) {
|
|
352
|
+
newMqa.videoTransmit[0].streams.push(videoSenderStream);
|
|
353
|
+
}
|
|
327
354
|
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
328
355
|
} else if (mediaType.startsWith('video-share-send')) {
|
|
329
356
|
const videoSenderStream = cloneDeep(emptyVideoTransmitStream);
|
|
@@ -334,7 +361,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
334
361
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
335
362
|
mediaType,
|
|
336
363
|
});
|
|
337
|
-
|
|
364
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.SEND_DIRECTION)) {
|
|
365
|
+
newMqa.videoTransmit[1].streams.push(videoSenderStream);
|
|
366
|
+
}
|
|
338
367
|
|
|
339
368
|
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
340
369
|
} else if (mediaType.startsWith('video-recv')) {
|
|
@@ -346,7 +375,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
346
375
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
347
376
|
mediaType,
|
|
348
377
|
});
|
|
349
|
-
|
|
378
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.RECEIVE_DIRECTION)) {
|
|
379
|
+
newMqa.videoReceive[0].streams.push(videoReceiverStream);
|
|
380
|
+
}
|
|
350
381
|
|
|
351
382
|
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
352
383
|
} else if (mediaType.startsWith('video-share-recv')) {
|
|
@@ -358,8 +389,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
358
389
|
lastMqaDataSent: this.lastMqaDataSent,
|
|
359
390
|
mediaType,
|
|
360
391
|
});
|
|
361
|
-
|
|
362
|
-
|
|
392
|
+
if (isStreamRequested(this.statsResults, mediaType, STATS.RECEIVE_DIRECTION)) {
|
|
393
|
+
newMqa.videoReceive[1].streams.push(videoReceiverStream);
|
|
394
|
+
}
|
|
363
395
|
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
364
396
|
}
|
|
365
397
|
});
|
|
@@ -388,6 +420,17 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
388
420
|
|
|
389
421
|
newMqa.networkType = this.statsResults.connectionType.local.networkType;
|
|
390
422
|
|
|
423
|
+
newMqa.intervalMetadata.screenWidth = window.screen.width;
|
|
424
|
+
newMqa.intervalMetadata.screenHeight = window.screen.height;
|
|
425
|
+
newMqa.intervalMetadata.screenResolution = Math.round(
|
|
426
|
+
(window.screen.width * window.screen.height) / 256
|
|
427
|
+
);
|
|
428
|
+
newMqa.intervalMetadata.appWindowWidth = window.innerWidth;
|
|
429
|
+
newMqa.intervalMetadata.appWindowHeight = window.innerHeight;
|
|
430
|
+
newMqa.intervalMetadata.appWindowSize = Math.round(
|
|
431
|
+
(window.innerWidth * window.innerHeight) / 256
|
|
432
|
+
);
|
|
433
|
+
|
|
391
434
|
this.mqaSentCount += 1;
|
|
392
435
|
|
|
393
436
|
newMqa.intervalNumber = this.mqaSentCount;
|
|
@@ -1003,6 +1046,11 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1003
1046
|
this.statsResults[mediaType][sendrecvType].totalRtxBytesSent = result.retransmittedBytesSent;
|
|
1004
1047
|
this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;
|
|
1005
1048
|
this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;
|
|
1049
|
+
this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =
|
|
1050
|
+
result.retransmittedBytesSent;
|
|
1051
|
+
this.statsResults[mediaType][sendrecvType].isRequested = result.isRequested;
|
|
1052
|
+
this.statsResults[mediaType][sendrecvType].lastRequestedUpdateTimestamp =
|
|
1053
|
+
result.lastRequestedUpdateTimestamp;
|
|
1006
1054
|
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
1007
1055
|
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
1008
1056
|
}
|
|
@@ -1088,6 +1136,12 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1088
1136
|
}
|
|
1089
1137
|
}
|
|
1090
1138
|
|
|
1139
|
+
if (mediaType.startsWith('video-recv')) {
|
|
1140
|
+
this.statsResults[mediaType][sendrecvType].isActiveSpeaker = result.isActiveSpeaker;
|
|
1141
|
+
this.statsResults[mediaType][sendrecvType].lastActiveSpeakerTimestamp =
|
|
1142
|
+
result.lastActiveSpeakerUpdateTimestamp;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1091
1145
|
// Check the over all packet Lost ratio
|
|
1092
1146
|
this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =
|
|
1093
1147
|
currentPacketsLost > 0
|
|
@@ -1151,6 +1205,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1151
1205
|
this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =
|
|
1152
1206
|
result.totalSamplesDecoded || 0;
|
|
1153
1207
|
this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;
|
|
1208
|
+
this.statsResults[mediaType][sendrecvType].isRequested = result.isRequested;
|
|
1209
|
+
this.statsResults[mediaType][sendrecvType].lastRequestedUpdateTimestamp =
|
|
1210
|
+
result.lastRequestedUpdateTimestamp;
|
|
1154
1211
|
}
|
|
1155
1212
|
}
|
|
1156
1213
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {mean, max} from 'lodash';
|
|
4
4
|
|
|
5
|
-
import {STATS} from '../constants';
|
|
5
|
+
import {MQA_INTERVAL, STATS} from '../constants';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Get the totals of a certain value from a certain media type.
|
|
@@ -28,6 +28,7 @@ export const getAudioReceiverMqa = ({
|
|
|
28
28
|
statsResults,
|
|
29
29
|
lastMqaDataSent,
|
|
30
30
|
baseMediaType,
|
|
31
|
+
isMultistream,
|
|
31
32
|
}) => {
|
|
32
33
|
const sendrecvType = STATS.RECEIVE_DIRECTION;
|
|
33
34
|
|
|
@@ -52,6 +53,7 @@ export const getAudioReceiverMqa = ({
|
|
|
52
53
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
53
54
|
?.direction || 'inactive';
|
|
54
55
|
audioReceiver.common.common.isMain = !baseMediaType.includes('-share');
|
|
56
|
+
audioReceiver.common.common.multistreamEnabled = isMultistream;
|
|
55
57
|
audioReceiver.common.transportType = statsResults.connectionType.local.transport;
|
|
56
58
|
|
|
57
59
|
// add rtpPacket info inside common as also for call analyzer
|
|
@@ -127,7 +129,13 @@ export const getAudioReceiverStreamMqa = ({
|
|
|
127
129
|
((statsResults[mediaType][sendrecvType].totalBytesReceived - lastBytesReceived) * 8) / 60 || 0;
|
|
128
130
|
};
|
|
129
131
|
|
|
130
|
-
export const getAudioSenderMqa = ({
|
|
132
|
+
export const getAudioSenderMqa = ({
|
|
133
|
+
audioSender,
|
|
134
|
+
statsResults,
|
|
135
|
+
lastMqaDataSent,
|
|
136
|
+
baseMediaType,
|
|
137
|
+
isMultistream,
|
|
138
|
+
}) => {
|
|
131
139
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
132
140
|
|
|
133
141
|
const getLastTotalValue = (value: string) =>
|
|
@@ -152,6 +160,7 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent, b
|
|
|
152
160
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
153
161
|
?.direction || 'inactive';
|
|
154
162
|
audioSender.common.common.isMain = !baseMediaType.includes('-share');
|
|
163
|
+
audioSender.common.common.multistreamEnabled = isMultistream;
|
|
155
164
|
audioSender.common.transportType = statsResults.connectionType.local.transport;
|
|
156
165
|
|
|
157
166
|
audioSender.common.maxRemoteJitter = max(meanRemoteJitter) * 1000 || 0;
|
|
@@ -166,8 +175,8 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent, b
|
|
|
166
175
|
baseMediaType,
|
|
167
176
|
'availableOutgoingBitrate'
|
|
168
177
|
);
|
|
169
|
-
// Calculate based on how much packets lost of received compated to how to the client sent
|
|
170
178
|
|
|
179
|
+
// Calculate based on how much packets lost of received compated to how to the client sent
|
|
171
180
|
const totalPacketsLostForaMin = totalPacketsLostOnReceiver - lastPacketsLostTotal;
|
|
172
181
|
audioSender.common.remoteLossRate =
|
|
173
182
|
totalPacketsSent - lastPacketsSent > 0
|
|
@@ -225,6 +234,7 @@ export const getVideoReceiverMqa = ({
|
|
|
225
234
|
statsResults,
|
|
226
235
|
lastMqaDataSent,
|
|
227
236
|
baseMediaType,
|
|
237
|
+
isMultistream,
|
|
228
238
|
}) => {
|
|
229
239
|
const sendrecvType = STATS.RECEIVE_DIRECTION;
|
|
230
240
|
|
|
@@ -254,6 +264,7 @@ export const getVideoReceiverMqa = ({
|
|
|
254
264
|
videoReceiver.common.common.direction =
|
|
255
265
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
256
266
|
?.direction || 'inactive';
|
|
267
|
+
videoReceiver.common.common.multistreamEnabled = isMultistream;
|
|
257
268
|
videoReceiver.common.common.isMain = !baseMediaType.includes('-share');
|
|
258
269
|
videoReceiver.common.transportType = statsResults.connectionType.local.transport;
|
|
259
270
|
|
|
@@ -347,9 +358,23 @@ export const getVideoReceiverStreamMqa = ({
|
|
|
347
358
|
statsResults[mediaType][sendrecvType].keyFramesDecoded - lastKeyFramesDecoded || 0;
|
|
348
359
|
videoReceiverStream.requestedKeyFrames =
|
|
349
360
|
statsResults[mediaType][sendrecvType].totalPliCount - lastPliCount || 0;
|
|
361
|
+
|
|
362
|
+
videoReceiverStream.isActiveSpeaker =
|
|
363
|
+
statsResults[mediaType][sendrecvType].isActiveSpeaker ||
|
|
364
|
+
((statsResults[mediaType][sendrecvType].lastActiveSpeakerTimestamp ?? 0) > 0 &&
|
|
365
|
+
performance.now() +
|
|
366
|
+
performance.timeOrigin -
|
|
367
|
+
(statsResults[mediaType][sendrecvType].lastActiveSpeakerTimestamp ?? 0) <
|
|
368
|
+
MQA_INTERVAL);
|
|
350
369
|
};
|
|
351
370
|
|
|
352
|
-
export const getVideoSenderMqa = ({
|
|
371
|
+
export const getVideoSenderMqa = ({
|
|
372
|
+
videoSender,
|
|
373
|
+
statsResults,
|
|
374
|
+
lastMqaDataSent,
|
|
375
|
+
baseMediaType,
|
|
376
|
+
isMultistream,
|
|
377
|
+
}) => {
|
|
353
378
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
354
379
|
|
|
355
380
|
const getLastTotalValue = (value: string) =>
|
|
@@ -373,6 +398,7 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, b
|
|
|
373
398
|
videoSender.common.common.direction =
|
|
374
399
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
375
400
|
?.direction || 'inactive';
|
|
401
|
+
videoSender.common.common.multistreamEnabled = isMultistream;
|
|
376
402
|
videoSender.common.common.isMain = !baseMediaType.includes('-share');
|
|
377
403
|
videoSender.common.transportType = statsResults.connectionType.local.transport;
|
|
378
404
|
|
|
@@ -461,3 +487,23 @@ export const getVideoSenderStreamMqa = ({
|
|
|
461
487
|
videoSenderStream.requestedFrameSize =
|
|
462
488
|
statsResults[mediaType][sendrecvType].requestedFrameSize || 0;
|
|
463
489
|
};
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Checks if stream stats should be updated based on request status and elapsed time.
|
|
493
|
+
*
|
|
494
|
+
* @param {Object} statsResults - Stats results object.
|
|
495
|
+
* @param {string} mediaType - Media type (e.g., 'audio', 'video').
|
|
496
|
+
* @param {string} direction - Stats direction (e.g., 'send', 'receive').
|
|
497
|
+
* @returns {boolean} Whether stats should be updated.
|
|
498
|
+
*/
|
|
499
|
+
export const isStreamRequested = (
|
|
500
|
+
statsResults: any,
|
|
501
|
+
mediaType: string,
|
|
502
|
+
direction: string
|
|
503
|
+
): boolean => {
|
|
504
|
+
const now = performance.timeOrigin + performance.now();
|
|
505
|
+
const lastUpdateTimestamp = statsResults[mediaType][direction]?.lastRequestedUpdateTimestamp;
|
|
506
|
+
const isRequested = statsResults[mediaType][direction]?.isRequested;
|
|
507
|
+
|
|
508
|
+
return isRequested || (lastUpdateTimestamp && now - lastUpdateTimestamp < MQA_INTERVAL);
|
|
509
|
+
};
|