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,89 @@
|
||||
# 03 — Aufnahme-Pipeline
|
||||
|
||||
Vom Klick auf „Stop“ bis zur fertigen Analyse. Crash-sicher: Audio + DB-Zeile werden **vor** der langen
|
||||
Verarbeitung persistiert; Transkription/Analyse laufen asynchron im Hintergrund (GUI pollt).
|
||||
|
||||
## Ablauf
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant GUI as Web-GUI
|
||||
participant SRV as server.js
|
||||
participant REC as recorder.js
|
||||
participant WH as Whisper (NPU-Encoder)
|
||||
participant DI as diar.js (sherpa, CPU)
|
||||
participant LLM as llm.js (Gemma, NPU)
|
||||
participant DB as MariaDB
|
||||
|
||||
GUI->>SRV: Stop
|
||||
SRV->>REC: stopAndSave()
|
||||
REC->>DB: WAV + MP3 + Zeile (status=transcribing)
|
||||
Note over REC: kehrt nach ~1,5 s zurück — GUI frei
|
||||
REC->>REC: A76-Takt kappen (1,6 GHz)
|
||||
REC->>WH: transcribeWav() [BatchedInferencePipeline, batch=8]
|
||||
WH-->>REC: Wörter + Zeitstempel
|
||||
REC->>DI: diarize() [Timeout = Dauer × 2,5, min. 20 min]
|
||||
DI-->>REC: Sprecher-Segmente
|
||||
REC->>DB: setTranscript (status=done)
|
||||
REC->>REC: finally: Takt zurück
|
||||
SRV->>LLM: analyzeRecording() (fire-and-forget, analysis_status=pending)
|
||||
LLM->>DB: Titel/Summary/Teilnehmer/Todos (analysis_status=done, analysis_ms)
|
||||
GUI->>SRV: Polling analysis_status
|
||||
```
|
||||
|
||||
## Pfadwahl Transkription
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["WAV fertig"] --> B{"Dauer ≤ 30 s?<br/>(SHORT_SEC)"}
|
||||
B -- ja --> C["Warm-Daemon transcribe_daemon_cpu.py<br/>CPU-only, koexistiert mit residentem rkllm<br/>kein Modell-Swap → 10-s-Clip in ~53 s statt 120 s"]
|
||||
B -- nein --> D["transcribe_cli: faster-whisper large-v3-turbo<br/>Encoder auf NPU, Decoder CPU, batch=8<br/>RTF ≈ 0,39"]
|
||||
C --> E["Diarization"]
|
||||
D --> E
|
||||
```
|
||||
|
||||
- `TRANSCRIBER=npu` (Default) / `=cpu` als Fallback-Schalter in recorder.js.
|
||||
- Whisper-Kalibrierung: medium beam1 hatte 11,3 % WER vs. large-v3 — beam5 schlechter, `--initial-prompt`
|
||||
mit Begriffsliste **zerstört** den Output (Echo-Loop). Eigennamen-Korrektur passiert deshalb im Text-Layer (Glossar, Kap. 05).
|
||||
|
||||
## Zustandsmodell einer Aufnahme
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> recording
|
||||
recording --> transcribing: stopAndSave() — WAV/MP3/Zeile SOFORT persistiert
|
||||
transcribing --> done_transcript: Transkript + Diarization gespeichert
|
||||
transcribing --> failed: Absturz/Fehler → GUI zeigt Retry
|
||||
failed --> transcribing: POST /retranscribe
|
||||
done_transcript --> analyzing: analysis_status=pending
|
||||
analyzing --> analyzed: analysis_status=done (analysis_ms gesetzt)
|
||||
analyzing --> analysis_error: GUI-Button "Erneut versuchen"
|
||||
analysis_error --> analyzing: POST /reanalyze bzw. /reanalyze-llm
|
||||
```
|
||||
|
||||
- Hängende `transcribing`-Zeile = Absturz mitten in der Diarization (Transkript wird erst NACH Diar gespeichert)
|
||||
→ kein Auto-Resume, GUI-Button „Neu transkribieren“.
|
||||
- **NPU-Lock:** alle schweren Jobs (transcribe / analyze / re-diarize) laufen seriell durch `withNpuLock` —
|
||||
zwei gleichzeitig fertig werdende Aufnahmen haben sich sonst gegenseitig zerlegt.
|
||||
- **GUI-Anzeige „⏱ Analysezeit“:** `analysis_started_at`/`analysis_ms` in der DB; beim Polling auf
|
||||
`analysis_status` achten, NICHT auf `status` (sonst wirkt die Summary „leer“).
|
||||
|
||||
## API-Endpunkte (Auszug)
|
||||
|
||||
| Endpunkt | Zweck |
|
||||
|---|---|
|
||||
| `POST /api/recordings/:id/retranscribe` | Hängende/fehlgeschlagene Transkription neu starten |
|
||||
| `POST /api/recordings/:id/reanalyze` `{numSpeakers?}` | Diarization **immer** neu (leer/0 = automatisch, Zahl = Anzahl gepinnt) + LLM neu |
|
||||
| `POST /api/recordings/:id/reanalyze-llm` | Nur LLM neu, Diarization/Wörter bleiben |
|
||||
| `POST /api/recordings/:id/speaker` `{speaker,name,enroll}` | Sprecher benennen + optional Stimme lernen |
|
||||
| `/api/glossary` (CRUD) | Eigennamen-Glossar |
|
||||
|
||||
## Performance-Kennzahlen (71-min-Referenz #69)
|
||||
|
||||
| Schritt | Wert |
|
||||
|---|---|
|
||||
| Transkription (NPU, batch=8) | RTF ≈ 0,39 |
|
||||
| Diarization (CPU) | RTF ≈ 0,19 |
|
||||
| Komplett E2E | RTF ≈ 0,9 |
|
||||
| LLM-Analyse (Gemma, 10 Chunks + Reduce) | ~20 min |
|
||||
| Kurzclip (10 s) komplett | ~53 s |
|
||||
Reference in New Issue
Block a user