Cepstral-Beweis auf #71: stabiler 80ms-Peak nur auf Gegenseiten-Segmenten = Muschel-Bleed durchs offene Mikro zusaetzlich zum digitalen Pfad. cr_mic2mix-Loopback entfernt, stattdessen pw-link micgate.out -> callmix (Fallback ohne Gate bleibt). Verschmierte Embeddings (verschmolzene Remote-Sprecher) sollten damit ebenfalls weg sein - echter Call offen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0113vDKdSNtD3Dwcw4QMu9yV
4.5 KiB
02 — Audio-Topologie (PipeWire)
Herzstück: virtueller Misch-Bus callmix (Null-Sink). Alles, was aufgenommen werden soll, wird per
Loopback dorthin geroutet; der Monitor von callmix wird als echte Quelle callrec_mix („CallRecMix“)
re-mappt — die wählt die Web-GUI als Aufnahmequelle.
Gesamtgraph
flowchart LR
PCIN["PC-Audio (Capture des UAC2-Gadgets)<br/>alsa_input.platform-fc000000.usb"]
MIC["Headset-Mikrofon H390<br/>alsa_input.usb-Logi...mono-fallback"]
HS["Headset-Hörer H390<br/>alsa_output.usb-Logi...analog-stereo"]
GADGET["Gadget-Sink (Board→PC)<br/>alsa_output.platform-fc000000.usb"]
GATE["micgate<br/>LADSPA Noise-Gate<br/>(swh gate_1410, Thr −45 dB)"]
MIX[("callmix<br/>Null-Sink")]
CRMIX["callrec_mix ('CallRecMix')<br/>remap von callmix.monitor"]
APP["Aime-App<br/>Aufnahme"]
PCIN -- "cr_pc2hs (100%)" --> HS
PCIN -- "cr_pc2mix (60% ≈ −13 dB)" --> MIX
MIC -- "cr_mic2pc (65%)" --> GATE
GATE --> GADGET
GATE -- "pw-link (gegatet, 2026-07-17)" --> MIX
MIX -.->|"monitor"| CRMIX --> APP
Drei Loopbacks (per media.name-Tag identifizierbar) + ein statischer pw-link; Gains setzt
si_vol() im Setup-Skript /opt/callrec/aime-usb-audio-setup.sh:
| Route | Weg | Gain | Zweck |
|---|---|---|---|
cr_pc2hs |
PC → Headset | 100 % | Nutzer hört PC/Teams |
cr_pc2mix |
PC → callmix | 60 % (≈ −13 dB) | Gegenseite in die Aufnahme (clip-sicher) |
cr_mic2pc |
Mikro → micgate → Gadget | 65 % | Gegenseite hört den Nutzer (gegatet) |
pw-link micgate.out → callmix |
GEGATETES Mikro → callmix | unity | Eigene Stimme in die Aufnahme |
cr_mic2mix |
— | ENTFERNT 2026-07-17 (nur noch Fallback ohne Gate): der offene Mikro-Pfad legte die Gegenseite ZWEIMAL in den Mix — digital + ~80 ms später als Muschel-Bleed (Cepstral-Peak 79–80 ms, #71) → Hall auf der Gegenseite + Diarization verschmolz zwei entfernte Sprecher |
Warum Noise-Gate (micgate)?
Teams-Gegenseite hörte sich selbst verzögert (Selbst-Echo). Nachgewiesen: akustisches Übersprechen ins Mikrofon (nicht elektrisch, nicht Ohrmuschel — Mute-Tests), und Teams-AGC renormalisiert jede Pegelabsenkung. Lösung: LADSPA-Gate im Mikro→PC-Pfad schließt in Sprechpausen → Gegenseite bekommt Stille → kein Echo. AEC wurde getestet und verworfen (Knistern, kein Nutzen).
flowchart LR
M["Mikrofon<br/>HW-Gain fest Stufe 12 (+1,4 dB)"] --> G{"Pegel > −45 dB?"}
G -- "ja (Sprache)" --> OPEN["Gate offen → Signal zum PC"]
G -- "nein (Pause)" --> CLOSED["Gate zu → Stille zum PC<br/>= kein Selbst-Echo"]
Gotchas (teuer bezahlt):
- Filter-Chain ist ein Core-Modul, kein Pulse-Modul → nicht per
pactl load-module, sondern Drop-infilter-chain.conf.d/micgate.conf+ eigener Dienstaime-micgate.service. - PipeWire liefert einen eigenen preset-aktivierten
filter-chain.servicemit → doppeltes micgate →systemctl --user mask filter-chain.service. - Mikro-HW-Gain nur über
pactl set-source-volume $HSMIC 62%setzen (= HW-Stufe 12).amixerdirekt wird von WirePlumber überschrieben; 100 % = +11 dB → Grundrauschen öffnet das Gate wieder. - 2-Mono-Node-Stereo-Graph im Filter-Chain = kein Audio → 1 Mono-Node verwenden.
pkill -f "pipewire -c filter-chain.conf"killt die eigene SSH-Session (exit 128) →setsidnutzen.
Merksätze
- PC-Audio = die Quelle
alsa_input.platform-fc000000.usb..., NICHT deren.monitor(der ist stumm — hat einmal eine Stunde gekostet). Quellen vor Verwendung mitparecord+ffmpeg astatsauf Signal prüfen. - Die GUI filtert alle
*.monitor-Quellen aus → deshalb der Remap aufcallrec_mix. - Gain-Staging ist clip-kritisch: Übersteuerung (0 dBFS) hat einmal die Diarization-Embeddings zerstört → 14 „Sprecher“ bei einem 2-Personen-Gespräch (Aufnahme #41, bleibt dauerhaft geclippt).
Persistenz
| Einheit | Aufgabe |
|---|---|
aime-usb-audio.service (user) |
baut die komplette Topologie beim Boot (aime-usb-audio-setup.sh); wartet auf micgate, Fallback direkt auf Gadget-Sink |
aime-micgate.service (user, enabled) |
startet die micgate-Filter-Chain |
aime-volume-headset.service (user) |
Windows-Volume-Bridge (UAC2 numid=7 → Headset-Sink) |
aime-headset-keys.service (root) |
H390-Inline-Tasten → Lautstärke |
alte aime-audio-out / aime-volume |
ES8323-Ära, disabled |
Kaltstart 2× verifiziert: Topologie, Gate, Volume-Bridge und WLAN kommen ohne Eingriff hoch.