@100mslive/roomkit-react 0.3.8 → 0.3.9-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  theme,
63
63
  useBorderAudioLevel,
64
64
  useTheme
65
- } from "./chunk-GTJZFIWX.js";
65
+ } from "./chunk-BKAJ6YG4.js";
66
66
  export {
67
67
  Accordion,
68
68
  AudioLevel,
@@ -1322,8 +1322,39 @@
1322
1322
  ],
1323
1323
  "format": "esm"
1324
1324
  },
1325
+ "src/Stats/useQoE.ts": {
1326
+ "bytes": 3123,
1327
+ "imports": [
1328
+ {
1329
+ "path": "react",
1330
+ "kind": "import-statement",
1331
+ "external": true
1332
+ },
1333
+ {
1334
+ "path": "react-use",
1335
+ "kind": "import-statement",
1336
+ "external": true
1337
+ },
1338
+ {
1339
+ "path": "@100mslive/react-sdk",
1340
+ "kind": "import-statement",
1341
+ "external": true
1342
+ },
1343
+ {
1344
+ "path": "<define:process.env>",
1345
+ "kind": "import-statement",
1346
+ "external": true
1347
+ },
1348
+ {
1349
+ "path": "<runtime>",
1350
+ "kind": "import-statement",
1351
+ "external": true
1352
+ }
1353
+ ],
1354
+ "format": "esm"
1355
+ },
1325
1356
  "src/Stats/Stats.tsx": {
1326
- "bytes": 8227,
1357
+ "bytes": 8401,
1327
1358
  "imports": [
1328
1359
  {
1329
1360
  "path": "react",
@@ -1350,6 +1381,11 @@
1350
1381
  "kind": "import-statement",
1351
1382
  "original": "./StyledStats"
1352
1383
  },
1384
+ {
1385
+ "path": "src/Stats/useQoE.ts",
1386
+ "kind": "import-statement",
1387
+ "original": "./useQoE"
1388
+ },
1353
1389
  {
1354
1390
  "path": "<define:process.env>",
1355
1391
  "kind": "import-statement",
@@ -4742,7 +4778,7 @@
4742
4778
  "format": "cjs"
4743
4779
  },
4744
4780
  "../hms-video-store/dist/index.js": {
4745
- "bytes": 332220,
4781
+ "bytes": 332801,
4746
4782
  "imports": [
4747
4783
  {
4748
4784
  "path": "../../node_modules/reselect/es/index.js",
@@ -13907,7 +13943,7 @@
13907
13943
  "imports": [],
13908
13944
  "exports": [],
13909
13945
  "inputs": {},
13910
- "bytes": 3323837
13946
+ "bytes": 3329809
13911
13947
  },
13912
13948
  "dist/index.cjs.js": {
13913
13949
  "imports": [
@@ -14101,6 +14137,21 @@
14101
14137
  "kind": "require-call",
14102
14138
  "external": true
14103
14139
  },
14140
+ {
14141
+ "path": "react-use",
14142
+ "kind": "require-call",
14143
+ "external": true
14144
+ },
14145
+ {
14146
+ "path": "@100mslive/react-sdk",
14147
+ "kind": "require-call",
14148
+ "external": true
14149
+ },
14150
+ {
14151
+ "path": "react",
14152
+ "kind": "require-call",
14153
+ "external": true
14154
+ },
14104
14155
  {
14105
14156
  "path": "@100mslive/react-sdk",
14106
14157
  "kind": "require-call",
@@ -16886,7 +16937,7 @@
16886
16937
  "entryPoint": "src/index.ts",
16887
16938
  "inputs": {
16888
16939
  "<define:process.env>": {
16889
- "bytesInOutput": 18218
16940
+ "bytesInOutput": 18307
16890
16941
  },
16891
16942
  "src/Theme/base.config.ts": {
16892
16943
  "bytesInOutput": 6104
@@ -17068,8 +17119,11 @@
17068
17119
  "src/Stats/StyledStats.tsx": {
17069
17120
  "bytesInOutput": 1004
17070
17121
  },
17122
+ "src/Stats/useQoE.ts": {
17123
+ "bytesInOutput": 3576
17124
+ },
17071
17125
  "src/Stats/Stats.tsx": {
17072
- "bytesInOutput": 9531
17126
+ "bytesInOutput": 9732
17073
17127
  },
17074
17128
  "src/Stats/index.tsx": {
17075
17129
  "bytesInOutput": 129
@@ -17150,7 +17204,7 @@
17150
17204
  "bytesInOutput": 1443
17151
17205
  },
17152
17206
  "src/Prebuilt/components/hooks/useUserPreferences.jsx": {
17153
- "bytesInOutput": 1087
17207
+ "bytesInOutput": 1090
17154
17208
  },
17155
17209
  "src/Prebuilt/components/AppData/useUISettings.js": {
17156
17210
  "bytesInOutput": 7316
@@ -17180,7 +17234,7 @@
17180
17234
  "bytesInOutput": 3003
17181
17235
  },
17182
17236
  "src/Prebuilt/components/AppData/useSidepane.js": {
17183
- "bytesInOutput": 3258
17237
+ "bytesInOutput": 3269
17184
17238
  },
17185
17239
  "src/Prebuilt/components/AppData/AppData.tsx": {
17186
17240
  "bytesInOutput": 6705
@@ -17378,7 +17432,7 @@
17378
17432
  "bytesInOutput": 615
17379
17433
  },
17380
17434
  "../hms-video-store/dist/index.js": {
17381
- "bytesInOutput": 53949
17435
+ "bytesInOutput": 53957
17382
17436
  },
17383
17437
  "src/Prebuilt/components/hooks/usePlaylistMusic.js": {
17384
17438
  "bytesInOutput": 1384
@@ -17399,7 +17453,7 @@
17399
17453
  "bytesInOutput": 4158
17400
17454
  },
17401
17455
  "src/Prebuilt/components/MoreSettings/ChangeNameModal.tsx": {
17402
- "bytesInOutput": 2839
17456
+ "bytesInOutput": 2842
17403
17457
  },
17404
17458
  "src/Prebuilt/components/AppData/useSheet.ts": {
17405
17459
  "bytesInOutput": 1099
@@ -17483,7 +17537,7 @@
17483
17537
  "bytesInOutput": 1729
17484
17538
  },
17485
17539
  "src/Prebuilt/components/Footer/Footer.tsx": {
17486
- "bytesInOutput": 4509
17540
+ "bytesInOutput": 4537
17487
17541
  },
17488
17542
  "src/Prebuilt/components/Notifications/HLSFailureModal.tsx": {
17489
17543
  "bytesInOutput": 2825
@@ -17702,7 +17756,7 @@
17702
17756
  "bytesInOutput": 1620
17703
17757
  },
17704
17758
  "src/Prebuilt/components/hooks/useTileLayout.tsx": {
17705
- "bytesInOutput": 4482
17759
+ "bytesInOutput": 4486
17706
17760
  },
17707
17761
  "src/Prebuilt/components/VideoLayouts/EqualProminence.tsx": {
17708
17762
  "bytesInOutput": 2453
@@ -17807,7 +17861,7 @@
17807
17861
  "bytesInOutput": 2886
17808
17862
  },
17809
17863
  "src/Prebuilt/layouts/HLSView.jsx": {
17810
- "bytesInOutput": 33634
17864
+ "bytesInOutput": 33658
17811
17865
  },
17812
17866
  "src/Prebuilt/layouts/VideoStreamingSection.tsx": {
17813
17867
  "bytesInOutput": 4705
@@ -17945,7 +17999,7 @@
17945
17999
  "bytesInOutput": 2980
17946
18000
  }
17947
18001
  },
17948
- "bytes": 1583280
18002
+ "bytes": 1587273
17949
18003
  }
17950
18004
  }
17951
18005
  }
@@ -1322,8 +1322,39 @@
1322
1322
  ],
1323
1323
  "format": "esm"
1324
1324
  },
1325
+ "src/Stats/useQoE.ts": {
1326
+ "bytes": 3123,
1327
+ "imports": [
1328
+ {
1329
+ "path": "react",
1330
+ "kind": "import-statement",
1331
+ "external": true
1332
+ },
1333
+ {
1334
+ "path": "react-use",
1335
+ "kind": "import-statement",
1336
+ "external": true
1337
+ },
1338
+ {
1339
+ "path": "@100mslive/react-sdk",
1340
+ "kind": "import-statement",
1341
+ "external": true
1342
+ },
1343
+ {
1344
+ "path": "<define:process.env>",
1345
+ "kind": "import-statement",
1346
+ "external": true
1347
+ },
1348
+ {
1349
+ "path": "<runtime>",
1350
+ "kind": "import-statement",
1351
+ "external": true
1352
+ }
1353
+ ],
1354
+ "format": "esm"
1355
+ },
1325
1356
  "src/Stats/Stats.tsx": {
1326
- "bytes": 8227,
1357
+ "bytes": 8401,
1327
1358
  "imports": [
1328
1359
  {
1329
1360
  "path": "react",
@@ -1350,6 +1381,11 @@
1350
1381
  "kind": "import-statement",
1351
1382
  "original": "./StyledStats"
1352
1383
  },
1384
+ {
1385
+ "path": "src/Stats/useQoE.ts",
1386
+ "kind": "import-statement",
1387
+ "original": "./useQoE"
1388
+ },
1353
1389
  {
1354
1390
  "path": "<define:process.env>",
1355
1391
  "kind": "import-statement",
@@ -4742,7 +4778,7 @@
4742
4778
  "format": "cjs"
4743
4779
  },
4744
4780
  "../hms-video-store/dist/index.js": {
4745
- "bytes": 332220,
4781
+ "bytes": 332801,
4746
4782
  "imports": [
4747
4783
  {
4748
4784
  "path": "../../node_modules/reselect/es/index.js",
@@ -13912,7 +13948,7 @@
13912
13948
  "dist/index.js": {
13913
13949
  "imports": [
13914
13950
  {
13915
- "path": "dist/chunk-GTJZFIWX.js",
13951
+ "path": "dist/chunk-BKAJ6YG4.js",
13916
13952
  "kind": "import-statement"
13917
13953
  }
13918
13954
  ],
@@ -13985,16 +14021,16 @@
13985
14021
  "inputs": {},
13986
14022
  "bytes": 1822
13987
14023
  },
13988
- "dist/HLSView-QBQRHXK4.js.map": {
14024
+ "dist/HLSView-SZL2TSWE.js.map": {
13989
14025
  "imports": [],
13990
14026
  "exports": [],
13991
14027
  "inputs": {},
13992
14028
  "bytes": 100708
13993
14029
  },
13994
- "dist/HLSView-QBQRHXK4.js": {
14030
+ "dist/HLSView-SZL2TSWE.js": {
13995
14031
  "imports": [
13996
14032
  {
13997
- "path": "dist/chunk-GTJZFIWX.js",
14033
+ "path": "dist/chunk-BKAJ6YG4.js",
13998
14034
  "kind": "import-statement"
13999
14035
  },
14000
14036
  {
@@ -14230,13 +14266,13 @@
14230
14266
  },
14231
14267
  "bytes": 61939
14232
14268
  },
14233
- "dist/chunk-GTJZFIWX.js.map": {
14269
+ "dist/chunk-BKAJ6YG4.js.map": {
14234
14270
  "imports": [],
14235
14271
  "exports": [],
14236
14272
  "inputs": {},
14237
- "bytes": 3219173
14273
+ "bytes": 3225135
14238
14274
  },
14239
- "dist/chunk-GTJZFIWX.js": {
14275
+ "dist/chunk-BKAJ6YG4.js": {
14240
14276
  "imports": [
14241
14277
  {
14242
14278
  "path": "react",
@@ -14433,6 +14469,21 @@
14433
14469
  "kind": "import-statement",
14434
14470
  "external": true
14435
14471
  },
14472
+ {
14473
+ "path": "react",
14474
+ "kind": "import-statement",
14475
+ "external": true
14476
+ },
14477
+ {
14478
+ "path": "react-use",
14479
+ "kind": "import-statement",
14480
+ "external": true
14481
+ },
14482
+ {
14483
+ "path": "@100mslive/react-sdk",
14484
+ "kind": "import-statement",
14485
+ "external": true
14486
+ },
14436
14487
  {
14437
14488
  "path": "@radix-ui/react-checkbox",
14438
14489
  "kind": "import-statement",
@@ -16654,7 +16705,7 @@
16654
16705
  "external": true
16655
16706
  },
16656
16707
  {
16657
- "path": "dist/HLSView-QBQRHXK4.js",
16708
+ "path": "dist/HLSView-SZL2TSWE.js",
16658
16709
  "kind": "dynamic-import"
16659
16710
  },
16660
16711
  {
@@ -17135,7 +17186,7 @@
17135
17186
  ],
17136
17187
  "inputs": {
17137
17188
  "<define:process.env>": {
17138
- "bytesInOutput": 18218
17189
+ "bytesInOutput": 18307
17139
17190
  },
17140
17191
  "../../node_modules/lodash/lodash.js": {
17141
17192
  "bytesInOutput": 224310
@@ -17330,7 +17381,7 @@
17330
17381
  "bytesInOutput": 27
17331
17382
  },
17332
17383
  "src/Stats/Stats.tsx": {
17333
- "bytesInOutput": 8364
17384
+ "bytesInOutput": 8580
17334
17385
  },
17335
17386
  "src/Stats/formatBytes.ts": {
17336
17387
  "bytesInOutput": 471
@@ -17338,6 +17389,9 @@
17338
17389
  "src/Stats/StyledStats.tsx": {
17339
17390
  "bytesInOutput": 708
17340
17391
  },
17392
+ "src/Stats/useQoE.ts": {
17393
+ "bytesInOutput": 3159
17394
+ },
17341
17395
  "src/Checkbox/Checkbox.tsx": {
17342
17396
  "bytesInOutput": 731
17343
17397
  },
@@ -17489,7 +17543,7 @@
17489
17543
  "bytesInOutput": 606
17490
17544
  },
17491
17545
  "src/Prebuilt/common/hooks.ts": {
17492
- "bytesInOutput": 5956
17546
+ "bytesInOutput": 5957
17493
17547
  },
17494
17548
  "src/Prebuilt/components/Leave/LeaveRoom.tsx": {
17495
17549
  "bytesInOutput": 2454
@@ -17576,7 +17630,7 @@
17576
17630
  "bytesInOutput": 9480
17577
17631
  },
17578
17632
  "../hms-video-store/dist/index.js": {
17579
- "bytesInOutput": 49337
17633
+ "bytesInOutput": 49345
17580
17634
  },
17581
17635
  "../../node_modules/reselect/es/index.js": {
17582
17636
  "bytesInOutput": 2539
@@ -17933,7 +17987,7 @@
17933
17987
  "bytesInOutput": 1204
17934
17988
  },
17935
17989
  "src/Prebuilt/components/hooks/useTileLayout.tsx": {
17936
- "bytesInOutput": 3831
17990
+ "bytesInOutput": 3835
17937
17991
  },
17938
17992
  "src/Prebuilt/components/VideoLayouts/RoleProminence.tsx": {
17939
17993
  "bytesInOutput": 2183
@@ -18101,7 +18155,7 @@
18101
18155
  "bytesInOutput": 651
18102
18156
  }
18103
18157
  },
18104
- "bytes": 1319032
18158
+ "bytes": 1322555
18105
18159
  }
18106
18160
  }
18107
18161
  }
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.3.8",
13
+ "version": "0.3.9-alpha.0",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -82,11 +82,11 @@
82
82
  "react": ">=17.0.2 <19.0.0"
83
83
  },
84
84
  "dependencies": {
85
- "@100mslive/hls-player": "0.3.8",
85
+ "@100mslive/hls-player": "0.3.9-alpha.0",
86
86
  "@100mslive/hms-noise-cancellation": "0.0.1",
87
- "@100mslive/hms-virtual-background": "1.13.8",
88
- "@100mslive/react-icons": "0.10.8",
89
- "@100mslive/react-sdk": "0.10.8",
87
+ "@100mslive/hms-virtual-background": "1.13.9-alpha.0",
88
+ "@100mslive/react-icons": "0.10.9-alpha.0",
89
+ "@100mslive/react-sdk": "0.10.9-alpha.0",
90
90
  "@100mslive/types-prebuilt": "0.12.8",
91
91
  "@emoji-mart/data": "^1.0.6",
92
92
  "@emoji-mart/react": "^1.0.1",
@@ -122,5 +122,5 @@
122
122
  "uuid": "^8.3.2",
123
123
  "worker-timers": "^7.0.40"
124
124
  },
125
- "gitHead": "51bc21610e944d2fb99f12c8f315577d5bc2ca43"
125
+ "gitHead": "0e749918d6dddfed6208acd8e4dbfed267cc751e"
126
126
  }
@@ -13,6 +13,7 @@ import {
13
13
  import { Tooltip } from '../Tooltip';
14
14
  import { formatBytes } from './formatBytes';
15
15
  import { Stats } from './StyledStats';
16
+ import { useQoE } from './useQoE';
16
17
 
17
18
  export interface VideoTileStatsProps {
18
19
  videoTrackID?: HMSTrackID;
@@ -33,6 +34,7 @@ export function VideoTileStats({ videoTrackID, audioTrackID, peerID, isLocal = f
33
34
  const videoTrackStats = isLocal ? localVideoTrackStats?.[0] : remoteVideoTrackStats;
34
35
  const downlinkScore = useHMSStore(selectConnectionQualityByPeerID(peerID))?.downlinkQuality;
35
36
  const availableOutgoingBitrate = useHMSStatsStore(selectHMSStats.availablePublishBitrate);
37
+ const qoe = useQoE({ videoTrackID, audioTrackID, isLocal });
36
38
 
37
39
  // Viewer role - no stats to show
38
40
  if (!(audioTrackStats || videoTrackStats)) {
@@ -87,6 +89,7 @@ export function VideoTileStats({ videoTrackID, audioTrackID, peerID, isLocal = f
87
89
  </Fragment>
88
90
  ) : (
89
91
  <Fragment>
92
+ <StatsRow show={isNotNullish(qoe)} label="QoE" value={qoe} />
90
93
  <StatsRow
91
94
  show={isNotNullishAndNot0(videoTrackStats?.frameWidth)}
92
95
  label="Width"
@@ -0,0 +1,79 @@
1
+ import { useRef } from 'react';
2
+ import { usePrevious } from 'react-use';
3
+ import { HMSTrackID, selectHMSStats, useHMSStatsStore } from '@100mslive/react-sdk';
4
+
5
+ interface UseQoEProps {
6
+ videoTrackID?: HMSTrackID;
7
+ audioTrackID?: HMSTrackID;
8
+ isLocal?: boolean;
9
+ }
10
+
11
+ const EXPECTED_RESOLUTION = 1280 * 720;
12
+
13
+ const clip = (value: number, min_value: number, max_value: number) => {
14
+ return Math.max(Math.min(value, max_value), min_value);
15
+ };
16
+
17
+ /**
18
+ * calculate QoE using 5 params:
19
+ * p1:freeze_duration_norm
20
+ * p2:resolution_norm
21
+ * p3:fps_norm
22
+ * p4:delay_norm
23
+ * p5:audio_concealed_norm
24
+ * the formula is 5*(p1)^3 * (p2)^0.3 * (p3)^0.5 * (p4)^1 * (p5)*2
25
+ *
26
+ * https://github.com/100mslive/webrtc-benchmark/blob/daily/sssd.py#L112
27
+ */
28
+ export const useQoE = ({ videoTrackID, audioTrackID, isLocal = false }: UseQoEProps) => {
29
+ const audioTrackStats = useHMSStatsStore(selectHMSStats.trackStatsByID(audioTrackID));
30
+ const videoTrackStats = useHMSStatsStore(selectHMSStats.trackStatsByID(videoTrackID));
31
+ const prevVideoTrackStats = usePrevious(videoTrackStats);
32
+ const prevAudioTrackStats = usePrevious(audioTrackStats);
33
+
34
+ const prevJitterBufferDelayMs = useRef<number>(0);
35
+
36
+ if (isLocal || (videoTrackID && !videoTrackStats) || (audioTrackID && !audioTrackStats)) {
37
+ return;
38
+ }
39
+
40
+ const resolutionNorm =
41
+ ((videoTrackStats?.frameWidth || 0) * (videoTrackStats?.frameHeight || 0)) / EXPECTED_RESOLUTION;
42
+
43
+ const framesDecodedInLastSec =
44
+ videoTrackStats?.framesDecoded && prevVideoTrackStats?.framesDecoded
45
+ ? videoTrackStats.framesDecoded - prevVideoTrackStats.framesDecoded
46
+ : 0;
47
+ let freezeDurationNorm =
48
+ 1 - ((videoTrackStats?.totalFreezesDuration || 0) - (prevVideoTrackStats?.totalFreezesDuration || 0));
49
+ freezeDurationNorm = freezeDurationNorm < 0 ? 0.5 : freezeDurationNorm;
50
+ freezeDurationNorm = framesDecodedInLastSec === 0 ? 0 : freezeDurationNorm;
51
+
52
+ const fpsNorm = framesDecodedInLastSec / 30;
53
+
54
+ const prevJBDelay = prevVideoTrackStats?.jitterBufferDelay || 0;
55
+ const prevJBEmittedCount = prevVideoTrackStats?.jitterBufferEmittedCount || 0;
56
+ const currentJBDelay = (videoTrackStats?.jitterBufferDelay || 0) - prevJBDelay;
57
+ const currentJBEmittedCount = (videoTrackStats?.jitterBufferEmittedCount || 0) - prevJBEmittedCount;
58
+
59
+ const jitterBufferDelayMs =
60
+ currentJBEmittedCount > 0 ? (currentJBDelay * 1000) / currentJBEmittedCount : prevJitterBufferDelayMs.current;
61
+ prevJitterBufferDelayMs.current = jitterBufferDelayMs;
62
+ const delayNorm = 1 - Math.min(1, jitterBufferDelayMs / 2000);
63
+
64
+ const prevConcealedSamples =
65
+ (prevAudioTrackStats?.concealedSamples || 0) - (prevAudioTrackStats?.silentConcealedSamples || 0);
66
+ const currentConcealedSamples =
67
+ (audioTrackStats?.concealedSamples || 0) - (audioTrackStats?.silentConcealedSamples || 0) - prevConcealedSamples;
68
+
69
+ const audioConcealedNorm = 1 - currentConcealedSamples / 48000;
70
+
71
+ return (
72
+ 5 *
73
+ clip(freezeDurationNorm, 0, 1) ** 3 *
74
+ clip(resolutionNorm, 0, 1) ** 0.3 *
75
+ clip(fpsNorm, 0, 1) ** 0.2 *
76
+ clip(delayNorm, 0, 1) ** 0.5 *
77
+ clip(audioConcealedNorm, 0, 1) ** 2
78
+ ).toFixed(2);
79
+ };