@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
|
@@ -53,7 +53,7 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
|
|
|
53
53
|
* in your project before using this component.
|
|
54
54
|
*/
|
|
55
55
|
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, } = 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;
|
|
57
57
|
const call = videoReactBindings.useCall();
|
|
58
58
|
const { useCallStatsReport } = videoReactBindings.useCallStateHooks();
|
|
59
59
|
const callStatsReport = useCallStatsReport();
|
|
@@ -200,6 +200,7 @@ const BackgroundFiltersProvider = (props) => {
|
|
|
200
200
|
modelFilePath,
|
|
201
201
|
basePath,
|
|
202
202
|
onError: handleError,
|
|
203
|
+
segmentationOptions,
|
|
203
204
|
};
|
|
204
205
|
return (jsxRuntime.jsxs(ContextProvider.Provider, { value: contextValue, children: [children, isReady && (jsxRuntime.jsx(BackgroundFilters, { api: contextValue, tfLite: tfLite, engine: engine, onStats: handleStats, setIsLoading: setIsLoading }))] }));
|
|
205
206
|
};
|
|
@@ -229,7 +230,7 @@ const BackgroundFilters = (props) => {
|
|
|
229
230
|
return children;
|
|
230
231
|
};
|
|
231
232
|
const useRenderer = (api, tfLite, call, engine) => {
|
|
232
|
-
const { backgroundFilter, backgroundBlurLevel, backgroundImage, modelFilePath, basePath, } = api;
|
|
233
|
+
const { backgroundFilter, backgroundBlurLevel, backgroundImage, modelFilePath, basePath, segmentationOptions, } = api;
|
|
233
234
|
const videoRef = react.useRef(null);
|
|
234
235
|
const canvasRef = react.useRef(null);
|
|
235
236
|
const bgImageRef = react.useRef(null);
|
|
@@ -260,6 +261,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
260
261
|
backgroundBlurLevel,
|
|
261
262
|
backgroundImage,
|
|
262
263
|
engine,
|
|
264
|
+
modelFilePath,
|
|
263
265
|
});
|
|
264
266
|
if (!videoEl) {
|
|
265
267
|
reject(new Error('Renderer started before elements are ready'));
|
|
@@ -276,6 +278,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
276
278
|
backgroundBlurLevel,
|
|
277
279
|
backgroundImage,
|
|
278
280
|
backgroundFilter,
|
|
281
|
+
segmentationOptions,
|
|
279
282
|
}, { onError, onStats });
|
|
280
283
|
processor
|
|
281
284
|
.start()
|
|
@@ -345,6 +348,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
345
348
|
engine,
|
|
346
349
|
modelFilePath,
|
|
347
350
|
basePath,
|
|
351
|
+
segmentationOptions,
|
|
348
352
|
]);
|
|
349
353
|
const children = (jsxRuntime.jsxs("div", { className: "str-video__background-filters", children: [jsxRuntime.jsx("video", { className: clsx('str-video__background-filters__video', videoSize.height > videoSize.width &&
|
|
350
354
|
'str-video__background-filters__video--tall'), ref: videoRef, playsInline: true, muted: true, controls: false, ...videoSize }), backgroundImage && (jsxRuntime.jsx("img", { className: "str-video__background-filters__background-image", alt: "Background", ref: bgImageRef, crossOrigin: "anonymous", src: backgroundImage, ...videoSize })), jsxRuntime.jsx("canvas", { className: "str-video__background-filters__target-canvas", ...videoSize, ref: canvasRef })] }));
|
|
@@ -352,4 +356,4 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
352
356
|
};
|
|
353
357
|
|
|
354
358
|
exports.BackgroundFiltersProvider = BackgroundFiltersProvider;
|
|
355
|
-
//# sourceMappingURL=embedded-BackgroundFilters-
|
|
359
|
+
//# sourceMappingURL=embedded-BackgroundFilters-DdQqSx4T.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-BackgroundFilters-DdQqSx4T.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 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 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 segmentationOptions,\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","useCall","useCallStateHooks","useState","useRef","useCallback","useMemo","useEffect","loadTFLite","loadMediaPipe","_jsxs","_jsx","flushSync","VirtualBackground","createRenderer","disposeOfMediaStream"],"mappings":"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"}
|
package/dist/{embedded-BackgroundFilters-RdXfNf6_.es.js → embedded-BackgroundFilters-g6ozIvlN.es.js}
RENAMED
|
@@ -51,7 +51,7 @@ const determineEngine = async (useLegacyFilter, forceSafariSupport, forceMobileS
|
|
|
51
51
|
* in your project before using this component.
|
|
52
52
|
*/
|
|
53
53
|
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, } = 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;
|
|
55
55
|
const call = useCall();
|
|
56
56
|
const { useCallStatsReport } = useCallStateHooks();
|
|
57
57
|
const callStatsReport = useCallStatsReport();
|
|
@@ -198,6 +198,7 @@ const BackgroundFiltersProvider = (props) => {
|
|
|
198
198
|
modelFilePath,
|
|
199
199
|
basePath,
|
|
200
200
|
onError: handleError,
|
|
201
|
+
segmentationOptions,
|
|
201
202
|
};
|
|
202
203
|
return (jsxs(ContextProvider.Provider, { value: contextValue, children: [children, isReady && (jsx(BackgroundFilters, { api: contextValue, tfLite: tfLite, engine: engine, onStats: handleStats, setIsLoading: setIsLoading }))] }));
|
|
203
204
|
};
|
|
@@ -227,7 +228,7 @@ const BackgroundFilters = (props) => {
|
|
|
227
228
|
return children;
|
|
228
229
|
};
|
|
229
230
|
const useRenderer = (api, tfLite, call, engine) => {
|
|
230
|
-
const { backgroundFilter, backgroundBlurLevel, backgroundImage, modelFilePath, basePath, } = api;
|
|
231
|
+
const { backgroundFilter, backgroundBlurLevel, backgroundImage, modelFilePath, basePath, segmentationOptions, } = api;
|
|
231
232
|
const videoRef = useRef(null);
|
|
232
233
|
const canvasRef = useRef(null);
|
|
233
234
|
const bgImageRef = useRef(null);
|
|
@@ -258,6 +259,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
258
259
|
backgroundBlurLevel,
|
|
259
260
|
backgroundImage,
|
|
260
261
|
engine,
|
|
262
|
+
modelFilePath,
|
|
261
263
|
});
|
|
262
264
|
if (!videoEl) {
|
|
263
265
|
reject(new Error('Renderer started before elements are ready'));
|
|
@@ -274,6 +276,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
274
276
|
backgroundBlurLevel,
|
|
275
277
|
backgroundImage,
|
|
276
278
|
backgroundFilter,
|
|
279
|
+
segmentationOptions,
|
|
277
280
|
}, { onError, onStats });
|
|
278
281
|
processor
|
|
279
282
|
.start()
|
|
@@ -343,6 +346,7 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
343
346
|
engine,
|
|
344
347
|
modelFilePath,
|
|
345
348
|
basePath,
|
|
349
|
+
segmentationOptions,
|
|
346
350
|
]);
|
|
347
351
|
const children = (jsxs("div", { className: "str-video__background-filters", children: [jsx("video", { className: clsx('str-video__background-filters__video', videoSize.height > videoSize.width &&
|
|
348
352
|
'str-video__background-filters__video--tall'), ref: videoRef, playsInline: true, muted: true, controls: false, ...videoSize }), backgroundImage && (jsx("img", { className: "str-video__background-filters__background-image", alt: "Background", ref: bgImageRef, crossOrigin: "anonymous", src: backgroundImage, ...videoSize })), jsx("canvas", { className: "str-video__background-filters__target-canvas", ...videoSize, ref: canvasRef })] }));
|
|
@@ -350,4 +354,4 @@ const useRenderer = (api, tfLite, call, engine) => {
|
|
|
350
354
|
};
|
|
351
355
|
|
|
352
356
|
export { BackgroundFiltersProvider };
|
|
353
|
-
//# sourceMappingURL=embedded-BackgroundFilters-
|
|
357
|
+
//# sourceMappingURL=embedded-BackgroundFilters-g6ozIvlN.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-BackgroundFilters-g6ozIvlN.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 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 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 segmentationOptions,\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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"}
|
package/dist/embedded.cjs.js
CHANGED
|
@@ -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-
|
|
689
|
+
const BackgroundFiltersProviderImpl = react.lazy(() => Promise.resolve().then(function () { return require('./embedded-BackgroundFilters-DdQqSx4T.cjs.js'); }).then((m) => ({
|
|
690
690
|
default: m.BackgroundFiltersProvider,
|
|
691
691
|
})));
|
|
692
692
|
/**
|
|
@@ -864,23 +864,53 @@ const WithTooltip = ({ title, tooltipClassName, tooltipPlacement, tooltipDisable
|
|
|
864
864
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Tooltip, { referenceElement: tooltipAnchor, visible: tooltipActuallyVisible, tooltipClassName: tooltipClassName, tooltipPlacement: tooltipPlacement, children: title || '' }), jsxRuntime.jsx("div", { ref: setTooltipAnchor, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, ...props })] }));
|
|
865
865
|
};
|
|
866
866
|
|
|
867
|
-
|
|
867
|
+
/**
|
|
868
|
+
* Wraps an event handler, silencing and logging exceptions (excluding the NotAllowedError
|
|
869
|
+
* DOMException, which is a normal situation handled by the SDK)
|
|
870
|
+
*
|
|
871
|
+
* @param props component props, including the onError callback
|
|
872
|
+
* @param handler event handler to wrap
|
|
873
|
+
*/
|
|
874
|
+
const createCallControlHandler = (props, handler) => {
|
|
875
|
+
return async () => {
|
|
876
|
+
try {
|
|
877
|
+
await handler();
|
|
878
|
+
}
|
|
879
|
+
catch (error) {
|
|
880
|
+
if (props.onError) {
|
|
881
|
+
props.onError(error);
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
if (!isNotAllowedError(error)) {
|
|
885
|
+
console.error('Call control handler failed', error);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
};
|
|
890
|
+
function isNotAllowedError(error) {
|
|
891
|
+
return error instanceof DOMException && error.name === 'NotAllowedError';
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
const RecordEndConfirmation = (props) => {
|
|
868
895
|
const { t } = videoReactBindings.useI18n();
|
|
869
896
|
const { toggleCallRecording, isAwaitingResponse } = videoReactBindings.useToggleCallRecording();
|
|
870
897
|
const { close } = useMenuContext();
|
|
871
|
-
|
|
898
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
899
|
+
return (jsxRuntime.jsxs("div", { className: "str-video__end-recording__confirmation", children: [jsxRuntime.jsxs("div", { className: "str-video__end-recording__header", children: [jsxRuntime.jsx(Icon, { icon: "recording-on" }), jsxRuntime.jsx("h2", { className: "str-video__end-recording__heading", children: t('End recording') })] }), jsxRuntime.jsx("p", { className: "str-video__end-recording__description", children: t('Are you sure you want end the recording?') }), jsxRuntime.jsxs("div", { className: "str-video__end-recording__actions", children: [jsxRuntime.jsx(CompositeButton, { variant: "secondary", onClick: close, children: t('Cancel') }), jsxRuntime.jsx(CompositeButton, { variant: "primary", onClick: isAwaitingResponse ? undefined : handleClick, children: isAwaitingResponse ? jsxRuntime.jsx(LoadingIndicator, {}) : t('End recording') })] })] }));
|
|
872
900
|
};
|
|
873
901
|
const ToggleEndRecordingMenuButton = react.forwardRef(function ToggleEndRecordingMenuButton(props, ref) {
|
|
874
902
|
return (jsxRuntime.jsx(CompositeButton, { ref: ref, active: true, variant: "secondary", "data-testid": "recording-stop-button", children: jsxRuntime.jsx(Icon, { icon: "recording-off" }) }));
|
|
875
903
|
});
|
|
876
|
-
const RecordCallConfirmationButton = (
|
|
904
|
+
const RecordCallConfirmationButton = (props) => {
|
|
905
|
+
const { caption } = props;
|
|
877
906
|
const { t } = videoReactBindings.useI18n();
|
|
878
907
|
const { toggleCallRecording, isAwaitingResponse, isCallRecordingInProgress } = videoReactBindings.useToggleCallRecording();
|
|
908
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
879
909
|
if (isCallRecordingInProgress) {
|
|
880
910
|
return (jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [
|
|
881
911
|
videoClient.OwnCapability.START_RECORD_CALL,
|
|
882
912
|
videoClient.OwnCapability.STOP_RECORD_CALL,
|
|
883
|
-
], children: jsxRuntime.jsx(MenuToggle, { ToggleButton: ToggleEndRecordingMenuButton, visualType: MenuVisualType.PORTAL, children: jsxRuntime.jsx(RecordEndConfirmation, {}) }) }));
|
|
913
|
+
], children: jsxRuntime.jsx(MenuToggle, { ToggleButton: ToggleEndRecordingMenuButton, visualType: MenuVisualType.PORTAL, children: jsxRuntime.jsx(RecordEndConfirmation, { onError: props.onError }) }) }));
|
|
884
914
|
}
|
|
885
915
|
const title = isAwaitingResponse
|
|
886
916
|
? t('Waiting for recording to start...')
|
|
@@ -888,7 +918,7 @@ const RecordCallConfirmationButton = ({ caption, }) => {
|
|
|
888
918
|
return (jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [
|
|
889
919
|
videoClient.OwnCapability.START_RECORD_CALL,
|
|
890
920
|
videoClient.OwnCapability.STOP_RECORD_CALL,
|
|
891
|
-
], children: jsxRuntime.jsx(WithTooltip, { title: title, children: jsxRuntime.jsx(CompositeButton, { active: isCallRecordingInProgress, caption: caption, variant: "secondary", "data-testid": "recording-start-button", onClick: isAwaitingResponse ? undefined :
|
|
921
|
+
], children: jsxRuntime.jsx(WithTooltip, { title: title, children: jsxRuntime.jsx(CompositeButton, { active: isCallRecordingInProgress, caption: caption, variant: "secondary", "data-testid": "recording-start-button", onClick: isAwaitingResponse ? undefined : handleClick, children: isAwaitingResponse ? (jsxRuntime.jsx(LoadingIndicator, {})) : (jsxRuntime.jsx(Icon, { icon: "recording-off" })) }) }) }));
|
|
892
922
|
};
|
|
893
923
|
|
|
894
924
|
const defaultEmojiReactionMap = {
|
|
@@ -963,33 +993,6 @@ const DefaultReactionsMenu = ({ reactions, layout = 'horizontal', }) => {
|
|
|
963
993
|
}, children: reaction.emoji_code && defaultEmojiReactionMap[reaction.emoji_code] }, reaction.emoji_code))) }));
|
|
964
994
|
};
|
|
965
995
|
|
|
966
|
-
/**
|
|
967
|
-
* Wraps an event handler, silencing and logging exceptions (excluding the NotAllowedError
|
|
968
|
-
* DOMException, which is a normal situation handled by the SDK)
|
|
969
|
-
*
|
|
970
|
-
* @param props component props, including the onError callback
|
|
971
|
-
* @param handler event handler to wrap
|
|
972
|
-
*/
|
|
973
|
-
const createCallControlHandler = (props, handler) => {
|
|
974
|
-
return async () => {
|
|
975
|
-
try {
|
|
976
|
-
await handler();
|
|
977
|
-
}
|
|
978
|
-
catch (error) {
|
|
979
|
-
if (props.onError) {
|
|
980
|
-
props.onError(error);
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
if (!isNotAllowedError(error)) {
|
|
984
|
-
console.error('Call control handler failed', error);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
};
|
|
989
|
-
function isNotAllowedError(error) {
|
|
990
|
-
return error instanceof DOMException && error.name === 'NotAllowedError';
|
|
991
|
-
}
|
|
992
|
-
|
|
993
996
|
const ScreenShareButton = (props) => {
|
|
994
997
|
const { t } = videoReactBindings.useI18n();
|
|
995
998
|
const { caption, optimisticUpdates } = props;
|
|
@@ -1153,7 +1156,7 @@ const SpeakerTest = (props) => {
|
|
|
1153
1156
|
const audioElementRef = react.useRef(null);
|
|
1154
1157
|
const [isPlaying, setIsPlaying] = react.useState(false);
|
|
1155
1158
|
const { t } = videoReactBindings.useI18n();
|
|
1156
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1159
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.34.1"}/assets/piano.mp3`, } = props;
|
|
1157
1160
|
// Update audio output device when selection changes
|
|
1158
1161
|
react.useEffect(() => {
|
|
1159
1162
|
const audio = audioElementRef.current;
|
|
@@ -1794,7 +1797,9 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
|
|
|
1794
1797
|
const hasVideoTrack = videoClient.hasVideo(participant);
|
|
1795
1798
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
1796
1799
|
const isTrackPaused = trackType !== 'none' ? videoClient.hasPausedTrack(participant, trackType) : false;
|
|
1797
|
-
|
|
1800
|
+
const isAudioTrackUnmuted = useIsTrackUnmuted(participant);
|
|
1801
|
+
const isAudioConnecting = hasAudioTrack && !isAudioTrackUnmuted;
|
|
1802
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "str-video__participant-details", children: jsxRuntime.jsxs("div", { className: "str-video__participant-details__name", children: [name || userId, indicatorsVisible && isAudioConnecting && (jsxRuntime.jsx(LoadingIndicator, { className: "str-video__participant-details__name--audio-connecting", tooltip: t('Audio is connecting...') })), indicatorsVisible && !hasAudioTrack && (jsxRuntime.jsx("span", { className: "str-video__participant-details__name--audio-muted" })), indicatorsVisible && !hasVideoTrack && (jsxRuntime.jsx("span", { className: "str-video__participant-details__name--video-muted" })), indicatorsVisible && isTrackPaused && (jsxRuntime.jsx("span", { title: t('Video paused due to insufficient bandwidth'), className: "str-video__participant-details__name--track-paused" })), indicatorsVisible && canUnpin && (
|
|
1798
1803
|
// TODO: remove this monstrosity once we have a proper design
|
|
1799
1804
|
jsxRuntime.jsx("span", { title: t('Unpin'), onClick: () => call?.unpin(sessionId), className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsxRuntime.jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsxRuntime.jsx(Notification, { isVisible: isLocalParticipant &&
|
|
1800
1805
|
connectionQuality === videoClient.SfuModels.ConnectionQuality.POOR, message: t('Poor connection quality'), children: connectionQualityAsString && (jsxRuntime.jsx("span", { className: clsx('str-video__participant-details__connection-quality', `str-video__participant-details__connection-quality--${connectionQualityAsString}`), title: connectionQualityAsString })) }))] }));
|
|
@@ -1804,6 +1809,29 @@ const SpeechIndicator = () => {
|
|
|
1804
1809
|
const { isSpeaking, isDominantSpeaker } = participant;
|
|
1805
1810
|
return (jsxRuntime.jsxs("span", { className: clsx('str-video__speech-indicator', isSpeaking && 'str-video__speech-indicator--speaking', isDominantSpeaker && 'str-video__speech-indicator--dominant'), children: [jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" }), jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" }), jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" })] }));
|
|
1806
1811
|
};
|
|
1812
|
+
const useIsTrackUnmuted = (participant) => {
|
|
1813
|
+
const audioStream = participant.audioStream;
|
|
1814
|
+
const [unmuted, setUnmuted] = react.useState(() => {
|
|
1815
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1816
|
+
return !!track && !track.muted;
|
|
1817
|
+
});
|
|
1818
|
+
react.useEffect(() => {
|
|
1819
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1820
|
+
if (!track)
|
|
1821
|
+
return;
|
|
1822
|
+
setUnmuted(!track.muted);
|
|
1823
|
+
const handler = () => {
|
|
1824
|
+
setUnmuted(!track.muted);
|
|
1825
|
+
};
|
|
1826
|
+
track.addEventListener('mute', handler);
|
|
1827
|
+
track.addEventListener('unmute', handler);
|
|
1828
|
+
return () => {
|
|
1829
|
+
track.removeEventListener('mute', handler);
|
|
1830
|
+
track.removeEventListener('unmute', handler);
|
|
1831
|
+
};
|
|
1832
|
+
}, [audioStream]);
|
|
1833
|
+
return unmuted;
|
|
1834
|
+
};
|
|
1807
1835
|
|
|
1808
1836
|
const ParticipantView = react.forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
1809
1837
|
const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
|
|
@@ -1974,6 +2002,7 @@ var en = {
|
|
|
1974
2002
|
"Dominant Speaker": "Dominant Speaker",
|
|
1975
2003
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
1976
2004
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
2005
|
+
"Audio is connecting...": "Audio is connecting...",
|
|
1977
2006
|
Participants: Participants,
|
|
1978
2007
|
Anonymous: Anonymous,
|
|
1979
2008
|
"No participants found": "No participants found",
|