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>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user