@stream-io/video-react-sdk 1.36.0 → 1.36.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.
@@ -8,13 +8,13 @@ import clsx from 'clsx';
8
8
 
9
9
  /**
10
10
  * Constants for FPS warning calculation.
11
- * Smooths out quick spikes using an EMA, ignores brief outliers,
12
- * and uses two thresholds to avoid flickering near the limit.
11
+ * Smooths the processed-to-source FPS ratio and uses hysteresis
12
+ * so the degradation warning doesn't flicker near the limit.
13
13
  */
14
14
  const ALPHA = 0.2;
15
- const DEFAULT_FPS = 30;
16
- const DEVIATION_LIMIT = 0.5;
17
- const OUTLIER_PERSISTENCE = 5;
15
+ const FPS_RATIO_WARNING_THRESHOLD_LOWER = 0.75;
16
+ const FPS_RATIO_WARNING_THRESHOLD_UPPER = 0.85;
17
+ const EMPTY_BACKGROUND_IMAGES = [];
18
18
  /**
19
19
  * Represents the available background filter processing engines.
20
20
  */
@@ -44,6 +44,58 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
44
44
  });
45
45
  return isMediaPipeSupported ? FilterEngine.MEDIA_PIPE : FilterEngine.NONE;
46
46
  };
47
+ /**
48
+ * Samples the raw camera track's frame stats (W3C MediaCapture Extensions) at a
49
+ * fixed interval and returns a live source fps estimate. Returns `undefined`
50
+ * while warming up, when the camera is off, or when the browser doesn't expose
51
+ * `MediaStreamTrack.stats` (currently Chromium-only).
52
+ */
53
+ const useTrackFramesPerSecond = (call) => {
54
+ const { useCameraState } = useCallStateHooks();
55
+ const { rootMediaStream } = useCameraState();
56
+ const [fps, setFps] = useState(undefined);
57
+ const trackId = rootMediaStream?.getVideoTracks()[0]?.id;
58
+ useEffect(() => {
59
+ if (!call) {
60
+ setFps(undefined);
61
+ return;
62
+ }
63
+ let previousSnapshot;
64
+ let previousTrackId;
65
+ const intervalId = setInterval(() => {
66
+ const track = rootMediaStream?.getVideoTracks()[0];
67
+ const stats = track?.stats;
68
+ if (!track || !stats) {
69
+ previousSnapshot = undefined;
70
+ setFps(undefined);
71
+ return;
72
+ }
73
+ if (track.id !== previousTrackId) {
74
+ previousTrackId = track.id;
75
+ previousSnapshot = undefined;
76
+ setFps(undefined);
77
+ }
78
+ const currentSnapshot = {
79
+ deliveredFrames: stats.deliveredFrames,
80
+ discardedFrames: stats.discardedFrames,
81
+ totalFrames: stats.totalFrames,
82
+ capturedAt: performance.now(),
83
+ };
84
+ if (previousSnapshot) {
85
+ const elapsedSec = (currentSnapshot.capturedAt - previousSnapshot.capturedAt) / 1000;
86
+ const delivered = currentSnapshot.deliveredFrames - previousSnapshot.deliveredFrames;
87
+ const nextFps = Math.round(delivered / elapsedSec);
88
+ setFps(nextFps);
89
+ }
90
+ previousSnapshot = currentSnapshot;
91
+ }, 1000);
92
+ return () => {
93
+ clearInterval(intervalId);
94
+ setFps(undefined);
95
+ };
96
+ }, [call, rootMediaStream, trackId]);
97
+ return fps;
98
+ };
47
99
  /**
48
100
  * A provider component that enables the use of background filters in your app.
49
101
  *
@@ -51,7 +103,7 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
51
103
  * in your project before using this component.
52
104
  */
53
105
  const BackgroundFiltersProvider = (props) => {
54
- const { ContextProvider, children, backgroundImages = [], backgroundFilter: bgFilterFromProps = undefined, backgroundImage: bgImageFromProps = undefined, backgroundBlurLevel: bgBlurLevelFromProps = undefined, tfFilePath, modelFilePath, useLegacyFilter, basePath, onError, performanceThresholds, forceSafariSupport, forceMobileSupport, segmentationOptions, } = props;
106
+ const { ContextProvider, children, backgroundImages = EMPTY_BACKGROUND_IMAGES, backgroundFilter: bgFilterFromProps = undefined, backgroundImage: bgImageFromProps = undefined, backgroundBlurLevel: bgBlurLevelFromProps = undefined, tfFilePath, modelFilePath, useLegacyFilter, basePath, onError, forceSafariSupport, forceMobileSupport, segmentationOptions, } = props;
55
107
  const call = useCall();
56
108
  const { useCallStatsReport } = useCallStateHooks();
57
109
  const callStatsReport = useCallStatsReport();
@@ -60,35 +112,29 @@ const BackgroundFiltersProvider = (props) => {
60
112
  const [backgroundBlurLevel, setBackgroundBlurLevel] = useState(bgBlurLevelFromProps);
61
113
  const [showLowFpsWarning, setShowLowFpsWarning] = useState(false);
62
114
  const [isLoading, setIsLoading] = useState(false);
115
+ const rootFps = useTrackFramesPerSecond(call);
63
116
  const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;
64
- const sourceFps = performanceThresholds?.defaultFps || cameraFrameRate || DEFAULT_FPS;
65
- const fpsWarningThresholdLower = performanceThresholds?.fpsWarningThresholdLower ?? sourceFps * 0.75;
66
- const fpsWarningThresholdUpper = performanceThresholds?.fpsWarningThresholdUpper ?? sourceFps * 0.85;
67
- const emaRef = useRef(sourceFps);
68
- const outlierStreakRef = useRef(0);
117
+ const sourceFps = rootFps ?? cameraFrameRate;
118
+ const fpsRatioEmaRef = useRef(undefined);
69
119
  const handleStats = useCallback((stats) => {
70
120
  const fps = stats?.fps;
71
- if (fps === undefined || fps === null) {
72
- emaRef.current = sourceFps;
73
- outlierStreakRef.current = 0;
121
+ if (fps == null || !sourceFps) {
122
+ fpsRatioEmaRef.current = undefined;
74
123
  setShowLowFpsWarning(false);
75
124
  return;
76
125
  }
77
- const prevEma = emaRef.current;
78
- const deviation = Math.abs(fps - prevEma) / prevEma;
79
- const isOutlier = fps < prevEma && deviation > DEVIATION_LIMIT;
80
- outlierStreakRef.current = isOutlier ? outlierStreakRef.current + 1 : 0;
81
- if (isOutlier && outlierStreakRef.current < OUTLIER_PERSISTENCE)
82
- return;
83
- emaRef.current = ALPHA * fps + (1 - ALPHA) * prevEma;
126
+ const ratio = fps / sourceFps;
127
+ const prevRatioEma = fpsRatioEmaRef.current ?? ratio;
128
+ const nextFpsRatioEma = ALPHA * ratio + (1 - ALPHA) * prevRatioEma;
129
+ fpsRatioEmaRef.current = nextFpsRatioEma;
84
130
  setShowLowFpsWarning((prev) => {
85
- if (prev && emaRef.current > fpsWarningThresholdUpper)
131
+ if (prev && nextFpsRatioEma > FPS_RATIO_WARNING_THRESHOLD_UPPER)
86
132
  return false;
87
- if (!prev && emaRef.current < fpsWarningThresholdLower)
133
+ if (!prev && nextFpsRatioEma < FPS_RATIO_WARNING_THRESHOLD_LOWER)
88
134
  return true;
89
135
  return prev;
90
136
  });
91
- }, [fpsWarningThresholdLower, fpsWarningThresholdUpper, sourceFps]);
137
+ }, [sourceFps]);
92
138
  const performance = useMemo(() => {
93
139
  if (!backgroundFilter) {
94
140
  return { degraded: false };
@@ -122,16 +168,17 @@ const BackgroundFiltersProvider = (props) => {
122
168
  call?.tracer.trace('backgroundFilters.performance', {
123
169
  degraded: currentDegraded,
124
170
  reason: performance?.reason,
125
- fps: emaRef.current,
171
+ ratio: fpsRatioEmaRef.current,
172
+ sourceFps,
126
173
  });
127
174
  }
128
175
  prevDegradedRef.current = currentDegraded;
129
176
  }, [
130
- performanceThresholds,
131
177
  performance.degraded,
132
178
  performance.reason,
133
179
  backgroundFilter,
134
180
  call?.tracer,
181
+ sourceFps,
135
182
  ]);
136
183
  const applyBackgroundImageFilter = useCallback((imageUrl) => {
137
184
  setBackgroundFilter('image');
@@ -145,10 +192,9 @@ const BackgroundFiltersProvider = (props) => {
145
192
  setBackgroundFilter(undefined);
146
193
  setBackgroundImage(undefined);
147
194
  setBackgroundBlurLevel(undefined);
148
- emaRef.current = sourceFps;
149
- outlierStreakRef.current = 0;
195
+ fpsRatioEmaRef.current = undefined;
150
196
  setShowLowFpsWarning(false);
151
- }, [sourceFps]);
197
+ }, []);
152
198
  const [engine, setEngine] = useState(FilterEngine.NONE);
153
199
  const [isSupported, setIsSupported] = useState(false);
154
200
  useEffect(() => {
@@ -182,7 +228,7 @@ const BackgroundFiltersProvider = (props) => {
182
228
  onError?.(error);
183
229
  }, [disableBackgroundFilter, onError]);
184
230
  const isReady = useLegacyFilter ? !!tfLite : !!mediaPipe;
185
- const contextValue = {
231
+ const contextValue = useMemo(() => ({
186
232
  isSupported,
187
233
  performance,
188
234
  isReady,
@@ -199,7 +245,24 @@ const BackgroundFiltersProvider = (props) => {
199
245
  basePath,
200
246
  onError: handleError,
201
247
  segmentationOptions,
202
- };
248
+ }), [
249
+ isSupported,
250
+ performance,
251
+ isReady,
252
+ isLoading,
253
+ backgroundImage,
254
+ backgroundBlurLevel,
255
+ backgroundFilter,
256
+ disableBackgroundFilter,
257
+ applyBackgroundBlurFilter,
258
+ applyBackgroundImageFilter,
259
+ backgroundImages,
260
+ tfFilePath,
261
+ modelFilePath,
262
+ basePath,
263
+ handleError,
264
+ segmentationOptions,
265
+ ]);
203
266
  return (jsxs(ContextProvider.Provider, { value: contextValue, children: [children, isReady && (jsx(BackgroundFilters, { api: contextValue, tfLite: tfLite, engine: engine, onStats: handleStats, setIsLoading: setIsLoading }))] }));
204
267
  };
205
268
  const BackgroundFilters = (props) => {
@@ -354,4 +417,4 @@ const useRenderer = (api, tfLite, call, engine) => {
354
417
  };
355
418
 
356
419
  export { BackgroundFiltersProvider };
357
- //# sourceMappingURL=background-filters-g6ozIvlN.es.js.map
420
+ //# sourceMappingURL=embedded-BackgroundFilters-D2U5UBbH.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded-BackgroundFilters-D2U5UBbH.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\ntype MediaStreamTrackVideoStats = {\n deliveredFrames: number;\n discardedFrames: number;\n totalFrames: number;\n};\n\ntype MediaStreamTrackWithStats = MediaStreamTrack & {\n stats?: MediaStreamTrackVideoStats;\n};\n\n/**\n * Constants for FPS warning calculation.\n * Smooths the processed-to-source FPS ratio and uses hysteresis\n * so the degradation warning doesn't flicker near the limit.\n */\nconst ALPHA = 0.2;\nconst FPS_RATIO_WARNING_THRESHOLD_LOWER = 0.75;\nconst FPS_RATIO_WARNING_THRESHOLD_UPPER = 0.85;\n\nconst EMPTY_BACKGROUND_IMAGES: string[] = [];\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 * Samples the raw camera track's frame stats (W3C MediaCapture Extensions) at a\n * fixed interval and returns a live source fps estimate. Returns `undefined`\n * while warming up, when the camera is off, or when the browser doesn't expose\n * `MediaStreamTrack.stats` (currently Chromium-only).\n */\nconst useTrackFramesPerSecond = (call: Call | undefined) => {\n const { useCameraState } = useCallStateHooks();\n const { rootMediaStream } = useCameraState();\n const [fps, setFps] = useState<number | undefined>(undefined);\n const trackId = rootMediaStream?.getVideoTracks()[0]?.id;\n\n useEffect(() => {\n if (!call) {\n setFps(undefined);\n return;\n }\n\n let previousSnapshot:\n | (MediaStreamTrackVideoStats & { capturedAt: number })\n | undefined;\n let previousTrackId: string | undefined;\n\n const intervalId = setInterval(() => {\n const track = rootMediaStream?.getVideoTracks()[0] as\n | MediaStreamTrackWithStats\n | undefined;\n\n const stats = track?.stats;\n if (!track || !stats) {\n previousSnapshot = undefined;\n setFps(undefined);\n return;\n }\n\n if (track.id !== previousTrackId) {\n previousTrackId = track.id;\n previousSnapshot = undefined;\n setFps(undefined);\n }\n\n const currentSnapshot = {\n deliveredFrames: stats.deliveredFrames,\n discardedFrames: stats.discardedFrames,\n totalFrames: stats.totalFrames,\n capturedAt: performance.now(),\n };\n\n if (previousSnapshot) {\n const elapsedSec =\n (currentSnapshot.capturedAt - previousSnapshot.capturedAt) / 1000;\n\n const delivered =\n currentSnapshot.deliveredFrames - previousSnapshot.deliveredFrames;\n\n const nextFps = Math.round(delivered / elapsedSec);\n setFps(nextFps);\n }\n previousSnapshot = currentSnapshot;\n }, 1000);\n\n return () => {\n clearInterval(intervalId);\n setFps(undefined);\n };\n }, [call, rootMediaStream, trackId]);\n\n return fps;\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 = EMPTY_BACKGROUND_IMAGES,\n backgroundFilter: bgFilterFromProps = undefined,\n backgroundImage: bgImageFromProps = undefined,\n backgroundBlurLevel: bgBlurLevelFromProps = undefined,\n tfFilePath,\n modelFilePath,\n useLegacyFilter,\n basePath,\n onError,\n forceSafariSupport,\n forceMobileSupport,\n segmentationOptions,\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 rootFps = useTrackFramesPerSecond(call);\n const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;\n\n const sourceFps = rootFps ?? cameraFrameRate;\n const fpsRatioEmaRef = useRef<number | undefined>(undefined);\n\n const handleStats = useCallback(\n (stats: PerformanceStats) => {\n const fps = stats?.fps;\n if (fps == null || !sourceFps) {\n fpsRatioEmaRef.current = undefined;\n setShowLowFpsWarning(false);\n return;\n }\n\n const ratio = fps / sourceFps;\n const prevRatioEma = fpsRatioEmaRef.current ?? ratio;\n\n const nextFpsRatioEma = ALPHA * ratio + (1 - ALPHA) * prevRatioEma;\n fpsRatioEmaRef.current = nextFpsRatioEma;\n\n setShowLowFpsWarning((prev) => {\n if (prev && nextFpsRatioEma > FPS_RATIO_WARNING_THRESHOLD_UPPER)\n return false;\n if (!prev && nextFpsRatioEma < FPS_RATIO_WARNING_THRESHOLD_LOWER)\n return true;\n\n return prev;\n });\n },\n [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 ratio: fpsRatioEmaRef.current,\n sourceFps,\n });\n }\n prevDegradedRef.current = currentDegraded;\n }, [\n performance.degraded,\n performance.reason,\n backgroundFilter,\n call?.tracer,\n sourceFps,\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 fpsRatioEmaRef.current = undefined;\n setShowLowFpsWarning(false);\n }, []);\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\n const contextValue = useMemo<BackgroundFiltersContextValue>(\n () => ({\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 segmentationOptions,\n }),\n [\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 handleError,\n segmentationOptions,\n ],\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 segmentationOptions,\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 modelFilePath,\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 segmentationOptions,\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 segmentationOptions,\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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"}
@@ -10,13 +10,13 @@ var clsx = require('clsx');
10
10
 
11
11
  /**
12
12
  * Constants for FPS warning calculation.
13
- * Smooths out quick spikes using an EMA, ignores brief outliers,
14
- * and uses two thresholds to avoid flickering near the limit.
13
+ * Smooths the processed-to-source FPS ratio and uses hysteresis
14
+ * so the degradation warning doesn't flicker near the limit.
15
15
  */
16
16
  const ALPHA = 0.2;
17
- const DEFAULT_FPS = 30;
18
- const DEVIATION_LIMIT = 0.5;
19
- const OUTLIER_PERSISTENCE = 5;
17
+ const FPS_RATIO_WARNING_THRESHOLD_LOWER = 0.75;
18
+ const FPS_RATIO_WARNING_THRESHOLD_UPPER = 0.85;
19
+ const EMPTY_BACKGROUND_IMAGES = [];
20
20
  /**
21
21
  * Represents the available background filter processing engines.
22
22
  */
@@ -46,6 +46,58 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
46
46
  });
47
47
  return isMediaPipeSupported ? FilterEngine.MEDIA_PIPE : FilterEngine.NONE;
48
48
  };
49
+ /**
50
+ * Samples the raw camera track's frame stats (W3C MediaCapture Extensions) at a
51
+ * fixed interval and returns a live source fps estimate. Returns `undefined`
52
+ * while warming up, when the camera is off, or when the browser doesn't expose
53
+ * `MediaStreamTrack.stats` (currently Chromium-only).
54
+ */
55
+ const useTrackFramesPerSecond = (call) => {
56
+ const { useCameraState } = videoReactBindings.useCallStateHooks();
57
+ const { rootMediaStream } = useCameraState();
58
+ const [fps, setFps] = react.useState(undefined);
59
+ const trackId = rootMediaStream?.getVideoTracks()[0]?.id;
60
+ react.useEffect(() => {
61
+ if (!call) {
62
+ setFps(undefined);
63
+ return;
64
+ }
65
+ let previousSnapshot;
66
+ let previousTrackId;
67
+ const intervalId = setInterval(() => {
68
+ const track = rootMediaStream?.getVideoTracks()[0];
69
+ const stats = track?.stats;
70
+ if (!track || !stats) {
71
+ previousSnapshot = undefined;
72
+ setFps(undefined);
73
+ return;
74
+ }
75
+ if (track.id !== previousTrackId) {
76
+ previousTrackId = track.id;
77
+ previousSnapshot = undefined;
78
+ setFps(undefined);
79
+ }
80
+ const currentSnapshot = {
81
+ deliveredFrames: stats.deliveredFrames,
82
+ discardedFrames: stats.discardedFrames,
83
+ totalFrames: stats.totalFrames,
84
+ capturedAt: performance.now(),
85
+ };
86
+ if (previousSnapshot) {
87
+ const elapsedSec = (currentSnapshot.capturedAt - previousSnapshot.capturedAt) / 1000;
88
+ const delivered = currentSnapshot.deliveredFrames - previousSnapshot.deliveredFrames;
89
+ const nextFps = Math.round(delivered / elapsedSec);
90
+ setFps(nextFps);
91
+ }
92
+ previousSnapshot = currentSnapshot;
93
+ }, 1000);
94
+ return () => {
95
+ clearInterval(intervalId);
96
+ setFps(undefined);
97
+ };
98
+ }, [call, rootMediaStream, trackId]);
99
+ return fps;
100
+ };
49
101
  /**
50
102
  * A provider component that enables the use of background filters in your app.
51
103
  *
@@ -53,7 +105,7 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
53
105
  * in your project before using this component.
54
106
  */
55
107
  const BackgroundFiltersProvider = (props) => {
56
- const { ContextProvider, children, backgroundImages = [], backgroundFilter: bgFilterFromProps = undefined, backgroundImage: bgImageFromProps = undefined, backgroundBlurLevel: bgBlurLevelFromProps = undefined, tfFilePath, modelFilePath, useLegacyFilter, basePath, onError, performanceThresholds, forceSafariSupport, forceMobileSupport, segmentationOptions, } = props;
108
+ const { ContextProvider, children, backgroundImages = EMPTY_BACKGROUND_IMAGES, backgroundFilter: bgFilterFromProps = undefined, backgroundImage: bgImageFromProps = undefined, backgroundBlurLevel: bgBlurLevelFromProps = undefined, tfFilePath, modelFilePath, useLegacyFilter, basePath, onError, forceSafariSupport, forceMobileSupport, segmentationOptions, } = props;
57
109
  const call = videoReactBindings.useCall();
58
110
  const { useCallStatsReport } = videoReactBindings.useCallStateHooks();
59
111
  const callStatsReport = useCallStatsReport();
@@ -62,35 +114,29 @@ const BackgroundFiltersProvider = (props) => {
62
114
  const [backgroundBlurLevel, setBackgroundBlurLevel] = react.useState(bgBlurLevelFromProps);
63
115
  const [showLowFpsWarning, setShowLowFpsWarning] = react.useState(false);
64
116
  const [isLoading, setIsLoading] = react.useState(false);
117
+ const rootFps = useTrackFramesPerSecond(call);
65
118
  const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;
66
- const sourceFps = performanceThresholds?.defaultFps || cameraFrameRate || DEFAULT_FPS;
67
- const fpsWarningThresholdLower = performanceThresholds?.fpsWarningThresholdLower ?? sourceFps * 0.75;
68
- const fpsWarningThresholdUpper = performanceThresholds?.fpsWarningThresholdUpper ?? sourceFps * 0.85;
69
- const emaRef = react.useRef(sourceFps);
70
- const outlierStreakRef = react.useRef(0);
119
+ const sourceFps = rootFps ?? cameraFrameRate;
120
+ const fpsRatioEmaRef = react.useRef(undefined);
71
121
  const handleStats = react.useCallback((stats) => {
72
122
  const fps = stats?.fps;
73
- if (fps === undefined || fps === null) {
74
- emaRef.current = sourceFps;
75
- outlierStreakRef.current = 0;
123
+ if (fps == null || !sourceFps) {
124
+ fpsRatioEmaRef.current = undefined;
76
125
  setShowLowFpsWarning(false);
77
126
  return;
78
127
  }
79
- const prevEma = emaRef.current;
80
- const deviation = Math.abs(fps - prevEma) / prevEma;
81
- const isOutlier = fps < prevEma && deviation > DEVIATION_LIMIT;
82
- outlierStreakRef.current = isOutlier ? outlierStreakRef.current + 1 : 0;
83
- if (isOutlier && outlierStreakRef.current < OUTLIER_PERSISTENCE)
84
- return;
85
- emaRef.current = ALPHA * fps + (1 - ALPHA) * prevEma;
128
+ const ratio = fps / sourceFps;
129
+ const prevRatioEma = fpsRatioEmaRef.current ?? ratio;
130
+ const nextFpsRatioEma = ALPHA * ratio + (1 - ALPHA) * prevRatioEma;
131
+ fpsRatioEmaRef.current = nextFpsRatioEma;
86
132
  setShowLowFpsWarning((prev) => {
87
- if (prev && emaRef.current > fpsWarningThresholdUpper)
133
+ if (prev && nextFpsRatioEma > FPS_RATIO_WARNING_THRESHOLD_UPPER)
88
134
  return false;
89
- if (!prev && emaRef.current < fpsWarningThresholdLower)
135
+ if (!prev && nextFpsRatioEma < FPS_RATIO_WARNING_THRESHOLD_LOWER)
90
136
  return true;
91
137
  return prev;
92
138
  });
93
- }, [fpsWarningThresholdLower, fpsWarningThresholdUpper, sourceFps]);
139
+ }, [sourceFps]);
94
140
  const performance = react.useMemo(() => {
95
141
  if (!backgroundFilter) {
96
142
  return { degraded: false };
@@ -124,16 +170,17 @@ const BackgroundFiltersProvider = (props) => {
124
170
  call?.tracer.trace('backgroundFilters.performance', {
125
171
  degraded: currentDegraded,
126
172
  reason: performance?.reason,
127
- fps: emaRef.current,
173
+ ratio: fpsRatioEmaRef.current,
174
+ sourceFps,
128
175
  });
129
176
  }
130
177
  prevDegradedRef.current = currentDegraded;
131
178
  }, [
132
- performanceThresholds,
133
179
  performance.degraded,
134
180
  performance.reason,
135
181
  backgroundFilter,
136
182
  call?.tracer,
183
+ sourceFps,
137
184
  ]);
138
185
  const applyBackgroundImageFilter = react.useCallback((imageUrl) => {
139
186
  setBackgroundFilter('image');
@@ -147,10 +194,9 @@ const BackgroundFiltersProvider = (props) => {
147
194
  setBackgroundFilter(undefined);
148
195
  setBackgroundImage(undefined);
149
196
  setBackgroundBlurLevel(undefined);
150
- emaRef.current = sourceFps;
151
- outlierStreakRef.current = 0;
197
+ fpsRatioEmaRef.current = undefined;
152
198
  setShowLowFpsWarning(false);
153
- }, [sourceFps]);
199
+ }, []);
154
200
  const [engine, setEngine] = react.useState(FilterEngine.NONE);
155
201
  const [isSupported, setIsSupported] = react.useState(false);
156
202
  react.useEffect(() => {
@@ -184,7 +230,7 @@ const BackgroundFiltersProvider = (props) => {
184
230
  onError?.(error);
185
231
  }, [disableBackgroundFilter, onError]);
186
232
  const isReady = useLegacyFilter ? !!tfLite : !!mediaPipe;
187
- const contextValue = {
233
+ const contextValue = react.useMemo(() => ({
188
234
  isSupported,
189
235
  performance,
190
236
  isReady,
@@ -201,7 +247,24 @@ const BackgroundFiltersProvider = (props) => {
201
247
  basePath,
202
248
  onError: handleError,
203
249
  segmentationOptions,
204
- };
250
+ }), [
251
+ isSupported,
252
+ performance,
253
+ isReady,
254
+ isLoading,
255
+ backgroundImage,
256
+ backgroundBlurLevel,
257
+ backgroundFilter,
258
+ disableBackgroundFilter,
259
+ applyBackgroundBlurFilter,
260
+ applyBackgroundImageFilter,
261
+ backgroundImages,
262
+ tfFilePath,
263
+ modelFilePath,
264
+ basePath,
265
+ handleError,
266
+ segmentationOptions,
267
+ ]);
205
268
  return (jsxRuntime.jsxs(ContextProvider.Provider, { value: contextValue, children: [children, isReady && (jsxRuntime.jsx(BackgroundFilters, { api: contextValue, tfLite: tfLite, engine: engine, onStats: handleStats, setIsLoading: setIsLoading }))] }));
206
269
  };
207
270
  const BackgroundFilters = (props) => {
@@ -356,4 +419,4 @@ const useRenderer = (api, tfLite, call, engine) => {
356
419
  };
357
420
 
358
421
  exports.BackgroundFiltersProvider = BackgroundFiltersProvider;
359
- //# sourceMappingURL=embedded-BackgroundFilters-DdQqSx4T.cjs.js.map
422
+ //# sourceMappingURL=embedded-BackgroundFilters-folwWrgs.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded-BackgroundFilters-folwWrgs.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\ntype MediaStreamTrackVideoStats = {\n deliveredFrames: number;\n discardedFrames: number;\n totalFrames: number;\n};\n\ntype MediaStreamTrackWithStats = MediaStreamTrack & {\n stats?: MediaStreamTrackVideoStats;\n};\n\n/**\n * Constants for FPS warning calculation.\n * Smooths the processed-to-source FPS ratio and uses hysteresis\n * so the degradation warning doesn't flicker near the limit.\n */\nconst ALPHA = 0.2;\nconst FPS_RATIO_WARNING_THRESHOLD_LOWER = 0.75;\nconst FPS_RATIO_WARNING_THRESHOLD_UPPER = 0.85;\n\nconst EMPTY_BACKGROUND_IMAGES: string[] = [];\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 * Samples the raw camera track's frame stats (W3C MediaCapture Extensions) at a\n * fixed interval and returns a live source fps estimate. Returns `undefined`\n * while warming up, when the camera is off, or when the browser doesn't expose\n * `MediaStreamTrack.stats` (currently Chromium-only).\n */\nconst useTrackFramesPerSecond = (call: Call | undefined) => {\n const { useCameraState } = useCallStateHooks();\n const { rootMediaStream } = useCameraState();\n const [fps, setFps] = useState<number | undefined>(undefined);\n const trackId = rootMediaStream?.getVideoTracks()[0]?.id;\n\n useEffect(() => {\n if (!call) {\n setFps(undefined);\n return;\n }\n\n let previousSnapshot:\n | (MediaStreamTrackVideoStats & { capturedAt: number })\n | undefined;\n let previousTrackId: string | undefined;\n\n const intervalId = setInterval(() => {\n const track = rootMediaStream?.getVideoTracks()[0] as\n | MediaStreamTrackWithStats\n | undefined;\n\n const stats = track?.stats;\n if (!track || !stats) {\n previousSnapshot = undefined;\n setFps(undefined);\n return;\n }\n\n if (track.id !== previousTrackId) {\n previousTrackId = track.id;\n previousSnapshot = undefined;\n setFps(undefined);\n }\n\n const currentSnapshot = {\n deliveredFrames: stats.deliveredFrames,\n discardedFrames: stats.discardedFrames,\n totalFrames: stats.totalFrames,\n capturedAt: performance.now(),\n };\n\n if (previousSnapshot) {\n const elapsedSec =\n (currentSnapshot.capturedAt - previousSnapshot.capturedAt) / 1000;\n\n const delivered =\n currentSnapshot.deliveredFrames - previousSnapshot.deliveredFrames;\n\n const nextFps = Math.round(delivered / elapsedSec);\n setFps(nextFps);\n }\n previousSnapshot = currentSnapshot;\n }, 1000);\n\n return () => {\n clearInterval(intervalId);\n setFps(undefined);\n };\n }, [call, rootMediaStream, trackId]);\n\n return fps;\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 = EMPTY_BACKGROUND_IMAGES,\n backgroundFilter: bgFilterFromProps = undefined,\n backgroundImage: bgImageFromProps = undefined,\n backgroundBlurLevel: bgBlurLevelFromProps = undefined,\n tfFilePath,\n modelFilePath,\n useLegacyFilter,\n basePath,\n onError,\n forceSafariSupport,\n forceMobileSupport,\n segmentationOptions,\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 rootFps = useTrackFramesPerSecond(call);\n const cameraFrameRate = callStatsReport?.publisherStats?.camera?.frameRate;\n\n const sourceFps = rootFps ?? cameraFrameRate;\n const fpsRatioEmaRef = useRef<number | undefined>(undefined);\n\n const handleStats = useCallback(\n (stats: PerformanceStats) => {\n const fps = stats?.fps;\n if (fps == null || !sourceFps) {\n fpsRatioEmaRef.current = undefined;\n setShowLowFpsWarning(false);\n return;\n }\n\n const ratio = fps / sourceFps;\n const prevRatioEma = fpsRatioEmaRef.current ?? ratio;\n\n const nextFpsRatioEma = ALPHA * ratio + (1 - ALPHA) * prevRatioEma;\n fpsRatioEmaRef.current = nextFpsRatioEma;\n\n setShowLowFpsWarning((prev) => {\n if (prev && nextFpsRatioEma > FPS_RATIO_WARNING_THRESHOLD_UPPER)\n return false;\n if (!prev && nextFpsRatioEma < FPS_RATIO_WARNING_THRESHOLD_LOWER)\n return true;\n\n return prev;\n });\n },\n [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 ratio: fpsRatioEmaRef.current,\n sourceFps,\n });\n }\n prevDegradedRef.current = currentDegraded;\n }, [\n performance.degraded,\n performance.reason,\n backgroundFilter,\n call?.tracer,\n sourceFps,\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 fpsRatioEmaRef.current = undefined;\n setShowLowFpsWarning(false);\n }, []);\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\n const contextValue = useMemo<BackgroundFiltersContextValue>(\n () => ({\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 segmentationOptions,\n }),\n [\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 handleError,\n segmentationOptions,\n ],\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 segmentationOptions,\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 modelFilePath,\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 segmentationOptions,\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 segmentationOptions,\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","useCallStateHooks","useState","useEffect","useCall","useRef","useCallback","useMemo","loadTFLite","loadMediaPipe","_jsxs","_jsx","flushSync","VirtualBackground","createRenderer","disposeOfMediaStream"],"mappings":"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"}
@@ -686,7 +686,7 @@ const AvatarFallback = ({ className, names, style, }) => {
686
686
  return (jsxRuntime.jsx("div", { className: clsx('str-video__avatar--initials-fallback', className), style: style, children: jsxRuntime.jsxs("div", { children: [names[0][0], names[1]?.[0]] }) }));
687
687
  };
688
688
 
689
- const BackgroundFiltersProviderImpl = react.lazy(() => Promise.resolve().then(function () { return require('./embedded-BackgroundFilters-DdQqSx4T.cjs.js'); }).then((m) => ({
689
+ const BackgroundFiltersProviderImpl = react.lazy(() => Promise.resolve().then(function () { return require('./embedded-BackgroundFilters-folwWrgs.cjs.js'); }).then((m) => ({
690
690
  default: m.BackgroundFiltersProvider,
691
691
  })));
692
692
  /**
@@ -1207,7 +1207,7 @@ const SpeakerTest = (props) => {
1207
1207
  const audioElementRef = react.useRef(null);
1208
1208
  const [isPlaying, setIsPlaying] = react.useState(false);
1209
1209
  const { t } = videoReactBindings.useI18n();
1210
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.0"}/assets/piano.mp3`, } = props;
1210
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.1"}/assets/piano.mp3`, } = props;
1211
1211
  // Update audio output device when selection changes
1212
1212
  react.useEffect(() => {
1213
1213
  const audio = audioElementRef.current;
@@ -684,7 +684,7 @@ const AvatarFallback = ({ className, names, style, }) => {
684
684
  return (jsx("div", { className: clsx('str-video__avatar--initials-fallback', className), style: style, children: jsxs("div", { children: [names[0][0], names[1]?.[0]] }) }));
685
685
  };
686
686
 
687
- const BackgroundFiltersProviderImpl = lazy(() => import('./embedded-BackgroundFilters-g6ozIvlN.es.js').then((m) => ({
687
+ const BackgroundFiltersProviderImpl = lazy(() => import('./embedded-BackgroundFilters-D2U5UBbH.es.js').then((m) => ({
688
688
  default: m.BackgroundFiltersProvider,
689
689
  })));
690
690
  /**
@@ -1205,7 +1205,7 @@ const SpeakerTest = (props) => {
1205
1205
  const audioElementRef = useRef(null);
1206
1206
  const [isPlaying, setIsPlaying] = useState(false);
1207
1207
  const { t } = useI18n();
1208
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.0"}/assets/piano.mp3`, } = props;
1208
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.1"}/assets/piano.mp3`, } = props;
1209
1209
  // Update audio output device when selection changes
1210
1210
  useEffect(() => {
1211
1211
  const audio = audioElementRef.current;
package/dist/index.cjs.js CHANGED
@@ -828,7 +828,7 @@ const AvatarFallback = ({ className, names, style, }) => {
828
828
  return (jsxRuntime.jsx("div", { className: clsx('str-video__avatar--initials-fallback', className), style: style, children: jsxRuntime.jsxs("div", { children: [names[0][0], names[1]?.[0]] }) }));
829
829
  };
830
830
 
831
- const BackgroundFiltersProviderImpl = react.lazy(() => Promise.resolve().then(function () { return require('./background-filters-DdQqSx4T.cjs.js'); }).then((m) => ({
831
+ const BackgroundFiltersProviderImpl = react.lazy(() => Promise.resolve().then(function () { return require('./background-filters-folwWrgs.cjs.js'); }).then((m) => ({
832
832
  default: m.BackgroundFiltersProvider,
833
833
  })));
834
834
  /**
@@ -1403,7 +1403,7 @@ const SpeakerTest = (props) => {
1403
1403
  const audioElementRef = react.useRef(null);
1404
1404
  const [isPlaying, setIsPlaying] = react.useState(false);
1405
1405
  const { t } = videoReactBindings.useI18n();
1406
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.0"}/assets/piano.mp3`, } = props;
1406
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.36.1"}/assets/piano.mp3`, } = props;
1407
1407
  // Update audio output device when selection changes
1408
1408
  react.useEffect(() => {
1409
1409
  const audio = audioElementRef.current;
@@ -3236,7 +3236,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
3236
3236
  return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
3237
3237
  };
3238
3238
 
3239
- const [major, minor, patch] = ("1.36.0").split('.');
3239
+ const [major, minor, patch] = ("1.36.1").split('.');
3240
3240
  videoClient.setSdkInfo({
3241
3241
  type: videoClient.SfuModels.SdkType.REACT,
3242
3242
  major,