Denoise init blocks LiveKit's track-change lock, freezing mute/unmute for seconds #7

Closed
opened 2026-09-12 02:12:59 -04:00 by jared · 0 comments
Owner

Severity: medium · Type: ux · Confidence: high

Location: src/lotus/lotusDenoise.ts:100-107, src/lotus/lotusDenoiseProcessor.ts:160-172, 210-251

Problem

LocalAudioTrack.setProcessor acquires trackChangeLock before awaiting processor.init() (livekit-client.esm.mjs:19820-19840). Our init() does a wasm/ESM fetch, audioWorklet.addModule(), for DeepFilterNet a full core.initialize() model load, plus a resumeCtx() that can burn up to 3 s (resumeCtx default timeoutMs = 3_000). All of that holds the lock, and every mute(), unmute(), restartTrack() and device switch queues behind it. On a cold cache with DFN this is easily several seconds during which pressing mute does nothing.

How to trigger

Join a call with lotusDenoiseSource=1&lotusModel=deepfilternet on a cold cache and immediately hit mute.

Suggested fix

Warm the context/worklet/model before calling setProcessor (prefetch wasm and addModule at module start, keyed by model), so init() only wires up already-loaded pieces; and drop the resume timeout to a few hundred ms since the statechange watcher heals it anyway.


Filed from the September 2026 audit (branch lotus).

**Severity:** medium · **Type:** ux · **Confidence:** high **Location:** `src/lotus/lotusDenoise.ts:100-107`, `src/lotus/lotusDenoiseProcessor.ts:160-172`, `210-251` ### Problem `LocalAudioTrack.setProcessor` acquires `trackChangeLock` *before* awaiting `processor.init()` (`livekit-client.esm.mjs:19820-19840`). Our `init()` does a wasm/ESM fetch, `audioWorklet.addModule()`, for DeepFilterNet a full `core.initialize()` model load, plus a `resumeCtx()` that can burn up to 3 s (`resumeCtx` default `timeoutMs = 3_000`). All of that holds the lock, and every `mute()`, `unmute()`, `restartTrack()` and device switch queues behind it. On a cold cache with DFN this is easily several seconds during which pressing mute does nothing. ### How to trigger Join a call with `lotusDenoiseSource=1&lotusModel=deepfilternet` on a cold cache and immediately hit mute. ### Suggested fix Warm the context/worklet/model *before* calling `setProcessor` (prefetch wasm and `addModule` at module start, keyed by model), so `init()` only wires up already-loaded pieces; and drop the resume timeout to a few hundred ms since the `statechange` watcher heals it anyway. --- _Filed from the September 2026 audit (branch `lotus`)._
jared added this to the EC fork audit 2026-09 · Medium & Low milestone 2026-09-12 02:12:59 -04:00
jared added the priority: mediumuxarea: denoise labels 2026-09-12 02:12:59 -04:00
jared self-assigned this 2026-09-12 02:12:59 -04:00
jared closed this issue 2026-09-13 01:22:43 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
2026-11-14
Dependencies

No dependencies set.

Reference: LotusGuild/element-call#7