From fac0c5312360129400b37b0f0574f1adf214add8 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Tue, 2 Sep 2025 14:06:29 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20refactor=20proce?= =?UTF-8?q?ssor=20wrapper=20to=20unified=20class=20architecture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace multiple processor wrappers with single unified class that enables seamless transformer switching and option updates without visual blinking artifacts. Leverages LiveKit track processor v0.6.0 updateTransformerOptions fix to provide smooth transitions between transformer types, eliminating the recreation-based approach that caused flickering during effects switching. --- .../BackgroundBlurTrackProcessorJsWrapper.ts | 68 -------------- .../blur/BackgroundCustomProcessor.ts | 2 +- ...ackgroundVirtualTrackProcessorJsWrapper.ts | 61 ------------- .../blur/UnifiedBackgroundTrackProcessor.ts | 91 +++++++++++++++++++ .../rooms/livekit/components/blur/index.ts | 9 +- .../effects/EffectsConfiguration.tsx | 13 ++- 6 files changed, 103 insertions(+), 141 deletions(-) delete mode 100644 src/frontend/src/features/rooms/livekit/components/blur/BackgroundBlurTrackProcessorJsWrapper.ts delete mode 100644 src/frontend/src/features/rooms/livekit/components/blur/BackgroundVirtualTrackProcessorJsWrapper.ts create mode 100644 src/frontend/src/features/rooms/livekit/components/blur/UnifiedBackgroundTrackProcessor.ts diff --git a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundBlurTrackProcessorJsWrapper.ts b/src/frontend/src/features/rooms/livekit/components/blur/BackgroundBlurTrackProcessorJsWrapper.ts deleted file mode 100644 index 603e793b..00000000 --- a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundBlurTrackProcessorJsWrapper.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { - BackgroundBlur, - BackgroundTransformer, - ProcessorWrapper, -} from '@livekit/track-processors' -import { ProcessorOptions, Track } from 'livekit-client' -import { - BackgroundProcessorInterface, - BackgroundOptions, - ProcessorType, -} from '.' - -/** - * This is simply a wrapper around track-processor-js Processor - * in order to be compatible with a common interface BackgroundBlurProcessorInterface - * used across the project. - */ -export class BackgroundBlurTrackProcessorJsWrapper - implements BackgroundProcessorInterface -{ - name: string = 'blur' - - processor: ProcessorWrapper - - opts: BackgroundOptions - - constructor(opts: BackgroundOptions) { - this.processor = BackgroundBlur(opts.blurRadius) - this.opts = opts - } - - async init(opts: ProcessorOptions) { - return this.processor.init(opts) - } - - async restart(opts: ProcessorOptions) { - return this.processor.restart(opts) - } - - async destroy() { - return this.processor.destroy() - } - - update(opts: BackgroundOptions): void { - this.processor.updateTransformerOptions(opts) - } - - get processedTrack() { - return this.processor.processedTrack - } - - get options() { - return (this.processor.transformer as BackgroundTransformer).options - } - - clone() { - return new BackgroundBlurTrackProcessorJsWrapper({ - blurRadius: this.options!.blurRadius, - }) - } - - serialize() { - return { - type: ProcessorType.BLUR, - options: this.options, - } - } -} diff --git a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundCustomProcessor.ts b/src/frontend/src/features/rooms/livekit/components/blur/BackgroundCustomProcessor.ts index 744a749f..fdc9fdb2 100644 --- a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundCustomProcessor.ts +++ b/src/frontend/src/features/rooms/livekit/components/blur/BackgroundCustomProcessor.ts @@ -118,7 +118,7 @@ export class BackgroundCustomProcessor implements BackgroundProcessorInterface { } } - update(opts: BackgroundOptions): void { + async update(opts: BackgroundOptions): Promise { this.options = opts this._initVirtualBackgroundImage() } diff --git a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundVirtualTrackProcessorJsWrapper.ts b/src/frontend/src/features/rooms/livekit/components/blur/BackgroundVirtualTrackProcessorJsWrapper.ts deleted file mode 100644 index 0a2525ad..00000000 --- a/src/frontend/src/features/rooms/livekit/components/blur/BackgroundVirtualTrackProcessorJsWrapper.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ProcessorOptions, Track } from 'livekit-client' -import { - BackgroundOptions, - BackgroundProcessorInterface, - ProcessorType, -} from '.' -import { - BackgroundTransformer, - ProcessorWrapper, - VirtualBackground, -} from '@livekit/track-processors' - -export class BackgroundVirtualTrackProcessorJsWrapper - implements BackgroundProcessorInterface -{ - name = 'virtual' - - processor: ProcessorWrapper - - opts: BackgroundOptions - - constructor(opts: BackgroundOptions) { - this.processor = VirtualBackground(opts.imagePath!) - this.opts = opts - } - - async init(opts: ProcessorOptions) { - return this.processor.init(opts) - } - - async restart(opts: ProcessorOptions) { - return this.processor.restart(opts) - } - - async destroy() { - return this.processor.destroy() - } - - update(opts: BackgroundOptions): void { - this.processor.updateTransformerOptions(opts) - } - - get processedTrack() { - return this.processor.processedTrack - } - - get options() { - return (this.processor.transformer as BackgroundTransformer).options - } - - clone() { - return new BackgroundVirtualTrackProcessorJsWrapper(this.options) - } - - serialize() { - return { - type: ProcessorType.VIRTUAL, - options: this.options, - } - } -} diff --git a/src/frontend/src/features/rooms/livekit/components/blur/UnifiedBackgroundTrackProcessor.ts b/src/frontend/src/features/rooms/livekit/components/blur/UnifiedBackgroundTrackProcessor.ts new file mode 100644 index 00000000..3c96b2de --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/blur/UnifiedBackgroundTrackProcessor.ts @@ -0,0 +1,91 @@ +import { ProcessorOptions, Track } from 'livekit-client' +import { + BackgroundBlur, + BackgroundTransformer, + ProcessorWrapper, + VirtualBackground, +} from '@livekit/track-processors' +import { + BackgroundOptions, + BackgroundProcessorInterface, + ProcessorType, +} from '.' + +export class UnifiedBackgroundTrackProcessor + implements BackgroundProcessorInterface +{ + processor: ProcessorWrapper + opts: BackgroundOptions + processorType: ProcessorType + + constructor(opts: BackgroundOptions) { + this.opts = opts + + if (opts.imagePath) { + this.processorType = ProcessorType.VIRTUAL + this.processor = VirtualBackground(opts.imagePath) + } else if (opts.blurRadius !== undefined) { + this.processorType = ProcessorType.BLUR + this.processor = BackgroundBlur(opts.blurRadius) + } else { + throw new Error( + 'Must provide either imagePath for virtual background or blurRadius for blur' + ) + } + } + + async init(opts: ProcessorOptions) { + return this.processor.init(opts) + } + + async restart(opts: ProcessorOptions) { + return this.processor.restart(opts) + } + + async destroy() { + return this.processor.destroy() + } + + async update(opts: BackgroundOptions): Promise { + const newProcessorType = opts.imagePath + ? ProcessorType.VIRTUAL + : ProcessorType.BLUR + + let processedOpts = opts + if (newProcessorType !== this.processorType) { + this.processorType = newProcessorType + if (newProcessorType === ProcessorType.VIRTUAL) { + this.processor.name = 'virtual-background' + processedOpts = { ...opts, blurRadius: undefined } + } else { + this.processor.name = 'background-blur' + processedOpts = { ...opts, imagePath: undefined } + } + } + await this.processor.updateTransformerOptions(processedOpts) + this.opts = processedOpts + } + + get name() { + return this.processor.name + } + + get processedTrack() { + return this.processor.processedTrack + } + + get options() { + return (this.processor.transformer as BackgroundTransformer).options + } + + clone() { + return new UnifiedBackgroundTrackProcessor(this.options || this.opts) + } + + serialize() { + return { + type: this.processorType, + options: this.options, + } + } +} diff --git a/src/frontend/src/features/rooms/livekit/components/blur/index.ts b/src/frontend/src/features/rooms/livekit/components/blur/index.ts index fa74ae44..13c85c8d 100644 --- a/src/frontend/src/features/rooms/livekit/components/blur/index.ts +++ b/src/frontend/src/features/rooms/livekit/components/blur/index.ts @@ -1,8 +1,7 @@ import { ProcessorWrapper } from '@livekit/track-processors' import { Track, TrackProcessor } from 'livekit-client' -import { BackgroundBlurTrackProcessorJsWrapper } from './BackgroundBlurTrackProcessorJsWrapper' import { BackgroundCustomProcessor } from './BackgroundCustomProcessor' -import { BackgroundVirtualTrackProcessorJsWrapper } from './BackgroundVirtualTrackProcessorJsWrapper' +import { UnifiedBackgroundTrackProcessor } from './UnifiedBackgroundTrackProcessor' export type BackgroundOptions = { blurRadius?: number @@ -16,7 +15,7 @@ export interface ProcessorSerialized { export interface BackgroundProcessorInterface extends TrackProcessor { - update(opts: BackgroundOptions): void + update(opts: BackgroundOptions): Promise options: BackgroundOptions clone(): BackgroundProcessorInterface serialize(): ProcessorSerialized @@ -47,9 +46,7 @@ export class BackgroundProcessorFactory { if (!isBlur && !isVirtual) return undefined if (ProcessorWrapper.isSupported) { - return isBlur - ? new BackgroundBlurTrackProcessorJsWrapper(opts) - : new BackgroundVirtualTrackProcessorJsWrapper(opts) + return new UnifiedBackgroundTrackProcessor(opts) } if (BackgroundCustomProcessor.isSupported) { 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 9542a056..ea408338 100644 --- a/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx +++ b/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx @@ -2,13 +2,13 @@ import { LocalVideoTrack, Track } from 'livekit-client' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { + BackgroundOptions, BackgroundProcessorFactory, BackgroundProcessorInterface, ProcessorType, - BackgroundOptions, } from '../blur' import { css } from '@/styled-system/css' -import { Text, P, ToggleButton, H } from '@/primitives' +import { H, P, Text, ToggleButton } from '@/primitives' import { styled } from '@/styled-system/jsx' import { BlurOn } from '@/components/icons/BlurOn' import { BlurOnStrong } from '@/components/icons/BlurOnStrong' @@ -105,7 +105,11 @@ export const EffectsConfiguration = ({ if (isSelected(type, options)) { // Stop processor. await clearEffect() - } else if (!processor || processor.serialize().type !== type) { + } else if ( + !processor || + (processor.serialize().type !== type && + !BackgroundProcessorFactory.hasModernApiSupport()) + ) { // Change processor. const newProcessor = BackgroundProcessorFactory.getProcessor( type, @@ -121,8 +125,7 @@ export const EffectsConfiguration = ({ await videoTrack.setProcessor(newProcessor) onSubmit?.(newProcessor) } else { - // Update processor. - processor?.update(options) + await processor?.update(options) // We want to trigger onSubmit when options changes so the parent component is aware of it. onSubmit?.(processor) }