Ein Freitextfeld ("Kontext zum Gespraech") in der Detailansicht, nach dem
Stop aufgeklappt. Der Text geht als Hintergrundwissen in die LLM-Analyse:
Personen, Firmen, Anlass und Eigennamen muessen nicht mehr aus dem
fehlerbehafteten ASR-Text erraten werden.
Bewusst EIN Feld statt eines Formulars mit Teilnehmer-/Anlass-/Begriffs-
feldern (Entscheidung des Nutzers): die Box benutzen auch technisch nicht
versierte Menschen. Gefuehrt wird ueber den Platzhaltertext, die Struktur
zieht die Analyse selbst aus der Prosa.
- recordings.context_note/-_at, db.setContextNote/getContextNote
- PATCH /api/recordings/:id/context; Antwort `applies` sagt ehrlich, ob die
Notiz die laufende Verarbeitung noch erreicht (auto/running/reanalyze)
- analyzeRecording liest die Notiz erst kurz vor dem LLM-Aufruf, damit
waehrend der minutenlangen Vorstufen Getipptes noch zaehlt
- llm.contextBlock: eigener """-Block mit Verbot, daraus Aussagen, Ergebnisse
oder Aufgaben abzuleiten (sonst schreibt das 4B-Modell die Notiz als
Gesagtes zurueck); eingespeist in Single-, Whole- und Sektions-Pfad
- zwei Deckel: 1200 Zeichen fuer Prompts, die die Notiz einmal sehen,
600 fuer die Chunk-Prompts (dort landet sie in jedem Chunk von 3200)
- GUI-Karte zeichnet sich selbst neu (kein openRecording -> Audio laeuft
weiter), ungespeicherter Text ueberlebt den Neuaufbau nach der Analyse
Verifiziert an #97: Kontext greift (korrekte Namen, richtiges Thema), die
absichtlich eingelegten Fremdfakten der Testnotiz erscheinen nicht in der
Zusammenfassung. Alte Analyse danach zurueckgeschrieben.
Doku: Kapitel 05 (neuer Abschnitt + Flussdiagramm + Deckel-Tabelle),
Kapitel 03 (Sequenzdiagramm + API), Changelog 2026-08-17.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Aime — Dokumentation
Name: Das Projekt heißt Aime (wie der Bluetooth-Name des Boards; vormals „CallRec“). Technische Bezeichner auf dem Board bleiben aus Stabilitätsgründen unverändert:
callrec.service,/opt/callrec, DB/Usercallrec, PipeWire-Quelle „CallRecMix“.
Selbst gehostete Anruf-Aufnahme- und Analyse-Appliance auf einem Youyeetoo R1 (RK3588S) Einplatinenrechner. Nimmt Gespräche auf (PC/Teams über USB-Gadget und iPhone über Bluetooth-HFP), transkribiert mit Whisper (Encoder auf der NPU), trennt Sprecher akustisch (Diarization + Stimm-Profile) und erzeugt eine strukturierte KI-Zusammenfassung (Gemma-3-4B auf der NPU) — komplett offline, keine Cloud.
Inhaltsverzeichnis
| Dokument | Inhalt |
|---|---|
| 01 – Hardware | Board, Audio-Hardware, USB-Gadget, Thermik, NPU |
| 02 – Audio-Topologie | PipeWire-Graph: callmix, Loopbacks, Noise-Gate, Volume-Bridges |
| 03 – Aufnahme-Pipeline | Aufnahme → Transkription → Diarization → LLM → Datenbank |
| 04 – Sprechertrennung | Diarization, Anchor-Merge-Konsolidierung, Stimm-Profile |
| 05 – LLM-Analyse | Gemma-3-4B/NPU, Analyse-Pfade, strukturierte Zusammenfassung, Glossar |
| 06 – iPhone-Bluetooth | HFP-Pfad, Routing-Watcher, Echo-Fix |
| 07 – Betrieb | Services, Zugänge, Backups, Troubleshooting |
| 08 – Changelog | Chronik aller Entwicklungsschritte |
| 09 – Suche & Verwaltung | Inhaltssuche mit Zeitstempel-Verweis, Papierkorb, Titel umbenennen |
| 10 – Projektansicht | Projektordner, Unterreiter, angeheftete Aufnahmen |
System-Überblick
flowchart LR
subgraph Quellen
PC["Windows-PC<br/>(Teams, Medien)"]
IPHONE["iPhone<br/>(Telefonate)"]
USER(("Nutzer<br/>Logi H390 Headset"))
end
subgraph R1["Youyeetoo R1 (RK3588S, Armbian, lüfterlos)"]
PW["PipeWire<br/>Audio-Routing<br/>(callmix + micgate)"]
APP["Aime Web-App<br/>Node.js :3000"]
WH["Whisper large-v3-turbo<br/>Encoder auf NPU"]
DIAR["Diarization<br/>sherpa-onnx + TitaNet"]
LLM["Gemma-3-4B<br/>rkllm auf NPU"]
DB[("MariaDB<br/>callrec")]
end
PC -- "USB-C (UAC2-Gadget)" --> PW
IPHONE -- "Bluetooth HFP (AX210)" --> PW
USER -- "USB-A" --> PW
PW -- "callrec_mix" --> APP
APP --> WH --> DIAR --> LLM --> DB
APP --- DB
Quick Facts
- Board:
192.168.1.200(WLAN, primär) /192.168.1.50(LAN), Loginroot - Web-GUI:
http://192.168.1.200:3000— Aufnahme, Transkript, Sprecher-Editor, Glossar - App-Verzeichnis:
/opt/callrec(Node.js, systemdcallrec.service) - Harte Anforderungen: immer offline (kein Cloud-LLM), akustische Sprecher-ID, kein aktiver Lüfter
- Details und alle Zugangsdaten: 07 – Betrieb
Repo-Aufbau
| Verzeichnis | Inhalt |
|---|---|
app/ |
Spiegel von /opt/callrec auf dem Board: Node-Backend (server.js, recorder.js, llm.js, diar.js, spk.js, db.js, bt.js), Vite-Frontend (web/), Python-Inferenz (inference/), Audio-/Setup-Skripte (aime-*.sh), rkllm_server.cpp |
system/ |
System-Konfiguration, Pfade wie auf dem Board: systemd-Units (etc/systemd/system/, home/callrec/.config/systemd/user/), WirePlumber-Drop-ins, micgate-Filter-Chain, sudoers |
docs/ |
Diese Dokumentation |
Nicht im Repo (zu groß / Laufzeit-Artefakte): node_modules, web/dist (per npx vite build erzeugbar),
Modelle (*.rkllm, *.rknn, models/), rkllm_server-Binary (aus rkllm_server.cpp kompilierbar),
Aufnahmen, milestones/, .bak-*.
Restore-Hinweis: app/ → /opt/callrec, system/… → jeweilige Absolutpfade; danach npm install
(Root + web/), npx vite build in web/, User-Units mit systemctl --user enable aktivieren
(filter-chain.service maskieren!), Details in 07 – Betrieb.
⚠️ Das Repo ist die Kopie — die Wahrheit läuft auf dem Board. Nach jeder Board-Änderung Code hierher zurückspiegeln.
Doku-Regeln
- Diese Doku ist die verbindliche Ablage für alle zukünftigen Änderungen am System.
- Jede Änderung: betroffenes Kapitel aktualisieren und Eintrag in 08 – Changelog.
- Prozesse/Abläufe immer mit Mermaid-Diagramm dokumentieren (Gitea rendert sie direkt).
- Auf dem Board bleiben
.bak-*-Dateien als Rollback-Punkte; Meilenstein-Snapshots unter/opt/callrec/milestones/.