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

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/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
+ };