feat(audio): attach the AI filter per-track after publication (way B, #0054)
Instead of webAudioMix on the room - which would also rewire playback (sink selection through the AudioContext, LiveKit's Chrome echo workaround) - only the local microphone track gets an AudioContext, via setAudioContext() right before setProcessor(). The attach happens in onLocalTrackPublished, so a failing filter can no longer prevent unmuting: the track is already published by then. audioCaptureDefaults now never carry a processor key in any state; the conditional spread only toggles noiseSuppression. A regression test covers the active case too. The gate stays closed. A single test client opts in via two localStorage keys (ai-noise-suppression-dev plus the regular setting); the regular setting alone stays inert. Four unit tests pin the attach order - setAudioContext before setProcessor is exactly what v0.5.0 lacked - and the containment of a failing attach. 77 tests green across the touched suites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
dcc86431dc
commit
df4e5eeb85
+24
-1
@@ -146,11 +146,34 @@ Daraus zwei **stehende Regeln** fuer diesen Fork:
|
||||
(`ConnectionFactory.ts`), abgesichert durch Regressionstests in
|
||||
`ECConnectionFactory.test.ts` (die auf dem alten Stand nachweislich rot waren).
|
||||
2. **Feature-Tor:** `AI_NOISE_SUPPRESSION_AVAILABLE` in `src/livekit/aiNoiseSuppression.ts`
|
||||
steht auf `false`, bis `webAudioMix` entschieden und im Call zu zweit getestet ist.
|
||||
steht auf `false`, bis die Track-Anbindung im Call zu zweit abgenommen ist.
|
||||
Das Tor neutralisiert auch Clients, die die Einstellung bereits aktiviert hatten
|
||||
(localStorage) - deren Zustand ueberlebt jedes Deployment. Die Bedienelemente in
|
||||
`SettingsModal.tsx` sind hinter demselben Tor versteckt.
|
||||
|
||||
### Weg B (Entscheidung sorb 2026-08-16): AudioContext nur auf dem Mikrofon-Track
|
||||
|
||||
Statt `webAudioMix` am Raum (wuerde auch die Wiedergabe umbauen: Ausgabegeraete-Wahl
|
||||
ueber den AudioContext statt `setSinkId`, eigener Chrome-Echo-Workaround in LiveKit)
|
||||
bekommt **nur der lokale Mikrofon-Track** einen AudioContext - via
|
||||
`LocalAudioTrack.setAudioContext()`, unmittelbar vor `setProcessor()`. Umgesetzt in
|
||||
`applyAiNoiseSuppression()` (`aiNoiseSuppression.ts`), aufgerufen aus
|
||||
`Publisher.onLocalTrackPublished` - also erst **nach** der Publikation: ein
|
||||
scheiternder Filter kann das Entmuten dann nicht mehr verhindern, der Fehlerfall ist
|
||||
per Konstruktion auf den Filter selbst begrenzt.
|
||||
|
||||
Die `audioCaptureDefaults` tragen damit in **keinem** Zustand mehr einen
|
||||
`processor`-Schluessel (Regressionstest deckt auch den Aktiv-Fall ab); dort wird nur
|
||||
noch `noiseSuppression` umgeschaltet, damit Browser- und KI-Filter nicht
|
||||
gegeneinander arbeiten.
|
||||
|
||||
**Testausrollung:** Das Tor bleibt zu. Ein einzelner Test-Client aktiviert den Filter
|
||||
ueber ZWEI localStorage-Schluessel: `matrix-setting-ai-noise-suppression-dev = true`
|
||||
(Entwickler-Schalter, bewusst ohne UI) **und** `matrix-setting-ai-noise-suppression =
|
||||
true`. Die normale Einstellung allein bleibt wirkungslos. Erst nach bestandener
|
||||
Abnahme im Call zu zweit wird das Tor geoeffnet und die UI wieder sichtbar.
|
||||
Einstellungs-Aenderungen wirken ab dem naechsten Beitritt, nicht live im Call.
|
||||
|
||||
## 6. Produktname im Widget (`.env.production`)
|
||||
|
||||
`VITE_PRODUCT_NAME=aXion1337.Chat` in `.env.production` — eine Zeile, keine
|
||||
|
||||
Reference in New Issue
Block a user