@stream-io/video-react-sdk 0.5.8 → 0.5.10
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 +19 -0
- package/dist/css/styles.css +27 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/index.cjs.js +155 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +155 -3
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/BackgroundFilters/BackgroundFilters.d.ts +86 -0
- package/dist/src/components/BackgroundFilters/index.d.ts +1 -0
- package/dist/src/components/Tooltip/hooks/useEnterLeaveHandlers.d.ts +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/utilities/isComponentType.d.ts +1 -1
- package/package.json +10 -9
- package/src/components/BackgroundFilters/BackgroundFilters.tsx +354 -0
- package/src/components/BackgroundFilters/index.ts +1 -0
- package/src/components/index.ts +1 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { BackgroundBlurLevel, BackgroundFilter } from '@stream-io/video-filters-web';
|
|
3
|
+
export type BackgroundFiltersProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Enables or disables the background-blurring feature.
|
|
6
|
+
* @default true.
|
|
7
|
+
*/
|
|
8
|
+
isBlurringEnabled?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* A list of URLs to use as background images.
|
|
11
|
+
*/
|
|
12
|
+
backgroundImages?: string[];
|
|
13
|
+
/**
|
|
14
|
+
* The background filter to apply to the video (by default).
|
|
15
|
+
* @default 'none'.
|
|
16
|
+
*/
|
|
17
|
+
backgroundFilter?: BackgroundFilter;
|
|
18
|
+
/**
|
|
19
|
+
* The URL of the image to use as the background (by default).
|
|
20
|
+
*/
|
|
21
|
+
backgroundImage?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The level of blur to apply to the background (by default).
|
|
24
|
+
* @default 'high'.
|
|
25
|
+
*/
|
|
26
|
+
backgroundBlurLevel?: BackgroundBlurLevel;
|
|
27
|
+
/**
|
|
28
|
+
* The base path for the TensorFlow Lite files.
|
|
29
|
+
* @default 'https://unpkg.com/@stream-io/video-filters-web/tf'.
|
|
30
|
+
*/
|
|
31
|
+
basePath?: string;
|
|
32
|
+
/**
|
|
33
|
+
* The path to the TensorFlow Lite WebAssembly file.
|
|
34
|
+
*
|
|
35
|
+
* Override this prop to use a custom path to the TensorFlow Lite WebAssembly file
|
|
36
|
+
* (e.g., if you choose to host it yourself).
|
|
37
|
+
*/
|
|
38
|
+
tfFilePath?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The path to the TensorFlow Lite model file.
|
|
41
|
+
* Override this prop to use a custom path to the TensorFlow Lite model file
|
|
42
|
+
* (e.g., if you choose to host it yourself).
|
|
43
|
+
*/
|
|
44
|
+
modelFilePath?: string;
|
|
45
|
+
};
|
|
46
|
+
export type BackgroundFiltersAPI = {
|
|
47
|
+
/**
|
|
48
|
+
* Whether the current platform supports the background filters.
|
|
49
|
+
*/
|
|
50
|
+
isSupported: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Indicates whether the background filters engine is loaded and ready.
|
|
53
|
+
*/
|
|
54
|
+
isReady: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Disables all background filters applied to the video.
|
|
57
|
+
*/
|
|
58
|
+
disableBackgroundFilter: () => void;
|
|
59
|
+
/**
|
|
60
|
+
* Applies a background blur filter to the video.
|
|
61
|
+
*
|
|
62
|
+
* @param blurLevel the level of blur to apply to the background.
|
|
63
|
+
*/
|
|
64
|
+
applyBackgroundBlurFilter: (blurLevel: BackgroundBlurLevel) => void;
|
|
65
|
+
/**
|
|
66
|
+
* Applies a background image filter to the video.
|
|
67
|
+
*
|
|
68
|
+
* @param imageUrl the URL of the image to use as the background.
|
|
69
|
+
*/
|
|
70
|
+
applyBackgroundImageFilter: (imageUrl: string) => void;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The context value for the background filters context.
|
|
74
|
+
*/
|
|
75
|
+
export type BackgroundFiltersContextValue = BackgroundFiltersProps & BackgroundFiltersAPI;
|
|
76
|
+
/**
|
|
77
|
+
* A hook to access the background filters context API.
|
|
78
|
+
*/
|
|
79
|
+
export declare const useBackgroundFilters: () => BackgroundFiltersContextValue;
|
|
80
|
+
/**
|
|
81
|
+
* A provider component that enables the use of background filters in your app.
|
|
82
|
+
*
|
|
83
|
+
* Please make sure you have the `@stream-io/video-filters-web` package installed
|
|
84
|
+
* in your project before using this component.
|
|
85
|
+
*/
|
|
86
|
+
export declare const BackgroundFiltersProvider: (props: PropsWithChildren<BackgroundFiltersProps>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BackgroundFilters';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MouseEventHandler } from 'react';
|
|
2
|
-
export declare const useEnterLeaveHandlers: <T extends HTMLElement>({ onMouseEnter, onMouseLeave, }?: Partial<Record<
|
|
2
|
+
export declare const useEnterLeaveHandlers: <T extends HTMLElement>({ onMouseEnter, onMouseLeave, }?: Partial<Record<'onMouseEnter' | 'onMouseLeave', MouseEventHandler<T>>>) => {
|
|
3
3
|
handleMouseEnter: MouseEventHandler<T>;
|
|
4
4
|
handleMouseLeave: MouseEventHandler<T>;
|
|
5
5
|
tooltipVisible: boolean;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ComponentType, ReactElement } from 'react';
|
|
2
|
-
export declare const isComponentType: <T extends {}>(elementOrComponent?:
|
|
2
|
+
export declare const isComponentType: <T extends {}>(elementOrComponent?: ComponentType<T> | ReactElement | null) => elementOrComponent is ComponentType<T>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-sdk",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.10",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"clean": "rimraf dist",
|
|
11
11
|
"start": "rollup -c -w",
|
|
12
|
-
"build": "NODE_ENV=production rollup -c && yarn copy-css",
|
|
12
|
+
"build": "rimraf dist && NODE_ENV=production rollup -c && yarn copy-css",
|
|
13
13
|
"copy-css": "cp -R ../../node_modules/@stream-io/video-styling/dist/* dist/",
|
|
14
14
|
"start:docs": "npx stream-chat-docusaurus -s"
|
|
15
15
|
},
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@floating-ui/react": "^0.26.5",
|
|
32
|
-
"@stream-io/video-client": "
|
|
33
|
-
"@stream-io/video-
|
|
32
|
+
"@stream-io/video-client": "0.6.8",
|
|
33
|
+
"@stream-io/video-filters-web": "0.0.1",
|
|
34
|
+
"@stream-io/video-react-bindings": "0.4.8",
|
|
34
35
|
"chart.js": "^4.4.1",
|
|
35
36
|
"clsx": "^2.0.0",
|
|
36
37
|
"react-chartjs-2": "^5.2.0"
|
|
@@ -40,14 +41,14 @@
|
|
|
40
41
|
"react-dom": "^18.0.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@rollup/plugin-json": "^6.0
|
|
44
|
-
"@rollup/plugin-replace": "^5.0.
|
|
45
|
-
"@rollup/plugin-typescript": "^11.1.
|
|
46
|
-
"@stream-io/video-styling": "^1.0.
|
|
44
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
45
|
+
"@rollup/plugin-replace": "^5.0.5",
|
|
46
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
47
|
+
"@stream-io/video-styling": "^1.0.2",
|
|
47
48
|
"react": "^18.2.0",
|
|
48
49
|
"react-dom": "^18.2.0",
|
|
49
50
|
"rimraf": "^5.0.5",
|
|
50
51
|
"rollup": "^3.29.4",
|
|
51
|
-
"typescript": "^5.
|
|
52
|
+
"typescript": "^5.4.3"
|
|
52
53
|
}
|
|
53
54
|
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
PropsWithChildren,
|
|
4
|
+
useCallback,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import clsx from 'clsx';
|
|
11
|
+
import { useCall } from '@stream-io/video-react-bindings';
|
|
12
|
+
import {
|
|
13
|
+
BackgroundBlurLevel,
|
|
14
|
+
BackgroundFilter,
|
|
15
|
+
createRenderer,
|
|
16
|
+
isPlatformSupported,
|
|
17
|
+
loadTFLite,
|
|
18
|
+
TFLite,
|
|
19
|
+
} from '@stream-io/video-filters-web';
|
|
20
|
+
|
|
21
|
+
export type BackgroundFiltersProps = {
|
|
22
|
+
/**
|
|
23
|
+
* Enables or disables the background-blurring feature.
|
|
24
|
+
* @default true.
|
|
25
|
+
*/
|
|
26
|
+
isBlurringEnabled?: boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A list of URLs to use as background images.
|
|
30
|
+
*/
|
|
31
|
+
backgroundImages?: string[];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The background filter to apply to the video (by default).
|
|
35
|
+
* @default 'none'.
|
|
36
|
+
*/
|
|
37
|
+
backgroundFilter?: BackgroundFilter;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The URL of the image to use as the background (by default).
|
|
41
|
+
*/
|
|
42
|
+
backgroundImage?: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The level of blur to apply to the background (by default).
|
|
46
|
+
* @default 'high'.
|
|
47
|
+
*/
|
|
48
|
+
backgroundBlurLevel?: BackgroundBlurLevel;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The base path for the TensorFlow Lite files.
|
|
52
|
+
* @default 'https://unpkg.com/@stream-io/video-filters-web/tf'.
|
|
53
|
+
*/
|
|
54
|
+
basePath?: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The path to the TensorFlow Lite WebAssembly file.
|
|
58
|
+
*
|
|
59
|
+
* Override this prop to use a custom path to the TensorFlow Lite WebAssembly file
|
|
60
|
+
* (e.g., if you choose to host it yourself).
|
|
61
|
+
*/
|
|
62
|
+
tfFilePath?: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The path to the TensorFlow Lite model file.
|
|
66
|
+
* Override this prop to use a custom path to the TensorFlow Lite model file
|
|
67
|
+
* (e.g., if you choose to host it yourself).
|
|
68
|
+
*/
|
|
69
|
+
modelFilePath?: string;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type BackgroundFiltersAPI = {
|
|
73
|
+
/**
|
|
74
|
+
* Whether the current platform supports the background filters.
|
|
75
|
+
*/
|
|
76
|
+
isSupported: boolean;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Indicates whether the background filters engine is loaded and ready.
|
|
80
|
+
*/
|
|
81
|
+
isReady: boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Disables all background filters applied to the video.
|
|
85
|
+
*/
|
|
86
|
+
disableBackgroundFilter: () => void;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Applies a background blur filter to the video.
|
|
90
|
+
*
|
|
91
|
+
* @param blurLevel the level of blur to apply to the background.
|
|
92
|
+
*/
|
|
93
|
+
applyBackgroundBlurFilter: (blurLevel: BackgroundBlurLevel) => void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Applies a background image filter to the video.
|
|
97
|
+
*
|
|
98
|
+
* @param imageUrl the URL of the image to use as the background.
|
|
99
|
+
*/
|
|
100
|
+
applyBackgroundImageFilter: (imageUrl: string) => void;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The context value for the background filters context.
|
|
105
|
+
*/
|
|
106
|
+
export type BackgroundFiltersContextValue = BackgroundFiltersProps &
|
|
107
|
+
BackgroundFiltersAPI;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The context for the background filters.
|
|
111
|
+
*/
|
|
112
|
+
const BackgroundFiltersContext = createContext<
|
|
113
|
+
BackgroundFiltersContextValue | undefined
|
|
114
|
+
>(undefined);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A hook to access the background filters context API.
|
|
118
|
+
*/
|
|
119
|
+
export const useBackgroundFilters = () => {
|
|
120
|
+
const context = useContext(BackgroundFiltersContext);
|
|
121
|
+
if (!context) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
'useBackgroundFilters must be used within a BackgroundFiltersProvider',
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return context;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* A provider component that enables the use of background filters in your app.
|
|
131
|
+
*
|
|
132
|
+
* Please make sure you have the `@stream-io/video-filters-web` package installed
|
|
133
|
+
* in your project before using this component.
|
|
134
|
+
*/
|
|
135
|
+
export const BackgroundFiltersProvider = (
|
|
136
|
+
props: PropsWithChildren<BackgroundFiltersProps>,
|
|
137
|
+
) => {
|
|
138
|
+
const {
|
|
139
|
+
children,
|
|
140
|
+
isBlurringEnabled = true,
|
|
141
|
+
backgroundImages = [],
|
|
142
|
+
backgroundFilter: bgFilterFromProps = undefined,
|
|
143
|
+
backgroundImage: bgImageFromProps = undefined,
|
|
144
|
+
backgroundBlurLevel: bgBlurLevelFromProps = 'high',
|
|
145
|
+
tfFilePath,
|
|
146
|
+
modelFilePath,
|
|
147
|
+
basePath,
|
|
148
|
+
} = props;
|
|
149
|
+
|
|
150
|
+
const [backgroundFilter, setBackgroundFilter] = useState(bgFilterFromProps);
|
|
151
|
+
const [backgroundImage, setBackgroundImage] = useState(bgImageFromProps);
|
|
152
|
+
const [backgroundBlurLevel, setBackgroundBlurLevel] =
|
|
153
|
+
useState(bgBlurLevelFromProps);
|
|
154
|
+
|
|
155
|
+
const applyBackgroundImageFilter = useCallback((imageUrl: string) => {
|
|
156
|
+
setBackgroundFilter('image');
|
|
157
|
+
setBackgroundImage(imageUrl);
|
|
158
|
+
}, []);
|
|
159
|
+
|
|
160
|
+
const applyBackgroundBlurFilter = useCallback(
|
|
161
|
+
(blurLevel: BackgroundBlurLevel = 'high') => {
|
|
162
|
+
setBackgroundFilter('blur');
|
|
163
|
+
setBackgroundBlurLevel(blurLevel);
|
|
164
|
+
},
|
|
165
|
+
[],
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const disableBackgroundFilter = useCallback(() => {
|
|
169
|
+
setBackgroundFilter(undefined);
|
|
170
|
+
setBackgroundImage(undefined);
|
|
171
|
+
setBackgroundBlurLevel('high');
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
const [isSupported, setIsSupported] = useState(false);
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
isPlatformSupported().then(setIsSupported);
|
|
177
|
+
}, []);
|
|
178
|
+
|
|
179
|
+
const [tfLite, setTfLite] = useState<TFLite>();
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
// don't try to load TFLite if the platform is not supported
|
|
182
|
+
if (!isSupported) return;
|
|
183
|
+
loadTFLite({ basePath, modelFilePath, tfFilePath })
|
|
184
|
+
.then(setTfLite)
|
|
185
|
+
.catch((err) => console.error('Failed to load TFLite', err));
|
|
186
|
+
}, [basePath, isSupported, modelFilePath, tfFilePath]);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<BackgroundFiltersContext.Provider
|
|
190
|
+
value={{
|
|
191
|
+
isSupported,
|
|
192
|
+
isReady: !!tfLite,
|
|
193
|
+
backgroundImage,
|
|
194
|
+
backgroundBlurLevel,
|
|
195
|
+
backgroundFilter,
|
|
196
|
+
disableBackgroundFilter,
|
|
197
|
+
applyBackgroundBlurFilter,
|
|
198
|
+
applyBackgroundImageFilter,
|
|
199
|
+
backgroundImages,
|
|
200
|
+
isBlurringEnabled,
|
|
201
|
+
tfFilePath,
|
|
202
|
+
modelFilePath,
|
|
203
|
+
basePath,
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
{children}
|
|
207
|
+
{tfLite && backgroundFilter && <BackgroundFilters tfLite={tfLite} />}
|
|
208
|
+
</BackgroundFiltersContext.Provider>
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const BackgroundFilters = (props: { tfLite: TFLite }) => {
|
|
213
|
+
const { tfLite } = props;
|
|
214
|
+
const call = useCall();
|
|
215
|
+
const { backgroundImage, backgroundFilter } = useBackgroundFilters();
|
|
216
|
+
const [videoRef, setVideoRef] = useState<HTMLVideoElement | null>(null);
|
|
217
|
+
const [bgImageRef, setBgImageRef] = useState<HTMLImageElement | null>(null);
|
|
218
|
+
const [canvasRef, setCanvasRef] = useState<HTMLCanvasElement | null>(null);
|
|
219
|
+
const [width, setWidth] = useState(1920);
|
|
220
|
+
const [height, setHeight] = useState(1080);
|
|
221
|
+
|
|
222
|
+
const resolveFilterRef =
|
|
223
|
+
useRef<(value: MediaStream | PromiseLike<MediaStream>) => void>();
|
|
224
|
+
|
|
225
|
+
const [mediaStream, setMediaStream] = useState<MediaStream>();
|
|
226
|
+
const registerFilterRef = useRef(Promise.resolve(async () => {}));
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (!call || !backgroundFilter) return;
|
|
229
|
+
registerFilterRef.current = registerFilterRef.current.then(() =>
|
|
230
|
+
call.camera.registerFilter(async (ms) => {
|
|
231
|
+
return new Promise<MediaStream>((resolve) => {
|
|
232
|
+
setMediaStream(ms);
|
|
233
|
+
resolveFilterRef.current = resolve;
|
|
234
|
+
});
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
return () => {
|
|
239
|
+
registerFilterRef.current
|
|
240
|
+
.then((unregister) => unregister())
|
|
241
|
+
.then(() => setMediaStream(undefined))
|
|
242
|
+
.catch((err) => console.error('Failed to unregister filter', err));
|
|
243
|
+
};
|
|
244
|
+
}, [backgroundFilter, call]);
|
|
245
|
+
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
if (!mediaStream || !videoRef || !canvasRef) return;
|
|
248
|
+
|
|
249
|
+
const handleOnPlay = () => {
|
|
250
|
+
const [track] = mediaStream.getVideoTracks();
|
|
251
|
+
if (track) {
|
|
252
|
+
const { width: w = 0, height: h = 0 } = track.getSettings();
|
|
253
|
+
setWidth(w);
|
|
254
|
+
setHeight(h);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const resolveFilter = resolveFilterRef.current;
|
|
258
|
+
if (!resolveFilter) return;
|
|
259
|
+
const filter = canvasRef.captureStream();
|
|
260
|
+
resolveFilter(filter);
|
|
261
|
+
};
|
|
262
|
+
videoRef.addEventListener('play', handleOnPlay);
|
|
263
|
+
|
|
264
|
+
videoRef.srcObject = mediaStream;
|
|
265
|
+
videoRef.play().catch((err) => console.error('Failed to play video', err));
|
|
266
|
+
return () => {
|
|
267
|
+
videoRef.removeEventListener('play', handleOnPlay);
|
|
268
|
+
videoRef.srcObject = null;
|
|
269
|
+
};
|
|
270
|
+
}, [canvasRef, mediaStream, videoRef]);
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<div
|
|
274
|
+
className="str-video__background-filters"
|
|
275
|
+
style={{
|
|
276
|
+
width: `${width}px`,
|
|
277
|
+
height: `${height}px`,
|
|
278
|
+
}}
|
|
279
|
+
>
|
|
280
|
+
{mediaStream && (
|
|
281
|
+
<RenderPipeline
|
|
282
|
+
tfLite={tfLite}
|
|
283
|
+
videoRef={videoRef}
|
|
284
|
+
canvasRef={canvasRef}
|
|
285
|
+
backgroundImageRef={bgImageRef}
|
|
286
|
+
/>
|
|
287
|
+
)}
|
|
288
|
+
<video
|
|
289
|
+
className={clsx(
|
|
290
|
+
'str-video__background-filters__video',
|
|
291
|
+
height > width && 'str-video__background-filters__video--tall',
|
|
292
|
+
)}
|
|
293
|
+
ref={setVideoRef}
|
|
294
|
+
autoPlay
|
|
295
|
+
playsInline
|
|
296
|
+
controls={false}
|
|
297
|
+
width={width}
|
|
298
|
+
height={height}
|
|
299
|
+
muted
|
|
300
|
+
loop
|
|
301
|
+
/>
|
|
302
|
+
{backgroundImage && (
|
|
303
|
+
<img
|
|
304
|
+
className="str-video__background-filters__background-image"
|
|
305
|
+
key={backgroundImage}
|
|
306
|
+
alt="Background"
|
|
307
|
+
ref={setBgImageRef}
|
|
308
|
+
src={backgroundImage}
|
|
309
|
+
width={width}
|
|
310
|
+
height={height}
|
|
311
|
+
/>
|
|
312
|
+
)}
|
|
313
|
+
<canvas
|
|
314
|
+
className="str-video__background-filters__target-canvas"
|
|
315
|
+
key={`key-${width}${height}`}
|
|
316
|
+
width={width}
|
|
317
|
+
height={height}
|
|
318
|
+
ref={setCanvasRef}
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
);
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const RenderPipeline = (props: {
|
|
325
|
+
tfLite: TFLite;
|
|
326
|
+
videoRef: HTMLVideoElement | null;
|
|
327
|
+
canvasRef: HTMLCanvasElement | null;
|
|
328
|
+
backgroundImageRef: HTMLImageElement | null;
|
|
329
|
+
}) => {
|
|
330
|
+
const { tfLite, videoRef, canvasRef, backgroundImageRef } = props;
|
|
331
|
+
const { backgroundFilter, backgroundBlurLevel } = useBackgroundFilters();
|
|
332
|
+
useEffect(() => {
|
|
333
|
+
if (!videoRef || !canvasRef || !backgroundFilter) return;
|
|
334
|
+
if (backgroundFilter === 'image' && !backgroundImageRef) return;
|
|
335
|
+
|
|
336
|
+
const renderer = createRenderer(tfLite, videoRef, canvasRef, {
|
|
337
|
+
backgroundFilter,
|
|
338
|
+
backgroundImage: backgroundImageRef ?? undefined,
|
|
339
|
+
backgroundBlurLevel,
|
|
340
|
+
});
|
|
341
|
+
return () => {
|
|
342
|
+
renderer.dispose();
|
|
343
|
+
};
|
|
344
|
+
}, [
|
|
345
|
+
backgroundBlurLevel,
|
|
346
|
+
backgroundFilter,
|
|
347
|
+
backgroundImageRef,
|
|
348
|
+
canvasRef,
|
|
349
|
+
tfLite,
|
|
350
|
+
videoRef,
|
|
351
|
+
]);
|
|
352
|
+
|
|
353
|
+
return null;
|
|
354
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BackgroundFilters';
|