@stream-io/video-react-sdk 1.33.4 → 1.34.1
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/CHANGELOG.md +29 -0
- package/dist/{background-filters-Zu84SkRR.cjs.js → background-filters-DdQqSx4T.cjs.js} +7 -3
- package/dist/background-filters-DdQqSx4T.cjs.js.map +1 -0
- package/dist/{background-filters-RdXfNf6_.es.js → background-filters-g6ozIvlN.es.js} +7 -3
- package/dist/background-filters-g6ozIvlN.es.js.map +1 -0
- package/dist/css/embedded.css +5 -0
- package/dist/css/embedded.css.map +1 -1
- package/dist/css/styles.css +5 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/{embedded-BackgroundFilters-Zu84SkRR.cjs.js → embedded-BackgroundFilters-DdQqSx4T.cjs.js} +7 -3
- package/dist/embedded-BackgroundFilters-DdQqSx4T.cjs.js.map +1 -0
- package/dist/{embedded-BackgroundFilters-RdXfNf6_.es.js → embedded-BackgroundFilters-g6ozIvlN.es.js} +7 -3
- package/dist/embedded-BackgroundFilters-g6ozIvlN.es.js.map +1 -0
- package/dist/embedded.cjs.js +64 -35
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +64 -35
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +70 -39
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +70 -39
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/BackgroundFilters/types.d.ts +6 -1
- package/dist/src/components/CallControls/RecordCallButton.d.ts +6 -5
- package/dist/src/translations/index.d.ts +1 -0
- package/package.json +5 -5
- package/src/components/BackgroundFilters/BackgroundFilters.tsx +6 -0
- package/src/components/BackgroundFilters/types.ts +7 -0
- package/src/components/CallControls/CallControls.tsx +4 -9
- package/src/components/CallControls/RecordCallButton.tsx +26 -13
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +44 -4
- package/src/translations/en.json +1 -0
- package/dist/background-filters-RdXfNf6_.es.js.map +0 -1
- package/dist/background-filters-Zu84SkRR.cjs.js.map +0 -1
- package/dist/embedded-BackgroundFilters-RdXfNf6_.es.js.map +0 -1
- package/dist/embedded-BackgroundFilters-Zu84SkRR.cjs.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BackgroundBlurLevel, BackgroundFilter, PlatformSupportFlags } from '@stream-io/video-filters-web';
|
|
1
|
+
import type { BackgroundBlurLevel, BackgroundFilter, PlatformSupportFlags, SegmentationOptions } from '@stream-io/video-filters-web';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration for performance metric thresholds.
|
|
4
4
|
*/
|
|
@@ -78,6 +78,11 @@ export type BackgroundFiltersProps = PlatformSupportFlags & {
|
|
|
78
78
|
* Use this to customize when performance warnings are triggered.
|
|
79
79
|
*/
|
|
80
80
|
performanceThresholds?: BackgroundFiltersPerformanceThresholds;
|
|
81
|
+
/**
|
|
82
|
+
* Options for controlling the segmentation mask smoothing in the WebGL shader.
|
|
83
|
+
* Use this to tune the trade-off between mask responsiveness and visual stability.
|
|
84
|
+
*/
|
|
85
|
+
segmentationOptions?: SegmentationOptions;
|
|
81
86
|
};
|
|
82
87
|
/**
|
|
83
88
|
* Represents the possible reasons for background filter performance degradation.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { PropsWithErrorHandler } from '../../utilities/callControlHandler';
|
|
2
|
+
export type RecordCallButtonProps = PropsWithErrorHandler<{
|
|
2
3
|
caption?: string;
|
|
3
|
-
}
|
|
4
|
-
export declare const RecordCallConfirmationButton: (
|
|
4
|
+
}>;
|
|
5
|
+
export declare const RecordCallConfirmationButton: (props: PropsWithErrorHandler<{
|
|
5
6
|
caption?: string;
|
|
6
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
-
export declare const RecordCallButton: (
|
|
7
|
+
}>) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const RecordCallButton: (props: RecordCallButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -86,6 +86,7 @@ export declare const translations: {
|
|
|
86
86
|
"Dominant Speaker": string;
|
|
87
87
|
"Poor connection quality": string;
|
|
88
88
|
"Video paused due to insufficient bandwidth": string;
|
|
89
|
+
"Audio is connecting...": string;
|
|
89
90
|
Participants: string;
|
|
90
91
|
Anonymous: string;
|
|
91
92
|
"No participants found": string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.34.1",
|
|
4
4
|
"main": "./dist/index.cjs.js",
|
|
5
5
|
"module": "./dist/index.es.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@floating-ui/react": "^0.27.6",
|
|
48
|
-
"@stream-io/video-client": "1.44.
|
|
49
|
-
"@stream-io/video-filters-web": "0.7.
|
|
50
|
-
"@stream-io/video-react-bindings": "1.13.
|
|
48
|
+
"@stream-io/video-client": "1.44.5",
|
|
49
|
+
"@stream-io/video-filters-web": "0.7.3",
|
|
50
|
+
"@stream-io/video-react-bindings": "1.13.14",
|
|
51
51
|
"chart.js": "^4.4.4",
|
|
52
52
|
"clsx": "^2.0.0",
|
|
53
53
|
"react-chartjs-2": "^5.3.0"
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@rollup/plugin-replace": "^6.0.2",
|
|
62
62
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
63
63
|
"@stream-io/audio-filters-web": "^0.7.3",
|
|
64
|
-
"@stream-io/video-styling": "^1.
|
|
64
|
+
"@stream-io/video-styling": "^1.12.0",
|
|
65
65
|
"@types/react": "~19.1.17",
|
|
66
66
|
"@types/react-dom": "~19.1.11",
|
|
67
67
|
"react": "19.1.0",
|
|
@@ -105,6 +105,7 @@ export const BackgroundFiltersProvider = (
|
|
|
105
105
|
performanceThresholds,
|
|
106
106
|
forceSafariSupport,
|
|
107
107
|
forceMobileSupport,
|
|
108
|
+
segmentationOptions,
|
|
108
109
|
} = props;
|
|
109
110
|
|
|
110
111
|
const call = useCall();
|
|
@@ -303,6 +304,7 @@ export const BackgroundFiltersProvider = (
|
|
|
303
304
|
modelFilePath,
|
|
304
305
|
basePath,
|
|
305
306
|
onError: handleError,
|
|
307
|
+
segmentationOptions,
|
|
306
308
|
};
|
|
307
309
|
return (
|
|
308
310
|
<ContextProvider.Provider value={contextValue}>
|
|
@@ -374,6 +376,7 @@ const useRenderer = (
|
|
|
374
376
|
backgroundImage,
|
|
375
377
|
modelFilePath,
|
|
376
378
|
basePath,
|
|
379
|
+
segmentationOptions,
|
|
377
380
|
} = api;
|
|
378
381
|
|
|
379
382
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
@@ -419,6 +422,7 @@ const useRenderer = (
|
|
|
419
422
|
backgroundBlurLevel,
|
|
420
423
|
backgroundImage,
|
|
421
424
|
engine,
|
|
425
|
+
modelFilePath,
|
|
422
426
|
});
|
|
423
427
|
|
|
424
428
|
if (!videoEl) {
|
|
@@ -442,6 +446,7 @@ const useRenderer = (
|
|
|
442
446
|
backgroundBlurLevel,
|
|
443
447
|
backgroundImage,
|
|
444
448
|
backgroundFilter,
|
|
449
|
+
segmentationOptions,
|
|
445
450
|
},
|
|
446
451
|
{ onError, onStats },
|
|
447
452
|
);
|
|
@@ -531,6 +536,7 @@ const useRenderer = (
|
|
|
531
536
|
engine,
|
|
532
537
|
modelFilePath,
|
|
533
538
|
basePath,
|
|
539
|
+
segmentationOptions,
|
|
534
540
|
],
|
|
535
541
|
);
|
|
536
542
|
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
BackgroundBlurLevel,
|
|
3
3
|
BackgroundFilter,
|
|
4
4
|
PlatformSupportFlags,
|
|
5
|
+
SegmentationOptions,
|
|
5
6
|
} from '@stream-io/video-filters-web';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -95,6 +96,12 @@ export type BackgroundFiltersProps = PlatformSupportFlags & {
|
|
|
95
96
|
* Use this to customize when performance warnings are triggered.
|
|
96
97
|
*/
|
|
97
98
|
performanceThresholds?: BackgroundFiltersPerformanceThresholds;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Options for controlling the segmentation mask smoothing in the WebGL shader.
|
|
102
|
+
* Use this to tune the trade-off between mask responsiveness and visual stability.
|
|
103
|
+
*/
|
|
104
|
+
segmentationOptions?: SegmentationOptions;
|
|
98
105
|
};
|
|
99
106
|
|
|
100
107
|
/**
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { OwnCapability } from '@stream-io/video-client';
|
|
2
2
|
import { Restricted } from '@stream-io/video-react-bindings';
|
|
3
|
-
import {
|
|
4
|
-
SpeakingWhileMutedNotification,
|
|
5
|
-
MicCaptureErrorNotification,
|
|
6
|
-
} from '../Notification';
|
|
3
|
+
import { SpeakingWhileMutedNotification } from '../Notification';
|
|
7
4
|
import { RecordCallButton } from './RecordCallButton';
|
|
8
5
|
import { ReactionsButton } from './ReactionsButton';
|
|
9
6
|
import { ScreenShareButton } from './ScreenShareButton';
|
|
@@ -18,11 +15,9 @@ export type CallControlsProps = {
|
|
|
18
15
|
export const CallControls = ({ onLeave }: CallControlsProps) => (
|
|
19
16
|
<div className="str-video__call-controls">
|
|
20
17
|
<Restricted requiredGrants={[OwnCapability.SEND_AUDIO]}>
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
</SpeakingWhileMutedNotification>
|
|
25
|
-
</MicCaptureErrorNotification>
|
|
18
|
+
<SpeakingWhileMutedNotification>
|
|
19
|
+
<ToggleAudioPublishingButton />
|
|
20
|
+
</SpeakingWhileMutedNotification>
|
|
26
21
|
</Restricted>
|
|
27
22
|
<Restricted requiredGrants={[OwnCapability.SEND_VIDEO]}>
|
|
28
23
|
<ToggleVideoPublishingButton />
|
|
@@ -16,17 +16,23 @@ import {
|
|
|
16
16
|
} from '../Menu';
|
|
17
17
|
import { LoadingIndicator } from '../LoadingIndicator';
|
|
18
18
|
import { WithTooltip } from '../Tooltip';
|
|
19
|
+
import {
|
|
20
|
+
createCallControlHandler,
|
|
21
|
+
PropsWithErrorHandler,
|
|
22
|
+
} from '../../utilities/callControlHandler';
|
|
19
23
|
|
|
20
|
-
export type RecordCallButtonProps = {
|
|
24
|
+
export type RecordCallButtonProps = PropsWithErrorHandler<{
|
|
21
25
|
caption?: string;
|
|
22
|
-
}
|
|
26
|
+
}>;
|
|
23
27
|
|
|
24
|
-
const RecordEndConfirmation = () => {
|
|
28
|
+
const RecordEndConfirmation = (props: PropsWithErrorHandler) => {
|
|
25
29
|
const { t } = useI18n();
|
|
26
30
|
const { toggleCallRecording, isAwaitingResponse } = useToggleCallRecording();
|
|
27
31
|
|
|
28
32
|
const { close } = useMenuContext();
|
|
29
33
|
|
|
34
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
35
|
+
|
|
30
36
|
return (
|
|
31
37
|
<div className="str-video__end-recording__confirmation">
|
|
32
38
|
<div className="str-video__end-recording__header">
|
|
@@ -42,7 +48,10 @@ const RecordEndConfirmation = () => {
|
|
|
42
48
|
<CompositeButton variant="secondary" onClick={close}>
|
|
43
49
|
{t('Cancel')}
|
|
44
50
|
</CompositeButton>
|
|
45
|
-
<CompositeButton
|
|
51
|
+
<CompositeButton
|
|
52
|
+
variant="primary"
|
|
53
|
+
onClick={isAwaitingResponse ? undefined : handleClick}
|
|
54
|
+
>
|
|
46
55
|
{isAwaitingResponse ? <LoadingIndicator /> : t('End recording')}
|
|
47
56
|
</CompositeButton>
|
|
48
57
|
</div>
|
|
@@ -66,15 +75,16 @@ const ToggleEndRecordingMenuButton = forwardRef<
|
|
|
66
75
|
);
|
|
67
76
|
});
|
|
68
77
|
|
|
69
|
-
export const RecordCallConfirmationButton = (
|
|
70
|
-
caption
|
|
71
|
-
|
|
72
|
-
caption
|
|
73
|
-
}) => {
|
|
78
|
+
export const RecordCallConfirmationButton = (
|
|
79
|
+
props: PropsWithErrorHandler<{ caption?: string }>,
|
|
80
|
+
) => {
|
|
81
|
+
const { caption } = props;
|
|
74
82
|
const { t } = useI18n();
|
|
75
83
|
const { toggleCallRecording, isAwaitingResponse, isCallRecordingInProgress } =
|
|
76
84
|
useToggleCallRecording();
|
|
77
85
|
|
|
86
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
87
|
+
|
|
78
88
|
if (isCallRecordingInProgress) {
|
|
79
89
|
return (
|
|
80
90
|
<Restricted
|
|
@@ -87,7 +97,7 @@ export const RecordCallConfirmationButton = ({
|
|
|
87
97
|
ToggleButton={ToggleEndRecordingMenuButton}
|
|
88
98
|
visualType={MenuVisualType.PORTAL}
|
|
89
99
|
>
|
|
90
|
-
<RecordEndConfirmation />
|
|
100
|
+
<RecordEndConfirmation onError={props.onError} />
|
|
91
101
|
</MenuToggle>
|
|
92
102
|
</Restricted>
|
|
93
103
|
);
|
|
@@ -110,7 +120,7 @@ export const RecordCallConfirmationButton = ({
|
|
|
110
120
|
caption={caption}
|
|
111
121
|
variant="secondary"
|
|
112
122
|
data-testid="recording-start-button"
|
|
113
|
-
onClick={isAwaitingResponse ? undefined :
|
|
123
|
+
onClick={isAwaitingResponse ? undefined : handleClick}
|
|
114
124
|
>
|
|
115
125
|
{isAwaitingResponse ? (
|
|
116
126
|
<LoadingIndicator />
|
|
@@ -123,11 +133,14 @@ export const RecordCallConfirmationButton = ({
|
|
|
123
133
|
);
|
|
124
134
|
};
|
|
125
135
|
|
|
126
|
-
export const RecordCallButton = (
|
|
136
|
+
export const RecordCallButton = (props: RecordCallButtonProps) => {
|
|
137
|
+
const { caption } = props;
|
|
127
138
|
const { t } = useI18n();
|
|
128
139
|
const { toggleCallRecording, isAwaitingResponse, isCallRecordingInProgress } =
|
|
129
140
|
useToggleCallRecording();
|
|
130
141
|
|
|
142
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
143
|
+
|
|
131
144
|
let title = caption ?? t('Record call');
|
|
132
145
|
|
|
133
146
|
if (isAwaitingResponse) {
|
|
@@ -153,7 +166,7 @@ export const RecordCallButton = ({ caption }: RecordCallButtonProps) => {
|
|
|
153
166
|
: 'recording-start-button'
|
|
154
167
|
}
|
|
155
168
|
title={title}
|
|
156
|
-
onClick={isAwaitingResponse ? undefined :
|
|
169
|
+
onClick={isAwaitingResponse ? undefined : handleClick}
|
|
157
170
|
>
|
|
158
171
|
{isAwaitingResponse ? (
|
|
159
172
|
<LoadingIndicator />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, forwardRef } from 'react';
|
|
1
|
+
import { ComponentType, forwardRef, useEffect, useState } from 'react';
|
|
2
2
|
import { Placement } from '@floating-ui/react';
|
|
3
3
|
import {
|
|
4
4
|
hasAudio,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
hasScreenShare,
|
|
7
7
|
hasVideo,
|
|
8
8
|
SfuModels,
|
|
9
|
+
StreamVideoParticipant,
|
|
9
10
|
} from '@stream-io/video-client';
|
|
10
11
|
import { useCall, useI18n } from '@stream-io/video-react-bindings';
|
|
11
12
|
import clsx from 'clsx';
|
|
@@ -13,6 +14,7 @@ import clsx from 'clsx';
|
|
|
13
14
|
import {
|
|
14
15
|
Icon,
|
|
15
16
|
IconButton,
|
|
17
|
+
LoadingIndicator,
|
|
16
18
|
MenuToggle,
|
|
17
19
|
Notification,
|
|
18
20
|
ToggleMenuButtonProps,
|
|
@@ -137,12 +139,20 @@ export const ParticipantDetails = ({
|
|
|
137
139
|
const isTrackPaused =
|
|
138
140
|
trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;
|
|
139
141
|
|
|
142
|
+
const isAudioTrackUnmuted = useIsTrackUnmuted(participant);
|
|
143
|
+
const isAudioConnecting = hasAudioTrack && !isAudioTrackUnmuted;
|
|
144
|
+
|
|
140
145
|
return (
|
|
141
146
|
<>
|
|
142
147
|
<div className="str-video__participant-details">
|
|
143
|
-
<
|
|
148
|
+
<div className="str-video__participant-details__name">
|
|
144
149
|
{name || userId}
|
|
145
|
-
|
|
150
|
+
{indicatorsVisible && isAudioConnecting && (
|
|
151
|
+
<LoadingIndicator
|
|
152
|
+
className="str-video__participant-details__name--audio-connecting"
|
|
153
|
+
tooltip={t('Audio is connecting...')}
|
|
154
|
+
/>
|
|
155
|
+
)}
|
|
146
156
|
{indicatorsVisible && !hasAudioTrack && (
|
|
147
157
|
<span className="str-video__participant-details__name--audio-muted" />
|
|
148
158
|
)}
|
|
@@ -164,7 +174,7 @@ export const ParticipantDetails = ({
|
|
|
164
174
|
/>
|
|
165
175
|
)}
|
|
166
176
|
{indicatorsVisible && <SpeechIndicator />}
|
|
167
|
-
</
|
|
177
|
+
</div>
|
|
168
178
|
</div>
|
|
169
179
|
{indicatorsVisible && (
|
|
170
180
|
<Notification
|
|
@@ -206,3 +216,33 @@ export const SpeechIndicator = () => {
|
|
|
206
216
|
</span>
|
|
207
217
|
);
|
|
208
218
|
};
|
|
219
|
+
|
|
220
|
+
const useIsTrackUnmuted = (participant: StreamVideoParticipant) => {
|
|
221
|
+
const audioStream = participant.audioStream;
|
|
222
|
+
|
|
223
|
+
const [unmuted, setUnmuted] = useState(() => {
|
|
224
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
225
|
+
return !!track && !track.muted;
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
230
|
+
if (!track) return;
|
|
231
|
+
|
|
232
|
+
setUnmuted(!track.muted);
|
|
233
|
+
|
|
234
|
+
const handler = () => {
|
|
235
|
+
setUnmuted(!track.muted);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
track.addEventListener('mute', handler);
|
|
239
|
+
track.addEventListener('unmute', handler);
|
|
240
|
+
|
|
241
|
+
return () => {
|
|
242
|
+
track.removeEventListener('mute', handler);
|
|
243
|
+
track.removeEventListener('unmute', handler);
|
|
244
|
+
};
|
|
245
|
+
}, [audioStream]);
|
|
246
|
+
|
|
247
|
+
return unmuted;
|
|
248
|
+
};
|
package/src/translations/en.json
CHANGED
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
"Dominant Speaker": "Dominant Speaker",
|
|
92
92
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
93
93
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
94
|
+
"Audio is connecting...": "Audio is connecting...",
|
|
94
95
|
|
|
95
96
|
"Participants": "Participants",
|
|
96
97
|
"Anonymous": ", and ({{ count }}) anonymous",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"background-filters-RdXfNf6_.es.js","sources":["../../src/components/BackgroundFilters/BackgroundFilters.tsx"],"sourcesContent":["import {\n Context,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';\nimport { Call, disposeOfMediaStream } from '@stream-io/video-client';\nimport {\n BackgroundBlurLevel,\n createRenderer,\n isMediaPipePlatformSupported,\n isPlatformSupported,\n loadMediaPipe,\n loadTFLite,\n PerformanceStats,\n Renderer,\n TFLite,\n VirtualBackground,\n} from '@stream-io/video-filters-web';\nimport clsx from 'clsx';\nimport type {\n BackgroundFiltersPerformance,\n BackgroundFiltersProps,\n BackgroundFiltersContextValue,\n PerformanceDegradationReason,\n} from './types';\n\n/**\n * Constants for FPS warning calculation.\n * Smooths out quick spikes using an EMA, ignores brief outliers,\n * and uses two thresholds to avoid flickering near the limit.\n */\nconst ALPHA = 0.2;\nconst DEFAULT_FPS = 30;\nconst DEVIATION_LIMIT = 0.5;\nconst OUTLIER_PERSISTENCE = 5;\n\n/**\n * Represents the available background filter processing engines.\n */\nenum FilterEngine {\n TF,\n MEDIA_PIPE,\n NONE,\n}\n\n/**\n * Determines which filter engine is available.\n * MEDIA_PIPE is the default unless legacy filters are requested or MediaPipe is unsupported.\n *\n * Returns NONE if neither is supported.\n */\nconst determineEngine = async (\n useLegacyFilter: boolean | undefined,\n forceSafariSupport: boolean | undefined,\n forceMobileSupport: boolean | undefined,\n): Promise<FilterEngine> => {\n if (useLegacyFilter) {\n const isTfPlatformSupported = await isPlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n return isTfPlatformSupported ? FilterEngine.TF : FilterEngine.NONE;\n }\n\n const isMediaPipeSupported = await isMediaPipePlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n\n return isMediaPipeSupported ? FilterEngine.MEDIA_PIPE : FilterEngine.NONE;\n};\n\n/**\n * A provider component that enables the use of background filters in your app.\n *\n * Please make sure you have the `@stream-io/video-filters-web` package installed\n * in your project before using this component.\n */\nexport const BackgroundFiltersProvider = (\n props: PropsWithChildren<BackgroundFiltersProps> & {\n // for code splitting. Prevents circular dependency issues where\n // this Context needs to be present in the main chunk, but also\n // imported by the background filters chunk.\n ContextProvider: Context<BackgroundFiltersContextValue | undefined>;\n },\n) => {\n const {\n ContextProvider,\n children,\n backgroundImages = [],\n backgroundFilter: bgFilterFromProps = undefined,\n backgroundImage: bgImageFromProps = undefined,\n backgroundBlurLevel: bgBlurLevelFromProps = undefined,\n tfFilePath,\n modelFilePath,\n useLegacyFilter,\n basePath,\n onError,\n performanceThresholds,\n forceSafariSupport,\n forceMobileSupport,\n } = props;\n\n const call = useCall();\n const { useCallStatsReport } = useCallStateHooks();\n const callStatsReport = useCallStatsReport();\n\n const [backgroundFilter, setBackgroundFilter] = useState(bgFilterFromProps);\n const [backgroundImage, setBackgroundImage] = useState(bgImageFromProps);\n const [backgroundBlurLevel, setBackgroundBlurLevel] =\n useState(bgBlurLevelFromProps);\n\n const [showLowFpsWarning, setShowLowFpsWarning] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;\n\n const sourceFps =\n performanceThresholds?.defaultFps || cameraFrameRate || DEFAULT_FPS;\n\n const fpsWarningThresholdLower =\n performanceThresholds?.fpsWarningThresholdLower ?? sourceFps * 0.75;\n const fpsWarningThresholdUpper =\n performanceThresholds?.fpsWarningThresholdUpper ?? sourceFps * 0.85;\n\n const emaRef = useRef<number>(sourceFps);\n const outlierStreakRef = useRef<number>(0);\n\n const handleStats = useCallback(\n (stats: PerformanceStats) => {\n const fps = stats?.fps;\n if (fps === undefined || fps === null) {\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n return;\n }\n\n const prevEma = emaRef.current;\n const deviation = Math.abs(fps - prevEma) / prevEma;\n\n const isOutlier = fps < prevEma && deviation > DEVIATION_LIMIT;\n outlierStreakRef.current = isOutlier ? outlierStreakRef.current + 1 : 0;\n if (isOutlier && outlierStreakRef.current < OUTLIER_PERSISTENCE) return;\n\n emaRef.current = ALPHA * fps + (1 - ALPHA) * prevEma;\n\n setShowLowFpsWarning((prev) => {\n if (prev && emaRef.current > fpsWarningThresholdUpper) return false;\n if (!prev && emaRef.current < fpsWarningThresholdLower) return true;\n\n return prev;\n });\n },\n [fpsWarningThresholdLower, fpsWarningThresholdUpper, sourceFps],\n );\n\n const performance: BackgroundFiltersPerformance = useMemo(() => {\n if (!backgroundFilter) {\n return { degraded: false };\n }\n\n const reasons: Array<PerformanceDegradationReason> = [];\n\n if (showLowFpsWarning) {\n reasons.push('frame-drop');\n }\n\n const qualityLimitationReasons =\n callStatsReport?.publisherStats?.qualityLimitationReasons;\n\n if (\n showLowFpsWarning &&\n qualityLimitationReasons &&\n qualityLimitationReasons?.includes('cpu')\n ) {\n reasons.push('cpu-throttling');\n }\n\n return {\n degraded: reasons.length > 0,\n reason: reasons.length > 0 ? reasons : undefined,\n };\n }, [\n showLowFpsWarning,\n callStatsReport?.publisherStats?.qualityLimitationReasons,\n backgroundFilter,\n ]);\n\n const prevDegradedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n const currentDegraded = performance.degraded;\n const prevDegraded = prevDegradedRef.current;\n\n if (\n !!backgroundFilter &&\n prevDegraded !== undefined &&\n prevDegraded !== currentDegraded\n ) {\n call?.tracer.trace('backgroundFilters.performance', {\n degraded: currentDegraded,\n reason: performance?.reason,\n fps: emaRef.current,\n });\n }\n prevDegradedRef.current = currentDegraded;\n }, [\n performanceThresholds,\n performance.degraded,\n performance.reason,\n backgroundFilter,\n call?.tracer,\n ]);\n\n const applyBackgroundImageFilter = useCallback((imageUrl: string) => {\n setBackgroundFilter('image');\n setBackgroundImage(imageUrl);\n }, []);\n\n const applyBackgroundBlurFilter = useCallback(\n (blurLevel: BackgroundBlurLevel = 'high') => {\n setBackgroundFilter('blur');\n setBackgroundBlurLevel(blurLevel);\n },\n [],\n );\n\n const disableBackgroundFilter = useCallback(() => {\n setBackgroundFilter(undefined);\n setBackgroundImage(undefined);\n setBackgroundBlurLevel(undefined);\n\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n }, [sourceFps]);\n\n const [engine, setEngine] = useState<FilterEngine>(FilterEngine.NONE);\n const [isSupported, setIsSupported] = useState(false);\n useEffect(() => {\n determineEngine(\n useLegacyFilter,\n forceSafariSupport,\n forceMobileSupport,\n ).then((determinedEngine) => {\n setEngine(determinedEngine);\n setIsSupported(determinedEngine !== FilterEngine.NONE);\n });\n }, [forceMobileSupport, forceSafariSupport, useLegacyFilter]);\n\n const [tfLite, setTfLite] = useState<TFLite>();\n useEffect(() => {\n if (engine !== FilterEngine.TF) return;\n\n loadTFLite({ basePath, modelFilePath, tfFilePath })\n .then(setTfLite)\n .catch((err) => console.error('Failed to load TFLite', err));\n }, [basePath, engine, modelFilePath, tfFilePath]);\n\n const [mediaPipe, setMediaPipe] = useState<ArrayBuffer>();\n useEffect(() => {\n if (engine !== FilterEngine.MEDIA_PIPE) return;\n\n loadMediaPipe({\n basePath: basePath,\n modelPath: modelFilePath,\n })\n .then(setMediaPipe)\n .catch((err) => console.error('Failed to preload MediaPipe', err));\n }, [engine, modelFilePath, basePath]);\n\n const handleError = useCallback(\n (error: any) => {\n console.warn(\n '[filters] Filter encountered an error and will be disabled',\n );\n disableBackgroundFilter();\n onError?.(error);\n },\n [disableBackgroundFilter, onError],\n );\n\n const isReady = useLegacyFilter ? !!tfLite : !!mediaPipe;\n const contextValue: BackgroundFiltersContextValue = {\n isSupported,\n performance,\n isReady,\n isLoading,\n backgroundImage,\n backgroundBlurLevel,\n backgroundFilter,\n disableBackgroundFilter,\n applyBackgroundBlurFilter,\n applyBackgroundImageFilter,\n backgroundImages,\n tfFilePath,\n modelFilePath,\n basePath,\n onError: handleError,\n };\n return (\n <ContextProvider.Provider value={contextValue}>\n {children}\n {isReady && (\n <BackgroundFilters\n api={contextValue}\n tfLite={tfLite}\n engine={engine}\n onStats={handleStats}\n setIsLoading={setIsLoading}\n />\n )}\n </ContextProvider.Provider>\n );\n};\n\nconst BackgroundFilters = (props: {\n api: BackgroundFiltersContextValue;\n tfLite?: TFLite;\n engine: FilterEngine;\n onStats: (stats: PerformanceStats) => void;\n setIsLoading: (loading: boolean) => void;\n}) => {\n const call = useCall();\n const { engine, api, tfLite, onStats, setIsLoading } = props;\n const { children, start } = useRenderer(api, tfLite, call, engine);\n const { onError, backgroundFilter } = api;\n const handleErrorRef = useRef<((error: any) => void) | undefined>(undefined);\n handleErrorRef.current = onError;\n\n const handleStatsRef = useRef<\n ((stats: PerformanceStats) => void) | undefined\n >(undefined);\n handleStatsRef.current = onStats;\n\n useEffect(() => {\n if (!call || !backgroundFilter) return;\n\n setIsLoading(true);\n const { unregister, registered } = call.camera.registerFilter((ms) => {\n return start(\n ms,\n (error) => handleErrorRef.current?.(error),\n (stats: PerformanceStats) => handleStatsRef.current?.(stats),\n );\n });\n registered.finally(() => {\n setIsLoading(false);\n });\n\n return () => {\n unregister().catch((err) => console.warn(`Can't unregister filter`, err));\n };\n }, [call, start, backgroundFilter, setIsLoading]);\n\n return children;\n};\n\nconst useRenderer = (\n api: BackgroundFiltersContextValue,\n tfLite: TFLite | undefined,\n call: Call | undefined,\n engine: FilterEngine,\n) => {\n const {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n modelFilePath,\n basePath,\n } = api;\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const bgImageRef = useRef<HTMLImageElement>(null);\n const [videoSize, setVideoSize] = useState<{ width: number; height: number }>(\n {\n width: 1920,\n height: 1080,\n },\n );\n\n const start = useCallback(\n (\n ms: MediaStream,\n onError?: (error: any) => void,\n onStats?: (stats: PerformanceStats) => void,\n ) => {\n let outputStream: MediaStream | undefined;\n let processor: VirtualBackground | undefined;\n let renderer: Renderer | undefined;\n\n const output = new Promise<MediaStream>((resolve, reject) => {\n if (!backgroundFilter) {\n reject(new Error('No filter specified'));\n return;\n }\n\n const videoEl = videoRef.current;\n const canvasEl = canvasRef.current;\n const bgImageEl = bgImageRef.current;\n\n const [track] = ms.getVideoTracks();\n\n if (!track) {\n reject(new Error('No video tracks in input media stream'));\n return;\n }\n\n if (engine === FilterEngine.MEDIA_PIPE) {\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!videoEl) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n\n processor = new VirtualBackground(\n track,\n {\n basePath: basePath,\n modelPath: modelFilePath,\n backgroundBlurLevel,\n backgroundImage,\n backgroundFilter,\n },\n { onError, onStats },\n );\n processor\n .start()\n .then((processedTrack) => {\n outputStream = new MediaStream([processedTrack]);\n resolve(outputStream);\n })\n .catch((error) => {\n reject(error);\n });\n\n return;\n }\n\n if (engine === FilterEngine.TF) {\n if (!videoEl || !canvasEl || (backgroundImage && !bgImageEl)) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n videoEl.srcObject = ms;\n videoEl.play().then(\n () => {\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!tfLite) {\n reject(new Error('TensorFlow Lite not loaded'));\n return;\n }\n\n renderer = createRenderer(\n tfLite,\n videoEl,\n canvasEl,\n {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage: bgImageEl ?? undefined,\n },\n onError,\n );\n outputStream = canvasEl.captureStream();\n\n resolve(outputStream);\n },\n () => {\n reject(new Error('Could not play the source video stream'));\n },\n );\n return;\n }\n\n reject(new Error('No supported engine available'));\n });\n\n return {\n output,\n stop: () => {\n call?.tracer.trace('backgroundFilters.disable', null);\n processor?.stop();\n renderer?.dispose();\n if (videoRef.current) videoRef.current.srcObject = null;\n if (outputStream) disposeOfMediaStream(outputStream);\n },\n };\n },\n [\n backgroundBlurLevel,\n backgroundFilter,\n backgroundImage,\n call?.tracer,\n tfLite,\n engine,\n modelFilePath,\n basePath,\n ],\n );\n\n const children = (\n <div className=\"str-video__background-filters\">\n <video\n className={clsx(\n 'str-video__background-filters__video',\n videoSize.height > videoSize.width &&\n 'str-video__background-filters__video--tall',\n )}\n ref={videoRef}\n playsInline\n muted\n controls={false}\n {...videoSize}\n />\n {backgroundImage && (\n <img\n className=\"str-video__background-filters__background-image\"\n alt=\"Background\"\n ref={bgImageRef}\n crossOrigin=\"anonymous\"\n src={backgroundImage}\n {...videoSize}\n />\n )}\n <canvas\n className=\"str-video__background-filters__target-canvas\"\n {...videoSize}\n ref={canvasRef}\n />\n </div>\n );\n\n return { start, children };\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"background-filters-Zu84SkRR.cjs.js","sources":["../../src/components/BackgroundFilters/BackgroundFilters.tsx"],"sourcesContent":["import {\n Context,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';\nimport { Call, disposeOfMediaStream } from '@stream-io/video-client';\nimport {\n BackgroundBlurLevel,\n createRenderer,\n isMediaPipePlatformSupported,\n isPlatformSupported,\n loadMediaPipe,\n loadTFLite,\n PerformanceStats,\n Renderer,\n TFLite,\n VirtualBackground,\n} from '@stream-io/video-filters-web';\nimport clsx from 'clsx';\nimport type {\n BackgroundFiltersPerformance,\n BackgroundFiltersProps,\n BackgroundFiltersContextValue,\n PerformanceDegradationReason,\n} from './types';\n\n/**\n * Constants for FPS warning calculation.\n * Smooths out quick spikes using an EMA, ignores brief outliers,\n * and uses two thresholds to avoid flickering near the limit.\n */\nconst ALPHA = 0.2;\nconst DEFAULT_FPS = 30;\nconst DEVIATION_LIMIT = 0.5;\nconst OUTLIER_PERSISTENCE = 5;\n\n/**\n * Represents the available background filter processing engines.\n */\nenum FilterEngine {\n TF,\n MEDIA_PIPE,\n NONE,\n}\n\n/**\n * Determines which filter engine is available.\n * MEDIA_PIPE is the default unless legacy filters are requested or MediaPipe is unsupported.\n *\n * Returns NONE if neither is supported.\n */\nconst determineEngine = async (\n useLegacyFilter: boolean | undefined,\n forceSafariSupport: boolean | undefined,\n forceMobileSupport: boolean | undefined,\n): Promise<FilterEngine> => {\n if (useLegacyFilter) {\n const isTfPlatformSupported = await isPlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n return isTfPlatformSupported ? FilterEngine.TF : FilterEngine.NONE;\n }\n\n const isMediaPipeSupported = await isMediaPipePlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n\n return isMediaPipeSupported ? FilterEngine.MEDIA_PIPE : FilterEngine.NONE;\n};\n\n/**\n * A provider component that enables the use of background filters in your app.\n *\n * Please make sure you have the `@stream-io/video-filters-web` package installed\n * in your project before using this component.\n */\nexport const BackgroundFiltersProvider = (\n props: PropsWithChildren<BackgroundFiltersProps> & {\n // for code splitting. Prevents circular dependency issues where\n // this Context needs to be present in the main chunk, but also\n // imported by the background filters chunk.\n ContextProvider: Context<BackgroundFiltersContextValue | undefined>;\n },\n) => {\n const {\n ContextProvider,\n children,\n backgroundImages = [],\n backgroundFilter: bgFilterFromProps = undefined,\n backgroundImage: bgImageFromProps = undefined,\n backgroundBlurLevel: bgBlurLevelFromProps = undefined,\n tfFilePath,\n modelFilePath,\n useLegacyFilter,\n basePath,\n onError,\n performanceThresholds,\n forceSafariSupport,\n forceMobileSupport,\n } = props;\n\n const call = useCall();\n const { useCallStatsReport } = useCallStateHooks();\n const callStatsReport = useCallStatsReport();\n\n const [backgroundFilter, setBackgroundFilter] = useState(bgFilterFromProps);\n const [backgroundImage, setBackgroundImage] = useState(bgImageFromProps);\n const [backgroundBlurLevel, setBackgroundBlurLevel] =\n useState(bgBlurLevelFromProps);\n\n const [showLowFpsWarning, setShowLowFpsWarning] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;\n\n const sourceFps =\n performanceThresholds?.defaultFps || cameraFrameRate || DEFAULT_FPS;\n\n const fpsWarningThresholdLower =\n performanceThresholds?.fpsWarningThresholdLower ?? sourceFps * 0.75;\n const fpsWarningThresholdUpper =\n performanceThresholds?.fpsWarningThresholdUpper ?? sourceFps * 0.85;\n\n const emaRef = useRef<number>(sourceFps);\n const outlierStreakRef = useRef<number>(0);\n\n const handleStats = useCallback(\n (stats: PerformanceStats) => {\n const fps = stats?.fps;\n if (fps === undefined || fps === null) {\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n return;\n }\n\n const prevEma = emaRef.current;\n const deviation = Math.abs(fps - prevEma) / prevEma;\n\n const isOutlier = fps < prevEma && deviation > DEVIATION_LIMIT;\n outlierStreakRef.current = isOutlier ? outlierStreakRef.current + 1 : 0;\n if (isOutlier && outlierStreakRef.current < OUTLIER_PERSISTENCE) return;\n\n emaRef.current = ALPHA * fps + (1 - ALPHA) * prevEma;\n\n setShowLowFpsWarning((prev) => {\n if (prev && emaRef.current > fpsWarningThresholdUpper) return false;\n if (!prev && emaRef.current < fpsWarningThresholdLower) return true;\n\n return prev;\n });\n },\n [fpsWarningThresholdLower, fpsWarningThresholdUpper, sourceFps],\n );\n\n const performance: BackgroundFiltersPerformance = useMemo(() => {\n if (!backgroundFilter) {\n return { degraded: false };\n }\n\n const reasons: Array<PerformanceDegradationReason> = [];\n\n if (showLowFpsWarning) {\n reasons.push('frame-drop');\n }\n\n const qualityLimitationReasons =\n callStatsReport?.publisherStats?.qualityLimitationReasons;\n\n if (\n showLowFpsWarning &&\n qualityLimitationReasons &&\n qualityLimitationReasons?.includes('cpu')\n ) {\n reasons.push('cpu-throttling');\n }\n\n return {\n degraded: reasons.length > 0,\n reason: reasons.length > 0 ? reasons : undefined,\n };\n }, [\n showLowFpsWarning,\n callStatsReport?.publisherStats?.qualityLimitationReasons,\n backgroundFilter,\n ]);\n\n const prevDegradedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n const currentDegraded = performance.degraded;\n const prevDegraded = prevDegradedRef.current;\n\n if (\n !!backgroundFilter &&\n prevDegraded !== undefined &&\n prevDegraded !== currentDegraded\n ) {\n call?.tracer.trace('backgroundFilters.performance', {\n degraded: currentDegraded,\n reason: performance?.reason,\n fps: emaRef.current,\n });\n }\n prevDegradedRef.current = currentDegraded;\n }, [\n performanceThresholds,\n performance.degraded,\n performance.reason,\n backgroundFilter,\n call?.tracer,\n ]);\n\n const applyBackgroundImageFilter = useCallback((imageUrl: string) => {\n setBackgroundFilter('image');\n setBackgroundImage(imageUrl);\n }, []);\n\n const applyBackgroundBlurFilter = useCallback(\n (blurLevel: BackgroundBlurLevel = 'high') => {\n setBackgroundFilter('blur');\n setBackgroundBlurLevel(blurLevel);\n },\n [],\n );\n\n const disableBackgroundFilter = useCallback(() => {\n setBackgroundFilter(undefined);\n setBackgroundImage(undefined);\n setBackgroundBlurLevel(undefined);\n\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n }, [sourceFps]);\n\n const [engine, setEngine] = useState<FilterEngine>(FilterEngine.NONE);\n const [isSupported, setIsSupported] = useState(false);\n useEffect(() => {\n determineEngine(\n useLegacyFilter,\n forceSafariSupport,\n forceMobileSupport,\n ).then((determinedEngine) => {\n setEngine(determinedEngine);\n setIsSupported(determinedEngine !== FilterEngine.NONE);\n });\n }, [forceMobileSupport, forceSafariSupport, useLegacyFilter]);\n\n const [tfLite, setTfLite] = useState<TFLite>();\n useEffect(() => {\n if (engine !== FilterEngine.TF) return;\n\n loadTFLite({ basePath, modelFilePath, tfFilePath })\n .then(setTfLite)\n .catch((err) => console.error('Failed to load TFLite', err));\n }, [basePath, engine, modelFilePath, tfFilePath]);\n\n const [mediaPipe, setMediaPipe] = useState<ArrayBuffer>();\n useEffect(() => {\n if (engine !== FilterEngine.MEDIA_PIPE) return;\n\n loadMediaPipe({\n basePath: basePath,\n modelPath: modelFilePath,\n })\n .then(setMediaPipe)\n .catch((err) => console.error('Failed to preload MediaPipe', err));\n }, [engine, modelFilePath, basePath]);\n\n const handleError = useCallback(\n (error: any) => {\n console.warn(\n '[filters] Filter encountered an error and will be disabled',\n );\n disableBackgroundFilter();\n onError?.(error);\n },\n [disableBackgroundFilter, onError],\n );\n\n const isReady = useLegacyFilter ? !!tfLite : !!mediaPipe;\n const contextValue: BackgroundFiltersContextValue = {\n isSupported,\n performance,\n isReady,\n isLoading,\n backgroundImage,\n backgroundBlurLevel,\n backgroundFilter,\n disableBackgroundFilter,\n applyBackgroundBlurFilter,\n applyBackgroundImageFilter,\n backgroundImages,\n tfFilePath,\n modelFilePath,\n basePath,\n onError: handleError,\n };\n return (\n <ContextProvider.Provider value={contextValue}>\n {children}\n {isReady && (\n <BackgroundFilters\n api={contextValue}\n tfLite={tfLite}\n engine={engine}\n onStats={handleStats}\n setIsLoading={setIsLoading}\n />\n )}\n </ContextProvider.Provider>\n );\n};\n\nconst BackgroundFilters = (props: {\n api: BackgroundFiltersContextValue;\n tfLite?: TFLite;\n engine: FilterEngine;\n onStats: (stats: PerformanceStats) => void;\n setIsLoading: (loading: boolean) => void;\n}) => {\n const call = useCall();\n const { engine, api, tfLite, onStats, setIsLoading } = props;\n const { children, start } = useRenderer(api, tfLite, call, engine);\n const { onError, backgroundFilter } = api;\n const handleErrorRef = useRef<((error: any) => void) | undefined>(undefined);\n handleErrorRef.current = onError;\n\n const handleStatsRef = useRef<\n ((stats: PerformanceStats) => void) | undefined\n >(undefined);\n handleStatsRef.current = onStats;\n\n useEffect(() => {\n if (!call || !backgroundFilter) return;\n\n setIsLoading(true);\n const { unregister, registered } = call.camera.registerFilter((ms) => {\n return start(\n ms,\n (error) => handleErrorRef.current?.(error),\n (stats: PerformanceStats) => handleStatsRef.current?.(stats),\n );\n });\n registered.finally(() => {\n setIsLoading(false);\n });\n\n return () => {\n unregister().catch((err) => console.warn(`Can't unregister filter`, err));\n };\n }, [call, start, backgroundFilter, setIsLoading]);\n\n return children;\n};\n\nconst useRenderer = (\n api: BackgroundFiltersContextValue,\n tfLite: TFLite | undefined,\n call: Call | undefined,\n engine: FilterEngine,\n) => {\n const {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n modelFilePath,\n basePath,\n } = api;\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const bgImageRef = useRef<HTMLImageElement>(null);\n const [videoSize, setVideoSize] = useState<{ width: number; height: number }>(\n {\n width: 1920,\n height: 1080,\n },\n );\n\n const start = useCallback(\n (\n ms: MediaStream,\n onError?: (error: any) => void,\n onStats?: (stats: PerformanceStats) => void,\n ) => {\n let outputStream: MediaStream | undefined;\n let processor: VirtualBackground | undefined;\n let renderer: Renderer | undefined;\n\n const output = new Promise<MediaStream>((resolve, reject) => {\n if (!backgroundFilter) {\n reject(new Error('No filter specified'));\n return;\n }\n\n const videoEl = videoRef.current;\n const canvasEl = canvasRef.current;\n const bgImageEl = bgImageRef.current;\n\n const [track] = ms.getVideoTracks();\n\n if (!track) {\n reject(new Error('No video tracks in input media stream'));\n return;\n }\n\n if (engine === FilterEngine.MEDIA_PIPE) {\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!videoEl) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n\n processor = new VirtualBackground(\n track,\n {\n basePath: basePath,\n modelPath: modelFilePath,\n backgroundBlurLevel,\n backgroundImage,\n backgroundFilter,\n },\n { onError, onStats },\n );\n processor\n .start()\n .then((processedTrack) => {\n outputStream = new MediaStream([processedTrack]);\n resolve(outputStream);\n })\n .catch((error) => {\n reject(error);\n });\n\n return;\n }\n\n if (engine === FilterEngine.TF) {\n if (!videoEl || !canvasEl || (backgroundImage && !bgImageEl)) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n videoEl.srcObject = ms;\n videoEl.play().then(\n () => {\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!tfLite) {\n reject(new Error('TensorFlow Lite not loaded'));\n return;\n }\n\n renderer = createRenderer(\n tfLite,\n videoEl,\n canvasEl,\n {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage: bgImageEl ?? undefined,\n },\n onError,\n );\n outputStream = canvasEl.captureStream();\n\n resolve(outputStream);\n },\n () => {\n reject(new Error('Could not play the source video stream'));\n },\n );\n return;\n }\n\n reject(new Error('No supported engine available'));\n });\n\n return {\n output,\n stop: () => {\n call?.tracer.trace('backgroundFilters.disable', null);\n processor?.stop();\n renderer?.dispose();\n if (videoRef.current) videoRef.current.srcObject = null;\n if (outputStream) disposeOfMediaStream(outputStream);\n },\n };\n },\n [\n backgroundBlurLevel,\n backgroundFilter,\n backgroundImage,\n call?.tracer,\n tfLite,\n engine,\n modelFilePath,\n basePath,\n ],\n );\n\n const children = (\n <div className=\"str-video__background-filters\">\n <video\n className={clsx(\n 'str-video__background-filters__video',\n videoSize.height > videoSize.width &&\n 'str-video__background-filters__video--tall',\n )}\n ref={videoRef}\n playsInline\n muted\n controls={false}\n {...videoSize}\n />\n {backgroundImage && (\n <img\n className=\"str-video__background-filters__background-image\"\n alt=\"Background\"\n ref={bgImageRef}\n crossOrigin=\"anonymous\"\n src={backgroundImage}\n {...videoSize}\n />\n )}\n <canvas\n className=\"str-video__background-filters__target-canvas\"\n {...videoSize}\n ref={canvasRef}\n />\n </div>\n );\n\n return { start, children };\n};\n"],"names":["isPlatformSupported","isMediaPipePlatformSupported","useCall","useCallStateHooks","useState","useRef","useCallback","useMemo","useEffect","loadTFLite","loadMediaPipe","_jsxs","_jsx","flushSync","VirtualBackground","createRenderer","disposeOfMediaStream"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embedded-BackgroundFilters-RdXfNf6_.es.js","sources":["../../src/components/BackgroundFilters/BackgroundFilters.tsx"],"sourcesContent":["import {\n Context,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';\nimport { Call, disposeOfMediaStream } from '@stream-io/video-client';\nimport {\n BackgroundBlurLevel,\n createRenderer,\n isMediaPipePlatformSupported,\n isPlatformSupported,\n loadMediaPipe,\n loadTFLite,\n PerformanceStats,\n Renderer,\n TFLite,\n VirtualBackground,\n} from '@stream-io/video-filters-web';\nimport clsx from 'clsx';\nimport type {\n BackgroundFiltersPerformance,\n BackgroundFiltersProps,\n BackgroundFiltersContextValue,\n PerformanceDegradationReason,\n} from './types';\n\n/**\n * Constants for FPS warning calculation.\n * Smooths out quick spikes using an EMA, ignores brief outliers,\n * and uses two thresholds to avoid flickering near the limit.\n */\nconst ALPHA = 0.2;\nconst DEFAULT_FPS = 30;\nconst DEVIATION_LIMIT = 0.5;\nconst OUTLIER_PERSISTENCE = 5;\n\n/**\n * Represents the available background filter processing engines.\n */\nenum FilterEngine {\n TF,\n MEDIA_PIPE,\n NONE,\n}\n\n/**\n * Determines which filter engine is available.\n * MEDIA_PIPE is the default unless legacy filters are requested or MediaPipe is unsupported.\n *\n * Returns NONE if neither is supported.\n */\nconst determineEngine = async (\n useLegacyFilter: boolean | undefined,\n forceSafariSupport: boolean | undefined,\n forceMobileSupport: boolean | undefined,\n): Promise<FilterEngine> => {\n if (useLegacyFilter) {\n const isTfPlatformSupported = await isPlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n return isTfPlatformSupported ? FilterEngine.TF : FilterEngine.NONE;\n }\n\n const isMediaPipeSupported = await isMediaPipePlatformSupported({\n forceSafariSupport,\n forceMobileSupport,\n });\n\n return isMediaPipeSupported ? FilterEngine.MEDIA_PIPE : FilterEngine.NONE;\n};\n\n/**\n * A provider component that enables the use of background filters in your app.\n *\n * Please make sure you have the `@stream-io/video-filters-web` package installed\n * in your project before using this component.\n */\nexport const BackgroundFiltersProvider = (\n props: PropsWithChildren<BackgroundFiltersProps> & {\n // for code splitting. Prevents circular dependency issues where\n // this Context needs to be present in the main chunk, but also\n // imported by the background filters chunk.\n ContextProvider: Context<BackgroundFiltersContextValue | undefined>;\n },\n) => {\n const {\n ContextProvider,\n children,\n backgroundImages = [],\n backgroundFilter: bgFilterFromProps = undefined,\n backgroundImage: bgImageFromProps = undefined,\n backgroundBlurLevel: bgBlurLevelFromProps = undefined,\n tfFilePath,\n modelFilePath,\n useLegacyFilter,\n basePath,\n onError,\n performanceThresholds,\n forceSafariSupport,\n forceMobileSupport,\n } = props;\n\n const call = useCall();\n const { useCallStatsReport } = useCallStateHooks();\n const callStatsReport = useCallStatsReport();\n\n const [backgroundFilter, setBackgroundFilter] = useState(bgFilterFromProps);\n const [backgroundImage, setBackgroundImage] = useState(bgImageFromProps);\n const [backgroundBlurLevel, setBackgroundBlurLevel] =\n useState(bgBlurLevelFromProps);\n\n const [showLowFpsWarning, setShowLowFpsWarning] = useState<boolean>(false);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;\n\n const sourceFps =\n performanceThresholds?.defaultFps || cameraFrameRate || DEFAULT_FPS;\n\n const fpsWarningThresholdLower =\n performanceThresholds?.fpsWarningThresholdLower ?? sourceFps * 0.75;\n const fpsWarningThresholdUpper =\n performanceThresholds?.fpsWarningThresholdUpper ?? sourceFps * 0.85;\n\n const emaRef = useRef<number>(sourceFps);\n const outlierStreakRef = useRef<number>(0);\n\n const handleStats = useCallback(\n (stats: PerformanceStats) => {\n const fps = stats?.fps;\n if (fps === undefined || fps === null) {\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n return;\n }\n\n const prevEma = emaRef.current;\n const deviation = Math.abs(fps - prevEma) / prevEma;\n\n const isOutlier = fps < prevEma && deviation > DEVIATION_LIMIT;\n outlierStreakRef.current = isOutlier ? outlierStreakRef.current + 1 : 0;\n if (isOutlier && outlierStreakRef.current < OUTLIER_PERSISTENCE) return;\n\n emaRef.current = ALPHA * fps + (1 - ALPHA) * prevEma;\n\n setShowLowFpsWarning((prev) => {\n if (prev && emaRef.current > fpsWarningThresholdUpper) return false;\n if (!prev && emaRef.current < fpsWarningThresholdLower) return true;\n\n return prev;\n });\n },\n [fpsWarningThresholdLower, fpsWarningThresholdUpper, sourceFps],\n );\n\n const performance: BackgroundFiltersPerformance = useMemo(() => {\n if (!backgroundFilter) {\n return { degraded: false };\n }\n\n const reasons: Array<PerformanceDegradationReason> = [];\n\n if (showLowFpsWarning) {\n reasons.push('frame-drop');\n }\n\n const qualityLimitationReasons =\n callStatsReport?.publisherStats?.qualityLimitationReasons;\n\n if (\n showLowFpsWarning &&\n qualityLimitationReasons &&\n qualityLimitationReasons?.includes('cpu')\n ) {\n reasons.push('cpu-throttling');\n }\n\n return {\n degraded: reasons.length > 0,\n reason: reasons.length > 0 ? reasons : undefined,\n };\n }, [\n showLowFpsWarning,\n callStatsReport?.publisherStats?.qualityLimitationReasons,\n backgroundFilter,\n ]);\n\n const prevDegradedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n const currentDegraded = performance.degraded;\n const prevDegraded = prevDegradedRef.current;\n\n if (\n !!backgroundFilter &&\n prevDegraded !== undefined &&\n prevDegraded !== currentDegraded\n ) {\n call?.tracer.trace('backgroundFilters.performance', {\n degraded: currentDegraded,\n reason: performance?.reason,\n fps: emaRef.current,\n });\n }\n prevDegradedRef.current = currentDegraded;\n }, [\n performanceThresholds,\n performance.degraded,\n performance.reason,\n backgroundFilter,\n call?.tracer,\n ]);\n\n const applyBackgroundImageFilter = useCallback((imageUrl: string) => {\n setBackgroundFilter('image');\n setBackgroundImage(imageUrl);\n }, []);\n\n const applyBackgroundBlurFilter = useCallback(\n (blurLevel: BackgroundBlurLevel = 'high') => {\n setBackgroundFilter('blur');\n setBackgroundBlurLevel(blurLevel);\n },\n [],\n );\n\n const disableBackgroundFilter = useCallback(() => {\n setBackgroundFilter(undefined);\n setBackgroundImage(undefined);\n setBackgroundBlurLevel(undefined);\n\n emaRef.current = sourceFps;\n outlierStreakRef.current = 0;\n setShowLowFpsWarning(false);\n }, [sourceFps]);\n\n const [engine, setEngine] = useState<FilterEngine>(FilterEngine.NONE);\n const [isSupported, setIsSupported] = useState(false);\n useEffect(() => {\n determineEngine(\n useLegacyFilter,\n forceSafariSupport,\n forceMobileSupport,\n ).then((determinedEngine) => {\n setEngine(determinedEngine);\n setIsSupported(determinedEngine !== FilterEngine.NONE);\n });\n }, [forceMobileSupport, forceSafariSupport, useLegacyFilter]);\n\n const [tfLite, setTfLite] = useState<TFLite>();\n useEffect(() => {\n if (engine !== FilterEngine.TF) return;\n\n loadTFLite({ basePath, modelFilePath, tfFilePath })\n .then(setTfLite)\n .catch((err) => console.error('Failed to load TFLite', err));\n }, [basePath, engine, modelFilePath, tfFilePath]);\n\n const [mediaPipe, setMediaPipe] = useState<ArrayBuffer>();\n useEffect(() => {\n if (engine !== FilterEngine.MEDIA_PIPE) return;\n\n loadMediaPipe({\n basePath: basePath,\n modelPath: modelFilePath,\n })\n .then(setMediaPipe)\n .catch((err) => console.error('Failed to preload MediaPipe', err));\n }, [engine, modelFilePath, basePath]);\n\n const handleError = useCallback(\n (error: any) => {\n console.warn(\n '[filters] Filter encountered an error and will be disabled',\n );\n disableBackgroundFilter();\n onError?.(error);\n },\n [disableBackgroundFilter, onError],\n );\n\n const isReady = useLegacyFilter ? !!tfLite : !!mediaPipe;\n const contextValue: BackgroundFiltersContextValue = {\n isSupported,\n performance,\n isReady,\n isLoading,\n backgroundImage,\n backgroundBlurLevel,\n backgroundFilter,\n disableBackgroundFilter,\n applyBackgroundBlurFilter,\n applyBackgroundImageFilter,\n backgroundImages,\n tfFilePath,\n modelFilePath,\n basePath,\n onError: handleError,\n };\n return (\n <ContextProvider.Provider value={contextValue}>\n {children}\n {isReady && (\n <BackgroundFilters\n api={contextValue}\n tfLite={tfLite}\n engine={engine}\n onStats={handleStats}\n setIsLoading={setIsLoading}\n />\n )}\n </ContextProvider.Provider>\n );\n};\n\nconst BackgroundFilters = (props: {\n api: BackgroundFiltersContextValue;\n tfLite?: TFLite;\n engine: FilterEngine;\n onStats: (stats: PerformanceStats) => void;\n setIsLoading: (loading: boolean) => void;\n}) => {\n const call = useCall();\n const { engine, api, tfLite, onStats, setIsLoading } = props;\n const { children, start } = useRenderer(api, tfLite, call, engine);\n const { onError, backgroundFilter } = api;\n const handleErrorRef = useRef<((error: any) => void) | undefined>(undefined);\n handleErrorRef.current = onError;\n\n const handleStatsRef = useRef<\n ((stats: PerformanceStats) => void) | undefined\n >(undefined);\n handleStatsRef.current = onStats;\n\n useEffect(() => {\n if (!call || !backgroundFilter) return;\n\n setIsLoading(true);\n const { unregister, registered } = call.camera.registerFilter((ms) => {\n return start(\n ms,\n (error) => handleErrorRef.current?.(error),\n (stats: PerformanceStats) => handleStatsRef.current?.(stats),\n );\n });\n registered.finally(() => {\n setIsLoading(false);\n });\n\n return () => {\n unregister().catch((err) => console.warn(`Can't unregister filter`, err));\n };\n }, [call, start, backgroundFilter, setIsLoading]);\n\n return children;\n};\n\nconst useRenderer = (\n api: BackgroundFiltersContextValue,\n tfLite: TFLite | undefined,\n call: Call | undefined,\n engine: FilterEngine,\n) => {\n const {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n modelFilePath,\n basePath,\n } = api;\n\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const bgImageRef = useRef<HTMLImageElement>(null);\n const [videoSize, setVideoSize] = useState<{ width: number; height: number }>(\n {\n width: 1920,\n height: 1080,\n },\n );\n\n const start = useCallback(\n (\n ms: MediaStream,\n onError?: (error: any) => void,\n onStats?: (stats: PerformanceStats) => void,\n ) => {\n let outputStream: MediaStream | undefined;\n let processor: VirtualBackground | undefined;\n let renderer: Renderer | undefined;\n\n const output = new Promise<MediaStream>((resolve, reject) => {\n if (!backgroundFilter) {\n reject(new Error('No filter specified'));\n return;\n }\n\n const videoEl = videoRef.current;\n const canvasEl = canvasRef.current;\n const bgImageEl = bgImageRef.current;\n\n const [track] = ms.getVideoTracks();\n\n if (!track) {\n reject(new Error('No video tracks in input media stream'));\n return;\n }\n\n if (engine === FilterEngine.MEDIA_PIPE) {\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!videoEl) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n\n processor = new VirtualBackground(\n track,\n {\n basePath: basePath,\n modelPath: modelFilePath,\n backgroundBlurLevel,\n backgroundImage,\n backgroundFilter,\n },\n { onError, onStats },\n );\n processor\n .start()\n .then((processedTrack) => {\n outputStream = new MediaStream([processedTrack]);\n resolve(outputStream);\n })\n .catch((error) => {\n reject(error);\n });\n\n return;\n }\n\n if (engine === FilterEngine.TF) {\n if (!videoEl || !canvasEl || (backgroundImage && !bgImageEl)) {\n reject(new Error('Renderer started before elements are ready'));\n return;\n }\n\n videoEl.srcObject = ms;\n videoEl.play().then(\n () => {\n const trackSettings = track.getSettings();\n flushSync(() =>\n setVideoSize({\n width: trackSettings.width ?? 0,\n height: trackSettings.height ?? 0,\n }),\n );\n call?.tracer.trace('backgroundFilters.enable', {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage,\n engine,\n });\n\n if (!tfLite) {\n reject(new Error('TensorFlow Lite not loaded'));\n return;\n }\n\n renderer = createRenderer(\n tfLite,\n videoEl,\n canvasEl,\n {\n backgroundFilter,\n backgroundBlurLevel,\n backgroundImage: bgImageEl ?? undefined,\n },\n onError,\n );\n outputStream = canvasEl.captureStream();\n\n resolve(outputStream);\n },\n () => {\n reject(new Error('Could not play the source video stream'));\n },\n );\n return;\n }\n\n reject(new Error('No supported engine available'));\n });\n\n return {\n output,\n stop: () => {\n call?.tracer.trace('backgroundFilters.disable', null);\n processor?.stop();\n renderer?.dispose();\n if (videoRef.current) videoRef.current.srcObject = null;\n if (outputStream) disposeOfMediaStream(outputStream);\n },\n };\n },\n [\n backgroundBlurLevel,\n backgroundFilter,\n backgroundImage,\n call?.tracer,\n tfLite,\n engine,\n modelFilePath,\n basePath,\n ],\n );\n\n const children = (\n <div className=\"str-video__background-filters\">\n <video\n className={clsx(\n 'str-video__background-filters__video',\n videoSize.height > videoSize.width &&\n 'str-video__background-filters__video--tall',\n )}\n ref={videoRef}\n playsInline\n muted\n controls={false}\n {...videoSize}\n />\n {backgroundImage && (\n <img\n className=\"str-video__background-filters__background-image\"\n alt=\"Background\"\n ref={bgImageRef}\n crossOrigin=\"anonymous\"\n src={backgroundImage}\n {...videoSize}\n />\n )}\n <canvas\n className=\"str-video__background-filters__target-canvas\"\n {...videoSize}\n ref={canvasRef}\n />\n </div>\n );\n\n return { start, children };\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|