diff --git a/src/lotus/lotusAudioInject.ts b/src/lotus/lotusAudioInject.ts index 998392e0..d5fe59ed 100644 --- a/src/lotus/lotusAudioInject.ts +++ b/src/lotus/lotusAudioInject.ts @@ -101,6 +101,13 @@ async function playInjectedClip( return; } + // Max ONE clip at a time (replace mode): stop any in-flight clip before + // starting a new one, so clips can't overlap or be spammed. Runs + // synchronously before the first await, and each cleanup() is idempotent and + // removes itself from activeClips (so no track leak). The host also debounces + // the button; together they cover the brief fetch window. + for (const abort of [...activeClips]) abort(); + const resp = await fetch(url, { credentials: "omit", mode: "cors" }); if (!resp.ok) throw new Error(`fetch ${url} -> ${resp.status}`); const arrayBuffer = await resp.arrayBuffer();