From 445e010cd3c54d6b522f75860a1060209decb060 Mon Sep 17 00:00:00 2001 From: fkwp Date: Thu, 8 Oct 2026 09:03:42 +0200 Subject: [PATCH] Tidy the background effect pipeline after review - The Vite transform wrapper takes Vite's own types, with no cast. - The pipeline's options are compared with deepCompare, not as JSON. - Renames `attached` to `enable` and shortens the pipeline's doc comment. - Drops a comment that blamed an ended track on the pipeline's queue. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/state/BackgroundEffects.ts | 13 +++++-------- src/tracks/TrackProcessorContext.tsx | 2 -- vite.config.ts | 17 ++++++----------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/state/BackgroundEffects.ts b/src/state/BackgroundEffects.ts index e89939805..353c4aac3 100644 --- a/src/state/BackgroundEffects.ts +++ b/src/state/BackgroundEffects.ts @@ -11,6 +11,7 @@ import { type SwitchBackgroundProcessorOptions, } from "@livekit/track-processors"; import { logger } from "matrix-js-sdk/lib/logger"; +import { deepCompare } from "matrix-js-sdk/lib/utils"; import { type Behavior } from "./Behavior"; import { type ObservableScope } from "./ObservableScope"; @@ -26,11 +27,7 @@ export interface BackgroundEffectsOptions { supported: boolean; /** Whether blur is chosen. */ blur$: Behavior; - /** - * Shared by the pre-join preview and the call. Building or destroying it is - * what primes it, and a primed pipeline lets its next frame through - * untouched, so it is switched rather than rebuilt. - */ + /** The background processor pipeline to be switched between effects. */ pipeline: BackgroundProcessorWrapper; } @@ -50,9 +47,9 @@ export class BackgroundEffects { (previous, wanted) => { // Attached the first time an effect is wanted and never detached // after, so someone who never turns one on pays for none of it. - const attached = + const enable = previous.processor !== undefined || (supported && wanted); - return { supported, processor: attached ? processor : undefined }; + return { supported, processor: enable ? processor : undefined }; }, { supported, processor: undefined }, ), @@ -66,7 +63,7 @@ export class BackgroundEffects { map(([, blur]): SwitchBackgroundProcessorOptions => blur ? { mode: "background-blur", blurRadius } : { mode: "disabled" }, ), - distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), + distinctUntilChanged(deepCompare), scope.bind(), ) .subscribe((options) => { diff --git a/src/tracks/TrackProcessorContext.tsx b/src/tracks/TrackProcessorContext.tsx index 3bb1e6f9a..e0059b41c 100644 --- a/src/tracks/TrackProcessorContext.tsx +++ b/src/tracks/TrackProcessorContext.tsx @@ -107,8 +107,6 @@ export function applyProcessor( } const track = videoTrack.mediaStreamTrack; videoTrack.setProcessor(convertToLivekitProcessor(processor)).catch((e) => { - // The pipeline builds one track at a time, so a track can end while its - // build waits a turn. The camera's next track attaches it again. if (track.readyState === "ended") logger.debug("Video processor not attached: the track ended first"); else logger.warn("Failed to attach video processor", e); diff --git a/vite.config.ts b/vite.config.ts index 1e50704dd..3e9f6aef1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details. import { loadEnv, + type Plugin, type PluginOption, searchForWorkspaceRoot, type ConfigEnv, @@ -211,19 +212,13 @@ function exceptMediaPipeWasm(plugins: PluginOption): PluginOption { ) return plugin; const transform = plugin.transform; - return { + const wrapped: Plugin = { ...plugin, - transform(this: unknown, code: string, id: string, options: unknown) { + transform(code, id, options) { if (isLoader(id)) return null; - return ( - transform as ( - this: unknown, - c: string, - i: string, - o: unknown, - ) => unknown - ).call(this, code, id, options); + return transform.call(this, code, id, options); }, - } as PluginOption; + }; + return wrapped; }); }