@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.
- 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.d.ts +103 -99
- package/dist/mediaQualityMetrics/config.js +133 -129
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/index.js +4 -2
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.d.ts +2 -0
- package/dist/meeting/request.js +4 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meetings/index.js +19 -0
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +1 -1
- package/dist/meetings/util.js.map +1 -1
- package/dist/metrics/constants.d.ts +2 -0
- package/dist/metrics/constants.js +3 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/index.js +14 -20
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +63 -43
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/turnDiscovery.d.ts +18 -2
- package/dist/roap/turnDiscovery.js +163 -69
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/index.d.ts +7 -0
- package/dist/rtcMetrics/index.js +38 -1
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +135 -23
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +28 -4
- package/dist/statsAnalyzer/mqaUtil.js +278 -148
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +21 -21
- package/src/mediaQualityMetrics/config.ts +107 -107
- package/src/meeting/index.ts +2 -0
- package/src/meeting/request.ts +6 -0
- package/src/meetings/index.ts +22 -0
- package/src/meetings/util.ts +1 -1
- package/src/metrics/constants.ts +2 -0
- package/src/reachability/index.ts +0 -6
- package/src/reconnection-manager/index.ts +18 -7
- package/src/roap/turnDiscovery.ts +100 -24
- package/src/rtcMetrics/index.ts +43 -1
- package/src/statsAnalyzer/index.ts +158 -24
- package/src/statsAnalyzer/mqaUtil.ts +302 -154
- package/test/unit/spec/meeting/index.js +46 -0
- package/test/unit/spec/meeting/request.js +2 -0
- package/test/unit/spec/meetings/utils.js +35 -8
- package/test/unit/spec/reachability/index.ts +74 -0
- package/test/unit/spec/reconnection-manager/index.js +36 -1
- package/test/unit/spec/roap/turnDiscovery.ts +326 -76
- package/test/unit/spec/rtcMetrics/index.ts +32 -3
- package/test/unit/spec/stats-analyzer/index.js +439 -1
- 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
|
-
|
|
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 && !
|
|
22
|
-
|
|
94
|
+
if (csi && !audioReceiverStream.common.csi.includes(csi)) {
|
|
95
|
+
audioReceiverStream.common.csi.push(csi);
|
|
23
96
|
}
|
|
24
97
|
|
|
25
|
-
|
|
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
|
-
|
|
101
|
+
audioReceiverStream.common.maxRtpJitter =
|
|
42
102
|
// @ts-ignore
|
|
43
103
|
max(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
|
|
44
|
-
|
|
104
|
+
audioReceiverStream.common.meanRtpJitter =
|
|
45
105
|
mean(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
|
|
46
|
-
|
|
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
|
-
|
|
114
|
+
audioReceiverStream.common.rtpEndToEndLost =
|
|
56
115
|
statsResults[mediaType][sendrecvType].totalPacketsLost - lastPacketsLost - fecRecovered || 0;
|
|
57
116
|
|
|
58
|
-
|
|
117
|
+
audioReceiverStream.common.framesDropped =
|
|
59
118
|
statsResults[mediaType][sendrecvType].totalSamplesDecoded - lastPacketsDecoded || 0;
|
|
60
|
-
|
|
61
|
-
(
|
|
119
|
+
audioReceiverStream.common.renderedFrameRate =
|
|
120
|
+
(audioReceiverStream.common.framesDropped * 100) / 60 || 0;
|
|
62
121
|
|
|
63
|
-
|
|
122
|
+
audioReceiverStream.common.framesReceived =
|
|
64
123
|
statsResults[mediaType][sendrecvType].totalSamplesReceived - lastSamplesReceived || 0;
|
|
65
|
-
|
|
124
|
+
audioReceiverStream.common.concealedFrames =
|
|
66
125
|
statsResults[mediaType][sendrecvType].concealedSamples - lastConcealedSamples || 0;
|
|
67
|
-
|
|
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,
|
|
130
|
+
export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent, baseMediaType}) => {
|
|
74
131
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
75
132
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
84
|
-
|
|
85
|
-
|
|
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 =
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
107
|
-
statsResults[mediaType][sendrecvType].totalPacketsLostOnReceiver - lastPacketsLost;
|
|
108
|
-
|
|
171
|
+
const totalPacketsLostForaMin = totalPacketsLostOnReceiver - lastPacketsLostTotal;
|
|
109
172
|
audioSender.common.remoteLossRate =
|
|
110
|
-
|
|
111
|
-
? (
|
|
112
|
-
: 0; // This is the packets sent with in last min
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
215
|
+
audioSenderStream.transmittedKeyFrames =
|
|
130
216
|
statsResults[mediaType][sendrecvType].totalKeyFramesEncoded - lastFramesEncoded || 0;
|
|
131
|
-
|
|
217
|
+
audioSenderStream.requestedKeyFrames =
|
|
132
218
|
statsResults[mediaType][sendrecvType].totalFirCount - lastFirCount || 0;
|
|
133
219
|
};
|
|
134
220
|
|
|
135
|
-
export const getVideoReceiverMqa = ({
|
|
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 && !
|
|
149
|
-
|
|
291
|
+
if (csi && !videoReceiverStream.common.csi.includes(csi)) {
|
|
292
|
+
videoReceiverStream.common.csi.push(csi);
|
|
150
293
|
}
|
|
151
294
|
|
|
152
|
-
|
|
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
|
-
|
|
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
|
-
|
|
302
|
+
videoReceiverStream.common.rtpEndToEndLost = totalPacketLoss;
|
|
170
303
|
|
|
171
|
-
|
|
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
|
-
|
|
319
|
+
videoReceiverStream.common.receivedFrameRate = Math.round(
|
|
197
320
|
totalFrameReceivedInaMin ? totalFrameReceivedInaMin / 60 : 0
|
|
198
321
|
);
|
|
199
|
-
|
|
322
|
+
videoReceiverStream.common.renderedFrameRate = Math.round(
|
|
200
323
|
totalFrameDecodedInaMin ? totalFrameDecodedInaMin / 60 : 0
|
|
201
324
|
);
|
|
202
325
|
|
|
203
|
-
|
|
204
|
-
statsResults[mediaType][sendrecvType].framesDropped - lastFramesDropped;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
(
|
|
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
|
-
|
|
333
|
+
videoReceiverStream.receivedKeyFrames =
|
|
211
334
|
statsResults[mediaType][sendrecvType].keyFramesDecoded - lastKeyFramesDecoded || 0;
|
|
212
|
-
|
|
335
|
+
videoReceiverStream.requestedKeyFrames =
|
|
213
336
|
statsResults[mediaType][sendrecvType].totalPliCount - lastPliCount || 0;
|
|
214
337
|
};
|
|
215
338
|
|
|
216
|
-
export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent,
|
|
339
|
+
export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, baseMediaType}) => {
|
|
217
340
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
218
341
|
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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 =
|
|
233
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
250
|
-
|
|
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
|
-
|
|
254
|
-
? (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
420
|
+
videoSenderStream.common.transmittedBitrate = totalBytesSentInaMin
|
|
271
421
|
? (totalBytesSentInaMin * 8) / 60
|
|
272
422
|
: 0;
|
|
273
423
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
videoSender.streams[0].transmittedKeyFrames =
|
|
424
|
+
videoSenderStream.transmittedKeyFrames =
|
|
277
425
|
statsResults[mediaType][sendrecvType].totalKeyFramesEncoded - lastKeyFramesEncoded || 0;
|
|
278
|
-
|
|
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
|
-
|
|
433
|
+
videoSenderStream.common.transmittedFrameRate = Math.round(
|
|
286
434
|
totalFrameSentInaMin ? totalFrameSentInaMin / 60 : 0
|
|
287
435
|
);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
(
|
|
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
|
};
|