diff --git a/docs/plans/2026-04-01-settings-remote-whisper-design.md b/docs/plans/2026-04-01-settings-remote-whisper-design.md new file mode 100644 index 0000000..58e87e4 --- /dev/null +++ b/docs/plans/2026-04-01-settings-remote-whisper-design.md @@ -0,0 +1,113 @@ +# Settings Page & Remote Whisper Design + +**Date:** 2026-04-01 + +## Goal + +Give each Linux client a settings page to configure audio device (via PipeWire/pactl) and remote server URLs (Whisper + Ollama). Beastix runs faster-whisper-server and Ollama; clients point their config at it. + +## Architecture + +``` +┌─────────────────┐ ┌─────────────────────────────┐ +│ Client (Linux) │ │ Beastix (LAN) │ +│ │ WAV │ │ +│ sounddevice │ ──────► │ faster-whisper-server │ +│ PipeWire src │ │ :8000 (OpenAI-kompatibel) │ +│ localhost:8765 │ Text │ │ +│ Browser UI │ ◄────── │ Ollama :11434 │ +└─────────────────┘ └─────────────────────────────┘ +``` + +Default: `whisper.base_url` leer → lokale faster-whisper-Instanz. Gesetzt → HTTP-Upload an Beastix. + +## Settings Page (`/settings`) + +Nur für Admins sichtbar (Gear-Icon im Header). Zwei Abschnitte: + +### Abschnitt 1 — Audio + +- Dropdown: alle verfügbaren PipeWire-Sources (live via `pactl list sources short`) +- Button "Combined Source erstellen" → App führt pactl-Kommandos aus, Combined Source erscheint in der Liste +- Gewähltes Device → `config.toml [audio] device = "..."` +- sounddevice nutzt diesen Device-Namen beim nächsten Start einer Aufnahme + +### Abschnitt 2 — Verarbeitung + +- Whisper `base_url`: leer = lokal, sonst z.B. `http://beastix:8000` +- Whisper `model`: Freitextfeld (default: `large-v3`) +- Ollama `base_url`: z.B. `http://beastix:11434` +- Ollama `model`: Dropdown gefüllt via `GET {ollama_base_url}/api/tags` + +Änderungen werden sofort in `config.toml` gespeichert (PUT /config). + +## Remote Whisper (transcription.py) + +```python +if cfg["whisper"].get("base_url"): + # OpenAI-kompatibler Upload + POST {base_url}/v1/audio/transcriptions + multipart: file=, model=, language= + → response.text +else: + # Lokal wie bisher + WhisperModel(model_name, device=device).transcribe(...) +``` + +## Neue API-Endpoints + +| Method | Path | Beschreibung | +|--------|------|--------------| +| GET | `/settings` | Liefert settings.html | +| GET | `/audio/devices` | pactl sources geparst → JSON-Liste | +| POST | `/audio/combined` | Erstellt PipeWire Combined Source via pactl | + +PUT `/config` ist bereits vorhanden — wird um `audio.device` und `whisper.base_url` erweitert. + +## Config-Schema Erweiterung + +```toml +[audio] +device = "" # leer = Systemstandard, sonst PipeWire-Source-Name + +[whisper] +model = "large-v3" +language = "de" +device = "auto" +base_url = "" # leer = lokal, sonst http://beastix:8000 +``` + +## PipeWire Combined Source + +Beim Klick auf "Combined Source erstellen": + +```bash +pactl load-module module-null-sink \ + sink_name=transkriptor-combined \ + sink_properties=device.description="Transkriptor\ Combined" + +pactl load-module module-loopback \ + source= sink=transkriptor-combined + +pactl load-module module-loopback \ + source=.monitor sink=transkriptor-combined +``` + +Ergebnis: `transkriptor-combined.monitor` erscheint als aufnehmbare Source in der Liste. + +Die Module-IDs werden in `config.toml` gespeichert damit sie beim App-Stop sauber entladen werden können (`pactl unload-module `). + +## Beastix Setup (einmalig) + +```bash +pip install faster-whisper-server +faster-whisper-server --host 0.0.0.0 --port 8000 --model large-v3 +``` + +Oder als systemd user service. Clients tragen dann `whisper.base_url = "http://beastix:8000"` ein. + +## Nicht in diesem Scope + +- Nutzer-Verwaltung über Settings (eigene Seite) +- Automatischer Neustart wenn Config sich ändert +- Windows-Support