root 5f0b41161e feat(export): Volltranskript als Anhang in DOCX/PDF (meeting/phone-call/interview)
LLM komprimiert das Transkript bisher auf wenige Sätze + 20 Excerpt-Einträge
— der Rest fiel aus dem Dokument. Pipeline reicht Whisper-Segmente jetzt an
build_docx/build_pdf durch; Profile mit `docx.include_full_transcript: true`
hängen das komplette Transkript (9 pt) am Ende an.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 14:35:34 +00:00

Voice-Agent

Self-hosted Transkriptions- und Protokollsystem für Sprachaufzeichnungen — vollständig lokal, DSGVO-konform.

Vollständiges Lastenheft: siehe need.md

Architektur

Benutzer (Browser / Handy-PWA)
  │
  ▼  HTTPS  (selbst-signiert, Mikrofon-fähig)
┌──────────────────────────────┐         ┌──────────────────────────────┐
│  LXC-Container (Linux)       │  HTTP   │  Mac (Apple Silicon)         │
│  - FastAPI + HTML/JS UI      │ ──────► │  - FastAPI Worker            │
│  - SQLite Job-Store + Auth   │         │  - lightning-whisper-mlx     │
│  - Profile (YAML, ≥17)       │         │  - Ollama (Standard 8B)      │
│  - Result-/Upload-Verz.      │ ◄────── │  - python-docx + reportlab   │
│  - Nginx HTTPS-Reverse-Proxy │         │  - Per-Job Log-Ringbuffer    │
└──────────────────────────────┘         └──────────────────────────────┘
  • LXC: keine AI-Verarbeitung — nur Uploads, Job-Tracking, Login, Auslieferung.
  • Mac: Stateless API. Erhält Audio/Text, gibt Transkripte / Zusammenfassungen / Protokolle / DOCX / PDF zurück.

Funktionsumfang (aktueller Stand)

  • Audio-Upload (MP3, WAV, M4A, MP4, OGG, FLAC, WEBM — max. 500 MB)
  • Mobile-First-Layout + PWA mit Mikrofon-Aufnahme (Start / Pause / Stop)
  • Whisper-Transkription auf dem Mac (MLX, Apple Neural Engine)
  • Ollama-Zusammenfassung
  • Strukturiertes Protokoll je Profil
  • 17 Verarbeitungs-Profile (Sitzung, Diktat, Pflegedoku, IT-Ticket, Sales-Call, …)
  • DOCX- und PDF-Export
  • Benutzer-Verwaltung (bcrypt, Cookie-Sessions, Per-User-Job-Isolation, Admin-Rolle)
  • HTTPS via selbst-signiertem Zertifikat (Mikrofon-Zugriff am Handy)
  • Idempotente Pipeline + Retry — bei „Server disconnected" automatischer 1× Retry, Transkript wird beim manuellen Erneut-Versuchen weiterverwendet
  • Diagnose-Panel pro Job — Live-Heartbeat während laufender Mac-Calls + Mac-Worker-Log direkt in der UI
  • Speaker-Diarization (Prio 2 — siehe mac-worker/README.md)

Installation — Schritt für Schritt

Voraussetzungen:

  • Mac (Apple Silicon empfohlen, M1/M2/M3/M4) mit min. 16 GB RAM, besser 32 GB.
  • Proxmox-Host (oder beliebiger Linux-Host) für den LXC-Container.
  • Netzwerk: Mac und LXC im selben LAN, der LXC muss den Mac auf Port 8080 erreichen.

Schritt 1 — LXC-Container provisionieren (Proxmox)

Container mit:

  • Debian 13 (Trixie) oder Ubuntu 24.04
  • 2 vCPU, 2 GB RAM, 20 GB Disk reichen
  • Statische LAN-IP, SSH-Zugang als root

Schritt 2 — App im LXC installieren

Im Container als root einloggen, dann eine der folgenden Optionen wählen:

Option A — Auto-Install per Curl (Repo wird selbst geklont):

bash <(curl -sSL https://git.cynfo.net/christian/voice-agent/raw/branch/main/deploy/install.sh)

Option B — Manuell aus geklontem Repo:

git clone https://git.cynfo.net/christian/voice-agent.git /var/www/voice-agent
cd /var/www/voice-agent
./deploy/install.sh

Das Skript installiert idempotent:

  1. apt-Pakete (git python3-venv nginx ffmpeg openssl …)
  2. Deploy-User deploy, klont/aktualisiert Repo nach /var/www/voice-agent
  3. Python-venv + Dependencies in lxc-frontend/.venv
  4. .env aus Vorlage anlegen, SESSION_SECRET automatisch erzeugen
  5. Verzeichnisse /var/lib/voice-agent/{uploads,results} + SQLite-DB
  6. systemd-Service voice-agent.service (autostart, restart-on-failure)
  7. Selbst-signiertes TLS-Zertifikat mit SAN (Hostname + IP)
  8. Nginx HTTPS-Reverse-Proxy + HTTP→HTTPS Redirect
  9. CLI-Wrapper /usr/local/bin/voice-agent-admin

Erneutes Ausführen aktualisiert auf den neuesten main (idempotent, kein Datenverlust — die SQLite-DB liegt unter /var/lib/voice-agent/, nicht im App-Verzeichnis).

Schritt 3 — Mac-Worker einrichten

Auf dem Mac (Details in mac-worker/README.md):

# Repo holen
git clone https://git.cynfo.net/christian/voice-agent.git ~/voice-agent
cd ~/voice-agent/mac-worker

# Ollama + Modell (einmalig)
brew install ollama
launchctl setenv OLLAMA_HOST "0.0.0.0:11434"
brew services restart ollama
ollama pull llama3.1:8b

# Worker als LaunchAgent installieren — macht venv + Dependencies + Autostart in einem Rutsch
./deploy/install-launchagent.sh

Test vom LXC aus:

curl http://<MAC-LAN-IP>:8080/health
# erwartet: {"status":"ok","whisper_engine":"mlx","ollama_reachable":true,...}

Schritt 4 — LXC mit Mac verbinden

Im LXC MAC_API_URL auf die Mac-LAN-IP setzen:

sudo nano /var/www/voice-agent/lxc-frontend/.env
# MAC_API_URL=http://192.168.x.y:8080
sudo systemctl restart voice-agent

Schritt 5 — Erst-Anmeldung + Benutzen

Browser auf https://<LXC-IP>/ — beim allerersten Aufruf legt die UI den initialen Admin an (Username + Passwort wählen). Bestehende Jobs werden diesem Konto zugeordnet.

Audio hochladen oder direkt in der UI aufnehmen → fertig.


Update / Neudeployment

LXC — einfach nochmal:

sudo /var/www/voice-agent/deploy/install.sh

Mac — ein Befehl macht git-pull + pip-install + Worker-Restart + Health-Check:

~/voice-agent/mac-worker/deploy/update.sh

(Falls update.sh aus irgendeinem Grund nicht läuft, ist ./deploy/install-launchagent.sh restart der manuelle Fallback.)


Benutzer-Verwaltung / Passwort zurücksetzen

Auf dem LXC steht nach dem Deploy voice-agent-admin als Befehl bereit:

# Passwort zurücksetzen (z. B. Admin-Login vergessen)
sudo voice-agent-admin reset admin 'NeuesPasswort123'

# User auflisten / anlegen / löschen
sudo voice-agent-admin list
sudo voice-agent-admin create maria 'StartPasswort123'
sudo voice-agent-admin create chefin 'Geheim12345' --admin
sudo voice-agent-admin delete maria

# Passwort prüfen ohne Browser (Debug)
sudo voice-agent-admin verify admin 'NeuesPasswort123'

Vollständige Befehlsreferenz: lxc-frontend/README.md.


Profile

Jeder Job läuft mit einem Verarbeitungs-Profil, das die Prompts für Summary, Protokoll und das Layout des Exports steuert. Standard ist meeting. Das Standard-Profil je User wird im Web-UI im Header gewählt und bleibt gespeichert.

Mitgelieferte Profile (alle in mac-worker/profiles/*.yaml):

Profil Zweck
meeting Klassisches Sitzungsprotokoll
phone-call Telefonat-Notiz mit Beteiligten/Verabredungen
memo Kurze Sprachnotiz / Diktat
interview Interview mit Sprecherspuren
one-on-one 1:1-Gespräch (Mitarbeiter / Kunde)
brainstorm Ideen-Sammlung mit Cluster-Vorschlägen
service-ticket IT-Service-Ticket aus Anruf-Mitschnitt
incident-report Incident-Doku (was, wann, Auswirkung, Status)
postmortem Post-Mortem mit Lessons-Learned
site-survey Vor-Ort-Aufnahme (Leitungsverlauf, Hardware, Zustand)
sales-call Sales-Gespräch mit Pain-Points / Next-Steps
schichtuebergabe Schichtübergabe Pflege
pflegedoku Pflegedokumentations-Eintrag
sturzbericht Sturzbericht (Pflege)
visite Arzt-Visite
angehoerigengespraech Angehörigen-Gespräch (Pflege)
biografie Biografie-Eintrag (Pflege)

Eigene Profile: einfach eine weitere YAML-Datei in mac-worker/profiles/ ablegen (Beispiel siehe meeting.yaml) und Mac-Worker neu starten.


Diagnose / Troubleshooting

Wenn ein Job hängt oder fehlschlägt:

  • In der UI: bei FAILED-Jobs und langlaufenden Stages erscheint „Diagnose ▾". Aufklappen zeigt:
    • aktuelle Stage und wie lange sie schon läuft
    • letzter Heartbeat (alle 3 s während Mac-Calls)
    • die letzten 200 Mac-Worker-Log-Zeilen für genau diesen Job
  • Auf dem LXC:
    • systemctl status voice-agent / journalctl -u voice-agent -f
    • curl -sk https://localhost/api/mac/health
  • Auf dem Mac:
    • ~/voice-agent/mac-worker/deploy/install-launchagent.sh status
    • tail -f ~/Library/Logs/voice-agent-worker.{out,err}.log

Wenn der Mac mitten in summarize die Verbindung abreissen lässt, retried der LXC einmal automatisch (3 s Backoff) — ein vorgelagerter Preload-Aufruf hat zudem das Ollama-Modell schon ins RAM geladen, damit es nicht in der eigentlichen Generierung neu lädt.


Modelle

Transkription (Mac, Whisper)

WHISPER_ENGINE WHISPER_MODEL Wann nutzen
mlx large-v3 (Default) Maximale Qualität, langsamer (~0.3× Realzeit auf M2)
mlx distil-large-v3 ~5× schneller, minimal schlechtere Qualität
mlx medium Schneller, deutlich schlechter bei Fachbegriffen
faster large-v3 Intel-Mac / Linux / CUDA
mock Tests ohne Modell-Download

Standard ist mlx + large-v3. Für lange Sitzungen lohnt sich distil-large-v3. Alternativen (whisper.cpp + CoreML, WhisperX mit Diarization, Voxtral) sind in mac-worker/README.md dokumentiert.

Zusammenfassung (Ollama)

Standard: llama3.1:8b — solide Basisqualität bei deutschen Texten, ~8 GB Speicher.

Empfohlene Alternativen je nach Hardware (alle via ollama pull <name> und OLLAMA_MODEL=<name> in .env):

Modell Größe RAM-Bedarf Stärken
llama3.1:8b (Default) 8 B ~8 GB Schnell, brauchbares Deutsch
qwen2.5:14b 14 B ~10 GB Sehr zuverlässige JSON-Ausgabe, exzellentes Deutsch
mistral-small:24b 24 B ~16 GB Europäisch trainiert, beste Kompromiss-Wahl
gemma3:12b 12 B ~10 GB Stark multilingual, gute Strukturierung
gpt-oss:20b 20 B ~14 GB Sehr gute strukturierte Ausgabe (OpenAI Open-Weight)
llama3.3:70b 70 B ~48 GB Top-Qualität, nur auf Macs mit 64 GB+

Für deutsche Protokolle mit viel JSON-Struktur ist qwen2.5:14b oder mistral-small:24b der beste Sweet-Spot auf einem Mac mit 32 GB.

Detaillierte Bewertung siehe mac-worker/README.md.


Verzeichnisstruktur

voice-agent/
├── lxc-frontend/        # FastAPI Web-App (läuft im LXC)
│   ├── app/
│   ├── requirements.txt
│   └── .env.example
├── mac-worker/          # FastAPI AI-Worker (läuft auf dem Mac)
│   ├── app/
│   ├── profiles/        # YAML-Profile (Prompts + Layout)
│   ├── deploy/          # install-launchagent.sh, update.sh, plist-Template
│   ├── requirements.txt
│   └── .env.example
├── deploy/              # systemd / nginx / install.sh (LXC)
├── config/              # Toolkit-Konfiguration (project.env)
├── .claude/             # KI-Agenten Skills
├── need.md              # Lastenheft
└── README.md

Sicherheit

  • Vollständig lokaler Betrieb. Keine Cloud-Calls.
  • HTTPS mit selbst-signiertem Cert (für Mikrofon-Zugriff am Handy zwingend nötig).
  • Web-UI ist Cookie-Session-basiert (bcrypt cost 12, signiert mit SESSION_SECRET).
  • Mac-Worker hat keine Auth — Betrieb nur im internen Netz.
  • Uploads / Ergebnisse unter /var/lib/voice-agent/ — bei Bedarf Backup einplanen.
  • .env-Dateien (LXC + Mac) sind chmod 600, enthalten Session-Secret + ggf. Tokens.
Description
Self-hosted AI transcription system (LXC web frontend + Mac AI worker)
Readme 525 KiB
Languages
Python 51.6%
JavaScript 23.9%
CSS 11.9%
Shell 7.7%
HTML 4.6%
Other 0.3%