@webex/plugin-meetings 2.60.1-next.13 → 2.60.1-next.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/interpretation/index.js +1 -1
  4. package/dist/interpretation/siLanguage.js +1 -1
  5. package/dist/mediaQualityMetrics/config.d.ts +103 -99
  6. package/dist/mediaQualityMetrics/config.js +133 -129
  7. package/dist/mediaQualityMetrics/config.js.map +1 -1
  8. package/dist/meeting/index.js +4 -2
  9. package/dist/meeting/index.js.map +1 -1
  10. package/dist/meeting/request.d.ts +2 -0
  11. package/dist/meeting/request.js +4 -0
  12. package/dist/meeting/request.js.map +1 -1
  13. package/dist/meetings/index.js +19 -0
  14. package/dist/meetings/index.js.map +1 -1
  15. package/dist/meetings/util.js +1 -1
  16. package/dist/meetings/util.js.map +1 -1
  17. package/dist/metrics/constants.d.ts +2 -0
  18. package/dist/metrics/constants.js +3 -1
  19. package/dist/metrics/constants.js.map +1 -1
  20. package/dist/reachability/index.js +14 -20
  21. package/dist/reachability/index.js.map +1 -1
  22. package/dist/reconnection-manager/index.js +63 -43
  23. package/dist/reconnection-manager/index.js.map +1 -1
  24. package/dist/roap/turnDiscovery.d.ts +18 -2
  25. package/dist/roap/turnDiscovery.js +163 -69
  26. package/dist/roap/turnDiscovery.js.map +1 -1
  27. package/dist/rtcMetrics/index.d.ts +7 -0
  28. package/dist/rtcMetrics/index.js +38 -1
  29. package/dist/rtcMetrics/index.js.map +1 -1
  30. package/dist/statsAnalyzer/index.js +135 -23
  31. package/dist/statsAnalyzer/index.js.map +1 -1
  32. package/dist/statsAnalyzer/mqaUtil.d.ts +28 -4
  33. package/dist/statsAnalyzer/mqaUtil.js +278 -148
  34. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  35. package/dist/webinar/index.js +1 -1
  36. package/package.json +21 -21
  37. package/src/mediaQualityMetrics/config.ts +107 -107
  38. package/src/meeting/index.ts +2 -0
  39. package/src/meeting/request.ts +6 -0
  40. package/src/meetings/index.ts +22 -0
  41. package/src/meetings/util.ts +1 -1
  42. package/src/metrics/constants.ts +2 -0
  43. package/src/reachability/index.ts +0 -6
  44. package/src/reconnection-manager/index.ts +18 -7
  45. package/src/roap/turnDiscovery.ts +100 -24
  46. package/src/rtcMetrics/index.ts +43 -1
  47. package/src/statsAnalyzer/index.ts +158 -24
  48. package/src/statsAnalyzer/mqaUtil.ts +302 -154
  49. package/test/unit/spec/meeting/index.js +46 -0
  50. package/test/unit/spec/meeting/request.js +2 -0
  51. package/test/unit/spec/meetings/utils.js +35 -8
  52. package/test/unit/spec/reachability/index.ts +74 -0
  53. package/test/unit/spec/reconnection-manager/index.js +36 -1
  54. package/test/unit/spec/roap/turnDiscovery.ts +326 -76
  55. package/test/unit/spec/rtcMetrics/index.ts +32 -3
  56. package/test/unit/spec/stats-analyzer/index.js +439 -1
  57. package/test/utils/webex-test-users.js +12 -4
@@ -4,11 +4,82 @@ import {mean, max} from 'lodash';
4
4
 
5
5
  import {STATS} from '../constants';
6
6
 
7
- export const getAudioReceiverMqa = ({audioReceiver, statsResults, lastMqaDataSent, mediaType}) => {
7
+ /**
8
+ * Get the totals of a certain value from a certain media type.
9
+ *
10
+ * @param {object} stats - The large stats object.
11
+ * @param {string} sendrecvType - "send" or "recv".
12
+ * @param {string} baseMediaType - audio or video _and_ share or non-share.
13
+ * @param {string} value - The value we want to get the totals of.
14
+ * @returns {number}
15
+ */
16
+ const getTotalValueFromBaseType = (
17
+ stats: object,
18
+ sendrecvType: string,
19
+ baseMediaType: string,
20
+ value: string
21
+ ): number =>
22
+ Object.keys(stats)
23
+ .filter((mt) => mt.includes(baseMediaType))
24
+ .reduce((acc, mt) => acc + (stats[mt]?.[sendrecvType]?.[value] || 0), 0);
25
+
26
+ export const getAudioReceiverMqa = ({
27
+ audioReceiver,
28
+ statsResults,
29
+ lastMqaDataSent,
30
+ baseMediaType,
31
+ }) => {
32
+ const sendrecvType = STATS.RECEIVE_DIRECTION;
33
+
34
+ const getLastTotalValue = (value: string) =>
35
+ getTotalValueFromBaseType(lastMqaDataSent, sendrecvType, baseMediaType, value);
36
+ const getTotalValue = (value: string) =>
37
+ getTotalValueFromBaseType(statsResults, sendrecvType, baseMediaType, value);
38
+
39
+ const lastPacketsReceived = getLastTotalValue('totalPacketsReceived');
40
+ const lastPacketsLost = getLastTotalValue('totalPacketsLost');
41
+ const lastBytesReceived = getLastTotalValue('totalBytesReceived');
42
+ const lastFecPacketsReceived = getLastTotalValue('fecPacketsReceived');
43
+ const lastFecPacketsDiscarded = getLastTotalValue('fecPacketsDiscarded');
44
+
45
+ const totalPacketsReceived = getTotalValue('totalPacketsReceived');
46
+ const packetsLost = getTotalValue('totalPacketsLost');
47
+ const totalBytesReceived = getTotalValue('totalBytesReceived');
48
+ const totalFecPacketsReceived = getTotalValue('fecPacketsReceived');
49
+ const totalFecPacketsDiscarded = getTotalValue('fecPacketsDiscarded');
50
+
51
+ audioReceiver.common.common.direction =
52
+ statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
53
+ ?.direction || 'inactive';
54
+ audioReceiver.common.common.isMain = !baseMediaType.includes('-share');
55
+ audioReceiver.common.transportType = statsResults.connectionType.local.transport;
56
+
57
+ // add rtpPacket info inside common as also for call analyzer
58
+ audioReceiver.common.rtpPackets = totalPacketsReceived - lastPacketsReceived;
59
+
60
+ // Hop by hop are numbers and not percentage so we compare on what we sent the last min
61
+ // collect the packets received for the last min
62
+ const totalPacketsLost = packetsLost - lastPacketsLost;
63
+ audioReceiver.common.mediaHopByHopLost = totalPacketsLost;
64
+ audioReceiver.common.rtpHopByHopLost = totalPacketsLost;
65
+
66
+ const fecRecovered =
67
+ totalFecPacketsReceived -
68
+ lastFecPacketsReceived -
69
+ (totalFecPacketsDiscarded - lastFecPacketsDiscarded);
70
+ audioReceiver.common.fecPackets = fecRecovered;
71
+
72
+ audioReceiver.common.rtpBitrate = ((totalBytesReceived - lastBytesReceived) * 8) / 60 || 0;
73
+ };
74
+
75
+ export const getAudioReceiverStreamMqa = ({
76
+ audioReceiverStream,
77
+ statsResults,
78
+ lastMqaDataSent,
79
+ mediaType,
80
+ }) => {
8
81
  const sendrecvType = STATS.RECEIVE_DIRECTION;
9
82
 
10
- const lastPacketsReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsReceived || 0;
11
- const lastPacketsLost = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLost || 0;
12
83
  const lastPacketsDecoded = lastMqaDataSent[mediaType]?.[sendrecvType].totalSamplesDecoded || 0;
13
84
  const lastSamplesReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalSamplesReceived || 0;
14
85
  const lastConcealedSamples = lastMqaDataSent[mediaType]?.[sendrecvType].concealedSamples || 0;
@@ -16,123 +87,195 @@ export const getAudioReceiverMqa = ({audioReceiver, statsResults, lastMqaDataSen
16
87
  const lastFecPacketsReceived = lastMqaDataSent[mediaType]?.[sendrecvType].fecPacketsReceived || 0;
17
88
  const lastFecPacketsDiscarded =
18
89
  lastMqaDataSent[mediaType]?.[sendrecvType].fecPacketsDiscarded || 0;
90
+ const lastPacketsReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsReceived || 0;
91
+ const lastPacketsLost = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLost || 0;
19
92
 
20
93
  const {csi} = statsResults[mediaType];
21
- if (csi && !audioReceiver.streams[0].common.csi.includes(csi)) {
22
- audioReceiver.streams[0].common.csi.push(csi);
94
+ if (csi && !audioReceiverStream.common.csi.includes(csi)) {
95
+ audioReceiverStream.common.csi.push(csi);
23
96
  }
24
97
 
25
- audioReceiver.common.common.direction = statsResults[mediaType].direction;
26
- audioReceiver.common.common.isMain = !mediaType.includes('-share');
27
- audioReceiver.common.transportType = statsResults.connectionType.local.transport;
28
-
29
- // add rtpPacket info inside common as also for call analyzer
30
- audioReceiver.common.rtpPackets =
98
+ audioReceiverStream.common.rtpPackets =
31
99
  statsResults[mediaType][sendrecvType].totalPacketsReceived - lastPacketsReceived || 0;
32
- audioReceiver.streams[0].common.rtpPackets = audioReceiver.common.rtpPackets;
33
-
34
- // Hop by hop are numbers and not percentage so we compare on what we sent the last min
35
- // collect the packets received for the last min
36
- const totalPacketsLost =
37
- statsResults[mediaType][sendrecvType].totalPacketsLost - lastPacketsLost || 0;
38
- audioReceiver.common.mediaHopByHopLost = totalPacketsLost;
39
- audioReceiver.common.rtpHopByHopLost = totalPacketsLost;
40
100
 
41
- audioReceiver.streams[0].common.maxRtpJitter =
101
+ audioReceiverStream.common.maxRtpJitter =
42
102
  // @ts-ignore
43
103
  max(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
44
- audioReceiver.streams[0].common.meanRtpJitter =
104
+ audioReceiverStream.common.meanRtpJitter =
45
105
  mean(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
46
- audioReceiver.streams[0].common.rtpJitter = audioReceiver.streams[0].common.maxRtpJitter;
106
+ audioReceiverStream.common.rtpJitter = audioReceiverStream.common.maxRtpJitter;
47
107
 
48
108
  // Fec packets do come in as part of the FEC only for audio
49
109
  const fecRecovered =
50
110
  statsResults[mediaType][sendrecvType].fecPacketsReceived -
51
111
  lastFecPacketsReceived -
52
112
  (statsResults[mediaType][sendrecvType].fecPacketsDiscarded - lastFecPacketsDiscarded);
53
- audioReceiver.common.fecPackets = fecRecovered || 0;
54
113
 
55
- audioReceiver.streams[0].common.rtpEndToEndLost =
114
+ audioReceiverStream.common.rtpEndToEndLost =
56
115
  statsResults[mediaType][sendrecvType].totalPacketsLost - lastPacketsLost - fecRecovered || 0;
57
116
 
58
- audioReceiver.streams[0].common.framesDropped =
117
+ audioReceiverStream.common.framesDropped =
59
118
  statsResults[mediaType][sendrecvType].totalSamplesDecoded - lastPacketsDecoded || 0;
60
- audioReceiver.streams[0].common.renderedFrameRate =
61
- (audioReceiver.streams[0].common.framesDropped * 100) / 60 || 0;
119
+ audioReceiverStream.common.renderedFrameRate =
120
+ (audioReceiverStream.common.framesDropped * 100) / 60 || 0;
62
121
 
63
- audioReceiver.streams[0].common.framesReceived =
122
+ audioReceiverStream.common.framesReceived =
64
123
  statsResults[mediaType][sendrecvType].totalSamplesReceived - lastSamplesReceived || 0;
65
- audioReceiver.streams[0].common.concealedFrames =
124
+ audioReceiverStream.common.concealedFrames =
66
125
  statsResults[mediaType][sendrecvType].concealedSamples - lastConcealedSamples || 0;
67
- audioReceiver.streams[0].common.receivedBitrate =
126
+ audioReceiverStream.common.receivedBitrate =
68
127
  ((statsResults[mediaType][sendrecvType].totalBytesReceived - lastBytesReceived) * 8) / 60 || 0;
69
-
70
- audioReceiver.common.rtpBitrate = audioReceiver.streams[0].common.receivedBitrate;
71
128
  };
72
129
 
73
- export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent, mediaType}) => {
130
+ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent, baseMediaType}) => {
74
131
  const sendrecvType = STATS.SEND_DIRECTION;
75
132
 
76
- const lastPacketsSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsSent || 0;
77
- const lastPacketsLost =
78
- lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLostOnReceiver || 0;
79
- const lastBytesSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesSent || 0;
80
- const lastFramesEncoded = lastMqaDataSent[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
81
- const lastFirCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalFirCount || 0;
133
+ const getLastTotalValue = (value: string) =>
134
+ getTotalValueFromBaseType(lastMqaDataSent, sendrecvType, baseMediaType, value);
135
+ const getTotalValue = (value: string) =>
136
+ getTotalValueFromBaseType(statsResults, sendrecvType, baseMediaType, value);
82
137
 
83
- const {csi} = statsResults[mediaType];
84
- if (csi && !audioSender.streams[0].common.csi.includes(csi)) {
85
- audioSender.streams[0].common.csi.push(csi);
86
- }
138
+ const lastPacketsSent = getLastTotalValue('totalPacketsSent');
139
+ const lastPacketsLostTotal = getLastTotalValue('totalPacketsLostOnReceiver');
140
+
141
+ const totalPacketsLostOnReceiver = getTotalValue('totalPacketsLostOnReceiver');
142
+ const totalPacketsSent = getTotalValue('totalPacketsSent');
143
+
144
+ const meanRemoteJitter = Object.keys(statsResults)
145
+ .filter((mt) => mt.includes(baseMediaType))
146
+ .reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRemoteJitter), []);
147
+ const meanRoundTripTime = Object.keys(statsResults)
148
+ .filter((mt) => mt.includes(baseMediaType))
149
+ .reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRoundTripTime), []);
87
150
 
88
- audioSender.common.common.direction = statsResults[mediaType].direction;
89
- audioSender.common.common.isMain = !mediaType.includes('-share');
151
+ audioSender.common.common.direction =
152
+ statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
153
+ ?.direction || 'inactive';
154
+ audioSender.common.common.isMain = !baseMediaType.includes('-share');
90
155
  audioSender.common.transportType = statsResults.connectionType.local.transport;
91
156
 
92
- audioSender.common.maxRemoteJitter =
93
- // @ts-ignore
94
- max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
95
- audioSender.common.meanRemoteJitter =
96
- mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
157
+ audioSender.common.maxRemoteJitter = max(meanRemoteJitter) * 1000 || 0;
158
+ audioSender.common.meanRemoteJitter = mean(meanRemoteJitter) * 1000 || 0;
97
159
 
98
- audioSender.common.rtpPackets =
99
- statsResults[mediaType][sendrecvType].totalPacketsSent - lastPacketsSent || 0;
100
- audioSender.streams[0].common.rtpPackets = audioSender.common.rtpPackets;
160
+ audioSender.common.rtpPackets = totalPacketsSent - lastPacketsSent || 0;
161
+ // audioSender.streams[0].common.rtpPackets = audioSender.common.rtpPackets;
101
162
  // From candidate-pair
102
- audioSender.common.availableBitrate =
103
- statsResults[mediaType][sendrecvType].availableOutgoingBitrate || 0;
163
+ audioSender.common.availableBitrate = getTotalValueFromBaseType(
164
+ statsResults,
165
+ sendrecvType,
166
+ baseMediaType,
167
+ 'availableOutgoingBitrate'
168
+ );
104
169
  // Calculate based on how much packets lost of received compated to how to the client sent
105
170
 
106
- const totalpacketsLostForaMin =
107
- statsResults[mediaType][sendrecvType].totalPacketsLostOnReceiver - lastPacketsLost;
108
-
171
+ const totalPacketsLostForaMin = totalPacketsLostOnReceiver - lastPacketsLostTotal;
109
172
  audioSender.common.remoteLossRate =
110
- audioSender.common.rtpPackets > 0
111
- ? (totalpacketsLostForaMin * 100) / audioSender.common.rtpPackets
112
- : 0; // This is the packets sent with in last min || 0;
173
+ totalPacketsSent - lastPacketsSent > 0
174
+ ? (totalPacketsLostForaMin * 100) / (totalPacketsSent - lastPacketsSent)
175
+ : 0; // This is the packets sent with in last min
113
176
 
114
- audioSender.common.maxRoundTripTime =
115
- // @ts-ignore
116
- max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
117
- audioSender.common.meanRoundTripTime =
118
- mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
177
+ audioSender.common.maxRoundTripTime = max(meanRoundTripTime) * 1000 || 0;
178
+ audioSender.common.meanRoundTripTime = mean(meanRoundTripTime) * 1000 || 0;
119
179
  audioSender.common.roundTripTime = audioSender.common.maxRoundTripTime;
120
180
 
121
181
  // Calculate the outgoing bitrate
122
- const totalBytesSentInaMin = statsResults[mediaType][sendrecvType].totalBytesSent - lastBytesSent;
182
+ const totalBytesSentInaMin =
183
+ getTotalValueFromBaseType(statsResults, sendrecvType, baseMediaType, 'totalBytesSent') -
184
+ getTotalValueFromBaseType(lastMqaDataSent, sendrecvType, baseMediaType, 'totalBytesSent');
185
+
186
+ audioSender.common.rtpBitrate = totalBytesSentInaMin ? (totalBytesSentInaMin * 8) / 60 : 0;
187
+ };
188
+
189
+ export const getAudioSenderStreamMqa = ({
190
+ audioSenderStream,
191
+ statsResults,
192
+ lastMqaDataSent,
193
+ mediaType,
194
+ }) => {
195
+ const sendrecvType = STATS.SEND_DIRECTION;
123
196
 
124
- audioSender.streams[0].common.transmittedBitrate = totalBytesSentInaMin
197
+ const lastBytesSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesSent || 0;
198
+ const lastFramesEncoded = lastMqaDataSent[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
199
+ const lastFirCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalFirCount || 0;
200
+ const lastPacketsSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsSent || 0;
201
+
202
+ const {csi} = statsResults[mediaType];
203
+ if (csi && !audioSenderStream.common.csi.includes(csi)) {
204
+ audioSenderStream.common.csi.push(csi);
205
+ }
206
+
207
+ audioSenderStream.common.rtpPackets =
208
+ statsResults[mediaType][sendrecvType].totalPacketsSent - lastPacketsSent || 0;
209
+
210
+ const totalBytesSentInaMin = statsResults[mediaType][sendrecvType].totalBytesSent - lastBytesSent;
211
+ audioSenderStream.common.transmittedBitrate = totalBytesSentInaMin
125
212
  ? (totalBytesSentInaMin * 8) / 60
126
213
  : 0;
127
- audioSender.common.rtpBitrate = audioSender.streams[0].common.transmittedBitrate;
128
214
 
129
- audioSender.streams[0].transmittedKeyFrames =
215
+ audioSenderStream.transmittedKeyFrames =
130
216
  statsResults[mediaType][sendrecvType].totalKeyFramesEncoded - lastFramesEncoded || 0;
131
- audioSender.streams[0].requestedKeyFrames =
217
+ audioSenderStream.requestedKeyFrames =
132
218
  statsResults[mediaType][sendrecvType].totalFirCount - lastFirCount || 0;
133
219
  };
134
220
 
135
- export const getVideoReceiverMqa = ({videoReceiver, statsResults, lastMqaDataSent, mediaType}) => {
221
+ export const getVideoReceiverMqa = ({
222
+ videoReceiver,
223
+ statsResults,
224
+ lastMqaDataSent,
225
+ baseMediaType,
226
+ }) => {
227
+ const sendrecvType = STATS.RECEIVE_DIRECTION;
228
+
229
+ const getLastTotalValue = (value: string) =>
230
+ getTotalValueFromBaseType(lastMqaDataSent, sendrecvType, baseMediaType, value);
231
+ const getTotalValue = (value: string) =>
232
+ getTotalValueFromBaseType(statsResults, sendrecvType, baseMediaType, value);
233
+
234
+ const lastPacketsReceived = getLastTotalValue('totalPacketsReceived');
235
+ const lastPacketsLost = getLastTotalValue('totalPacketsLost');
236
+ const lastBytesReceived = getLastTotalValue('totalBytesReceived');
237
+
238
+ const packetsLost = getTotalValue('totalPacketsLost');
239
+ const totalPacketsReceived = getTotalValue('totalPacketsReceived');
240
+ const totalBytesReceived = getTotalValue('totalBytesReceived');
241
+
242
+ const meanRemoteJitter = Object.keys(statsResults)
243
+ .filter((mt) => mt.includes(baseMediaType))
244
+ .reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRemoteJitter), []);
245
+
246
+ videoReceiver.common.common.direction =
247
+ statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
248
+ ?.direction || 'inactive';
249
+ videoReceiver.common.common.isMain = !baseMediaType.includes('-share');
250
+ videoReceiver.common.transportType = statsResults.connectionType.local.transport;
251
+
252
+ // collect the packets received for the last min
253
+ videoReceiver.common.rtpPackets = totalPacketsReceived - lastPacketsReceived || 0;
254
+
255
+ // Hop by hop are numbers and not percentage so we compare on what we sent the last min
256
+ // this is including packet lost
257
+ const totalPacketsLost = packetsLost - lastPacketsLost;
258
+ videoReceiver.common.mediaHopByHopLost = totalPacketsLost;
259
+ videoReceiver.common.rtpHopByHopLost = totalPacketsLost;
260
+
261
+ // calculate this values
262
+ videoReceiver.common.maxRemoteJitter = max(meanRemoteJitter) * 1000 || 0;
263
+ videoReceiver.common.meanRemoteJitter = mean(meanRemoteJitter) * 1000 || 0;
264
+
265
+ // Calculate the outgoing bitrate
266
+ const totalBytesReceivedInaMin = totalBytesReceived - lastBytesReceived;
267
+
268
+ videoReceiver.common.rtpBitrate = totalBytesReceivedInaMin
269
+ ? (totalBytesReceivedInaMin * 8) / 60
270
+ : 0;
271
+ };
272
+
273
+ export const getVideoReceiverStreamMqa = ({
274
+ videoReceiverStream,
275
+ statsResults,
276
+ lastMqaDataSent,
277
+ mediaType,
278
+ }) => {
136
279
  const sendrecvType = STATS.RECEIVE_DIRECTION;
137
280
 
138
281
  const lastPacketsReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsReceived || 0;
@@ -145,148 +288,153 @@ export const getVideoReceiverMqa = ({videoReceiver, statsResults, lastMqaDataSen
145
288
  const lastPliCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalPliCount || 0;
146
289
 
147
290
  const {csi} = statsResults[mediaType];
148
- if (csi && !videoReceiver.streams[0].common.csi.includes(csi)) {
149
- videoReceiver.streams[0].common.csi.push(csi);
291
+ if (csi && !videoReceiverStream.common.csi.includes(csi)) {
292
+ videoReceiverStream.common.csi.push(csi);
150
293
  }
151
294
 
152
- videoReceiver.common.common.direction = statsResults[mediaType].direction;
153
- videoReceiver.common.common.isMain = !mediaType.includes('-share');
154
- videoReceiver.common.transportType = statsResults.connectionType.local.transport;
155
-
156
- // collect the packets received for the last min
157
- videoReceiver.common.rtpPackets =
295
+ videoReceiverStream.common.rtpPackets =
158
296
  statsResults[mediaType][sendrecvType].totalPacketsReceived - lastPacketsReceived || 0;
159
- videoReceiver.streams[0].common.rtpPackets = videoReceiver.common.rtpPackets;
160
297
 
161
- // Hop by hop are numbers and not percentage so we compare on what we sent the last min
162
- // this is including packet lost
163
- const totalPacketsLost =
298
+ const totalPacketLoss =
164
299
  statsResults[mediaType][sendrecvType].totalPacketsLost - lastPacketsLost || 0;
165
- videoReceiver.common.mediaHopByHopLost = totalPacketsLost;
166
- videoReceiver.common.rtpHopByHopLost = totalPacketsLost;
167
300
 
168
301
  // End to end packetloss is after recovery
169
- videoReceiver.streams[0].common.rtpEndToEndLost = totalPacketsLost;
302
+ videoReceiverStream.common.rtpEndToEndLost = totalPacketLoss;
170
303
 
171
- // calculate this values
172
-
173
- videoReceiver.common.maxRemoteJitter =
304
+ videoReceiverStream.common.rtpJitter =
174
305
  // @ts-ignore
175
306
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
176
- videoReceiver.common.meanRemoteJitter =
177
- mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
178
307
 
179
- videoReceiver.streams[0].common.rtpJitter = videoReceiver.common.maxRemoteJitter;
180
-
181
- // Calculate the outgoing bitrate
182
308
  const totalBytesReceivedInaMin =
183
309
  statsResults[mediaType][sendrecvType].totalBytesReceived - lastBytesReceived;
184
-
185
- videoReceiver.streams[0].common.receivedBitrate = totalBytesReceivedInaMin
310
+ videoReceiverStream.common.receivedBitrate = totalBytesReceivedInaMin
186
311
  ? (totalBytesReceivedInaMin * 8) / 60
187
312
  : 0;
188
- videoReceiver.common.rtpBitrate = videoReceiver.streams[0].common.receivedBitrate;
189
313
 
190
- // From tracks //TODO: calculate a proper one
191
314
  const totalFrameReceivedInaMin =
192
315
  statsResults[mediaType][sendrecvType].framesReceived - lastFramesReceived;
193
316
  const totalFrameDecodedInaMin =
194
317
  statsResults[mediaType][sendrecvType].framesDecoded - lastFramesDecoded;
195
318
 
196
- videoReceiver.streams[0].common.receivedFrameRate = Math.round(
319
+ videoReceiverStream.common.receivedFrameRate = Math.round(
197
320
  totalFrameReceivedInaMin ? totalFrameReceivedInaMin / 60 : 0
198
321
  );
199
- videoReceiver.streams[0].common.renderedFrameRate = Math.round(
322
+ videoReceiverStream.common.renderedFrameRate = Math.round(
200
323
  totalFrameDecodedInaMin ? totalFrameDecodedInaMin / 60 : 0
201
324
  );
202
325
 
203
- videoReceiver.streams[0].common.framesDropped =
204
- statsResults[mediaType][sendrecvType].framesDropped - lastFramesDropped;
205
- videoReceiver.streams[0].receivedHeight = statsResults[mediaType][sendrecvType].height || 0;
206
- videoReceiver.streams[0].receivedWidth = statsResults[mediaType][sendrecvType].width || 0;
207
- videoReceiver.streams[0].receivedFrameSize =
208
- (videoReceiver.streams[0].receivedHeight * videoReceiver.streams[0].receivedWidth) / 256;
326
+ videoReceiverStream.common.framesDropped =
327
+ statsResults[mediaType][sendrecvType].framesDropped - lastFramesDropped || 0;
328
+ videoReceiverStream.receivedHeight = statsResults[mediaType][sendrecvType].height || 0;
329
+ videoReceiverStream.receivedWidth = statsResults[mediaType][sendrecvType].width || 0;
330
+ videoReceiverStream.receivedFrameSize =
331
+ (videoReceiverStream.receivedHeight * videoReceiverStream.receivedWidth) / 256;
209
332
 
210
- videoReceiver.streams[0].receivedKeyFrames =
333
+ videoReceiverStream.receivedKeyFrames =
211
334
  statsResults[mediaType][sendrecvType].keyFramesDecoded - lastKeyFramesDecoded || 0;
212
- videoReceiver.streams[0].requestedKeyFrames =
335
+ videoReceiverStream.requestedKeyFrames =
213
336
  statsResults[mediaType][sendrecvType].totalPliCount - lastPliCount || 0;
214
337
  };
215
338
 
216
- export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, mediaType}) => {
339
+ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, baseMediaType}) => {
217
340
  const sendrecvType = STATS.SEND_DIRECTION;
218
341
 
219
- const lastPacketsSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsSent || 0;
220
- const lastPacketsLost =
221
- lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLostOnReceiver || 0;
222
- const lastBytesSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesSent || 0;
223
- const lastKeyFramesEncoded =
224
- lastMqaDataSent[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
225
- const lastFirCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalFirCount || 0;
226
- const lastFramesSent = lastMqaDataSent[mediaType]?.[sendrecvType].framesSent || 0;
227
- const {csi} = statsResults[mediaType];
228
- if (csi && !videoSender.streams[0].common.csi.includes(csi)) {
229
- videoSender.streams[0].common.csi.push(csi);
230
- }
342
+ const getLastTotalValue = (value: string) =>
343
+ getTotalValueFromBaseType(lastMqaDataSent, sendrecvType, baseMediaType, value);
344
+ const getTotalValue = (value: string) =>
345
+ getTotalValueFromBaseType(statsResults, sendrecvType, baseMediaType, value);
346
+
347
+ const lastPacketsSent = getLastTotalValue('totalPacketsSent');
348
+ const lastBytesSent = getLastTotalValue('totalBytesSent');
349
+ const lastPacketsLostTotal = getLastTotalValue('totalPacketsLostOnReceiver');
350
+
351
+ const totalPacketsLostOnReceiver = getTotalValue('totalPacketsLostOnReceiver');
352
+ const totalPacketsSent = getTotalValue('totalPacketsSent');
353
+ const totalBytesSent = getTotalValue('totalBytesSent');
354
+ const availableOutgoingBitrate = getTotalValue('availableOutgoingBitrate');
231
355
 
232
- videoSender.common.common.direction = statsResults[mediaType].direction;
233
- videoSender.common.common.isMain = !mediaType.includes('-share');
356
+ videoSender.common.common.direction =
357
+ statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
358
+ ?.direction || 'inactive';
359
+ videoSender.common.common.isMain = !baseMediaType.includes('-share');
234
360
  videoSender.common.transportType = statsResults.connectionType.local.transport;
235
361
 
362
+ const meanRemoteJitter = Object.keys(statsResults)
363
+ .filter((mt) => mt.includes(baseMediaType))
364
+ .reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRemoteJitter), []);
365
+ const meanRoundTripTime = Object.keys(statsResults)
366
+ .filter((mt) => mt.includes(baseMediaType))
367
+ .reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRoundTripTime), []);
368
+
236
369
  // @ts-ignore
237
- videoSender.common.maxRemoteJitter =
238
- // @ts-ignore
239
- max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
240
- videoSender.common.meanRemoteJitter =
241
- mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
370
+ videoSender.common.maxRemoteJitter = max(meanRemoteJitter) * 1000 || 0;
371
+ videoSender.common.meanRemoteJitter = mean(meanRemoteJitter) * 1000 || 0;
242
372
 
243
- videoSender.common.rtpPackets =
244
- statsResults[mediaType][sendrecvType].totalPacketsSent - lastPacketsSent || 0;
245
- videoSender.common.availableBitrate =
246
- statsResults[mediaType][sendrecvType].availableOutgoingBitrate || 0;
247
- // Calculate based on how much packets lost of received compated to how to the client sent
373
+ videoSender.common.rtpPackets = totalPacketsSent - lastPacketsSent;
374
+ videoSender.common.availableBitrate = availableOutgoingBitrate;
248
375
 
249
- const totalpacketsLostForaMin =
250
- statsResults[mediaType][sendrecvType].totalPacketsLostOnReceiver - lastPacketsLost;
376
+ // Calculate based on how much packets lost of received compated to how to the client sent
377
+ const totalPacketsLostForaMin = totalPacketsLostOnReceiver - lastPacketsLostTotal;
251
378
 
252
379
  videoSender.common.remoteLossRate =
253
- videoSender.common.rtpPackets > 0
254
- ? (totalpacketsLostForaMin * 100) / videoSender.common.rtpPackets
380
+ totalPacketsSent - lastPacketsSent > 0
381
+ ? (totalPacketsLostForaMin * 100) / (totalPacketsSent - lastPacketsSent)
255
382
  : 0; // This is the packets sent with in last min || 0;
256
383
 
257
- videoSender.common.maxRoundTripTime =
258
- // @ts-ignore
259
- max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
260
- videoSender.common.meanRoundTripTime =
261
- mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
384
+ videoSender.common.maxRoundTripTime = max(meanRoundTripTime) * 1000 || 0;
385
+ videoSender.common.meanRoundTripTime = mean(meanRoundTripTime) * 1000 || 0;
262
386
  videoSender.common.roundTripTime = videoSender.common.maxRoundTripTime;
263
387
 
264
- videoSender.streams[0].common.rtpPackets =
388
+ // Calculate the outgoing bitrate
389
+ const totalBytesSentInaMin = totalBytesSent - lastBytesSent;
390
+
391
+ videoSender.common.rtpBitrate = totalBytesSentInaMin ? (totalBytesSentInaMin * 8) / 60 : 0;
392
+ };
393
+
394
+ export const getVideoSenderStreamMqa = ({
395
+ videoSenderStream,
396
+ statsResults,
397
+ lastMqaDataSent,
398
+ mediaType,
399
+ }) => {
400
+ const sendrecvType = STATS.SEND_DIRECTION;
401
+
402
+ const lastPacketsSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsSent || 0;
403
+ const lastBytesSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesSent || 0;
404
+ const lastKeyFramesEncoded =
405
+ lastMqaDataSent[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
406
+ const lastFirCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalFirCount || 0;
407
+ const lastFramesSent = lastMqaDataSent[mediaType]?.[sendrecvType].framesSent || 0;
408
+
409
+ const {csi} = statsResults[mediaType];
410
+ if (csi && !videoSenderStream.common.csi.includes(csi)) {
411
+ videoSenderStream.common.csi.push(csi);
412
+ }
413
+
414
+ videoSenderStream.common.rtpPackets =
265
415
  statsResults[mediaType][sendrecvType].totalPacketsSent - lastPacketsSent || 0;
266
416
 
267
417
  // Calculate the outgoing bitrate
268
418
  const totalBytesSentInaMin = statsResults[mediaType][sendrecvType].totalBytesSent - lastBytesSent;
269
419
 
270
- videoSender.streams[0].common.transmittedBitrate = totalBytesSentInaMin
420
+ videoSenderStream.common.transmittedBitrate = totalBytesSentInaMin
271
421
  ? (totalBytesSentInaMin * 8) / 60
272
422
  : 0;
273
423
 
274
- videoSender.common.rtpBitrate = videoSender.streams[0].common.transmittedBitrate;
275
-
276
- videoSender.streams[0].transmittedKeyFrames =
424
+ videoSenderStream.transmittedKeyFrames =
277
425
  statsResults[mediaType][sendrecvType].totalKeyFramesEncoded - lastKeyFramesEncoded || 0;
278
- videoSender.streams[0].requestedKeyFrames =
426
+ videoSenderStream.requestedKeyFrames =
279
427
  statsResults[mediaType][sendrecvType].totalFirCount - lastFirCount || 0;
280
428
 
281
429
  // From tracks //TODO: calculate a proper one
282
430
  const totalFrameSentInaMin =
283
431
  statsResults[mediaType][sendrecvType].framesSent - (lastFramesSent || 0);
284
432
 
285
- videoSender.streams[0].common.transmittedFrameRate = Math.round(
433
+ videoSenderStream.common.transmittedFrameRate = Math.round(
286
434
  totalFrameSentInaMin ? totalFrameSentInaMin / 60 : 0
287
435
  );
288
- videoSender.streams[0].transmittedHeight = statsResults[mediaType][sendrecvType].height || 0;
289
- videoSender.streams[0].transmittedWidth = statsResults[mediaType][sendrecvType].width || 0;
290
- videoSender.streams[0].transmittedFrameSize =
291
- (videoSender.streams[0].transmittedHeight * videoSender.streams[0].transmittedWidth) / 256;
436
+ videoSenderStream.transmittedHeight = statsResults[mediaType][sendrecvType].height || 0;
437
+ videoSenderStream.transmittedWidth = statsResults[mediaType][sendrecvType].width || 0;
438
+ videoSenderStream.transmittedFrameSize =
439
+ (videoSenderStream.transmittedHeight * videoSenderStream.transmittedWidth) / 256;
292
440
  };