From 35cb114160891e667c8f22b67377858b7c6cd4e9 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 2 Sep 2026 20:48:16 +0200 Subject: [PATCH] wip try to enhance error handling --- .../effects/EffectsConfiguration.tsx | 29 +++++++++++++--- .../rooms/livekit/hooks/useJoinTracks.ts | 34 ++++++++++++++----- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx b/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx index 2b01119d..46aee140 100644 --- a/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx +++ b/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx @@ -201,10 +201,23 @@ export const EffectsConfiguration = ({ * * We arrive in this condition when we enter the room with the camera already off. */ - const newProcessorTmp = BackgroundProcessorFactory.getProcessor(config)! - await toggle(true, { - processor: newProcessorTmp, - }) + try { + const newProcessorTmp = + BackgroundProcessorFactory.getProcessor(config)! + await toggle(true, { + processor: newProcessorTmp, + }) + } catch (error) { + reportError('effects_processor_failure', error, { + context: 'Error applying effect while enabling camera:', + }) + saveProcessorConfig(undefined) + try { + await toggle(true) + } catch { + // Camera errors are handled by the toggle's own error path. + } + } setTimeout(() => setProcessorPending(false)) return } @@ -246,6 +259,14 @@ export const EffectsConfiguration = ({ reportError('effects_processor_failure', error, { context: 'Error applying effect:', }) + try { + if (videoTrack.getProcessor()) { + await videoTrack.stopProcessor() + } + } catch { + // Best effort: the processor may already be broken. + } + saveProcessorConfig(undefined) } finally { // Without setTimeout the DOM is not refreshing when updating the options. setTimeout(() => setProcessorPending(false)) diff --git a/src/frontend/src/features/rooms/livekit/hooks/useJoinTracks.ts b/src/frontend/src/features/rooms/livekit/hooks/useJoinTracks.ts index f536bf78..6599351c 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useJoinTracks.ts +++ b/src/frontend/src/features/rooms/livekit/hooks/useJoinTracks.ts @@ -22,10 +22,12 @@ import { VOICE_AUDIO_CONSTRAINTS } from '../utils/constants' import { saveAudioInputDeviceId, saveAudioInputEnabled, + saveProcessorConfig, saveVideoInputDeviceId, saveVideoInputEnabled, userChoicesStore, } from '@/stores/userChoices' +import { reportError } from '@/features/analytics/telemetry' import { useSyncTrackDeviceId } from './useSyncTrackDeviceId' // Module-level: effect dependencies, must be referentially stable. @@ -221,15 +223,31 @@ export function useJoinTracks(): { [audioDeviceId] ) - const createVideo = useCallback( - () => - createLocalVideoTrack({ + const createVideo = useCallback(async () => { + const processor = + BackgroundProcessorFactory.fromProcessorConfig(processorConfig) + if (!processor) { + return createLocalVideoTrack({ deviceId: videoDeviceId }) + } + try { + return await createLocalVideoTrack({ deviceId: videoDeviceId, - processor: - BackgroundProcessorFactory.fromProcessorConfig(processorConfig), - }), - [videoDeviceId, processorConfig] - ) + processor, + }) + } catch (error) { + // A camera problem (permission, device missing/busy) is not the + // effect's fault: let the normal media error handling deal with it + // without touching the user's saved effect. + if (getMediaDeviceFailure(error as Error)) { + throw error + } + reportError('effects_processor_failure', error, { + context: 'Restoring saved effect failed, retrying without it', + }) + saveProcessorConfig(undefined) + return createLocalVideoTrack({ deviceId: videoDeviceId }) + } + }, [videoDeviceId, processorConfig]) const audioTrack = useLocalTrack({ ready: audioReady,