Files
Aime/docs/02-audio-topologie.md
T
Claude db3d946592 docs: komplette CallRec-Dokumentation mit Mermaid-Diagrammen
Architektur, Hardware/Thermik, PipeWire-Audio-Topologie, Aufnahme-Pipeline,
Diarization (Anchor-Merge), LLM-Analyse (Gemma-3-4B/NPU), iPhone-BT-HFP,
Betrieb/Troubleshooting und Changelog-Chronik.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:51:22 +02:00

4.2 KiB
Raw Blame History

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["CallRec-App<br/>Aufnahme"]

    PCIN -- "cr_pc2hs (100%)" --> HS
    PCIN -- "cr_pc2mix (60% ≈ −13 dB)" --> MIX
    MIC -- "cr_mic2mix (100%)" --> MIX
    MIC -- "cr_mic2pc (100%)" --> GATE --> GADGET
    MIX -.->|"monitor"| CRMIX --> APP

Vier Loopbacks, jeder per media.name-Tag identifizierbar (robust gegen Index-Verschiebung), Gains setzt si_vol() im Setup-Skript /opt/callrec/aime-usb-audio-setup.sh:

Loopback 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_mic2mix Mikro → callmix 100 % Eigene Stimme in die Aufnahme
cr_mic2pc Mikro → micgate → Gadget 100 % Gegenseite hört den Nutzer

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-in filter-chain.conf.d/micgate.conf + eigener Dienst aime-micgate.service.
  • PipeWire liefert einen eigenen preset-aktivierten filter-chain.service mit → doppeltes micgate → systemctl --user mask filter-chain.service.
  • Mikro-HW-Gain nur über pactl set-source-volume $HSMIC 62% setzen (= HW-Stufe 12). amixer direkt 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) → setsid nutzen.

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 mit parecord + ffmpeg astats auf Signal prüfen.
  • Die GUI filtert alle *.monitor-Quellen aus → deshalb der Remap auf callrec_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.