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

80 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```mermaid
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).
```mermaid
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.