router: deutsche Spracherkennung mit whisper.cpp (CPU-only)

- STT-Worker (stt_worker.py): langlebiger HTTP-Service auf Port 8084
  - whisper-cli als Subprozess (CPU-only, 8 Threads)
  - Audio-Vorbereitung via ffmpeg (WebM/Opus/M4A → 16 kHz WAV)
  - Nativ: WAV, MP3, OGG, FLAC
  - Health-Endpunkt: GET /status
  - Transkription: POST /transcribe (Multipart-Form-Data)

- Router-Integration:
  - POST /v1/audio/transcriptions (OpenAI-kompatibel)
  - GET /v1/audio/models (whisper-1, kokoro-german)
  - GET /v1/audio/voices (martin, victoria)
  - /status mit stt-Section
  - model=whisper-1 akzeptiert
  - response_format: json, verbose_json

- systemd-Service: mike-ai-whisper.service
  - Boot-Start, Restart on failure, journald
  - CPU-only, kein GPU-Lock

- Deploy-Dateien aktualisiert (deploy.sh, install.sh)
- Mock-STT-Worker für lokale Tests (dev/mock_stt_worker.py)
- Tests ergänzt: STT Status, WAV, language=de, unbekanntes Modell,
  Worker down, Recovery, Audio-Modelle, Audio-Voices,
  STT+Qwen parallel, STT+TTS parallel
- README.md: STT-Section mit Endpunkten, Benchmarks, Doku

Benchmarks (CPU-only, 8 Threads):
  7.3 s Audio → 8.9 s (RTF 1.22×)
  30 s Audio → 16.8 s (RTF 0.56×)
  50 s Audio → 18.5 s (RTF 0.37×)
  RAM: ~1.7 GB (Modell), Worker: ~20 MB
This commit is contained in:
Mikei386
2026-08-19 13:53:22 +02:00
parent ff064685ce
commit 51ef07c874
8 changed files with 1059 additions and 6 deletions
+96
View File
@@ -19,6 +19,7 @@ Sprachausgabe bereit (Kokoro-82M, CPU-only, OpenAI-kompatibel).
| Router-Port | **8081** |
| Router-Service | `mike-ai-profile-router.service` |
| TTS-Worker | `http://127.0.0.1:8082` (Service `mike-ai-kokoro.service`) |
| STT-Worker | `http://127.0.0.1:8084` (Service `mike-ai-whisper.service`) |
## Profile / virtuelle Modelle
@@ -40,6 +41,9 @@ Sprachausgabe bereit (Kokoro-82M, CPU-only, OpenAI-kompatibel).
| `GET /images` | Liste der gespeicherten Bilder (max. 200) |
| `GET /images/<datei>` | PNG-Download (nur `images/`-Verzeichnis, validiert) |
| `POST /v1/audio/speech` | Deutsche Sprachausgabe (Kokoro-82M, OpenAI-kompatibel) |
| `POST /v1/audio/transcriptions` | Deutsche Spracherkennung (whisper.cpp, OpenAI-kompatibel) |
| `GET /v1/audio/models` | Verfügbare Audio-Modelle (STT + TTS) |
| `GET /v1/audio/voices` | Verfügbare TTS-Stimmen |
| alles andere | Transparente Weiterleitung an llama.cpp |
### Verhalten
@@ -280,14 +284,106 @@ Pfad `phonemizer-fork` + `espeakng-loader` (kein spacy-curated-transformers,
kein thinc 9.x). `spacy` wird nur für den `misaki.en`-Import benötigt
(Englisch), nicht für den deutschen Pfad.
## Spracherkennung (whisper.cpp, deutsch, CPU-only)
Der Router stellt lokale deutsche Spracherkennung bereit. Die Transkription
läuft in einem **separaten, langlebigen Worker** (`mike-ai-whisper.service`),
der `whisper-cli` als Subprozess aufruft. Der Worker ist CPU-only und
blockiert weder Qwen/llama.cpp noch FLUX/GPU – er teilt sich nur den
Prozessor.
- **Modell:** Whisper large-v3-turbo (ggml, ~1.6 GB, Vollpräzision)
- **Build:** whisper.cpp CPU-only (AVX2+FMA, 8 Threads)
- **Audio-Vorbereitung:** ffmpeg konvertiert WebM/Opus/M4A/AAC → 16 kHz mono WAV
- **Nativ unterstützt:** WAV, MP3, OGG, FLAC
- **Kein GPU-Lock:** STT läuft vollständig auf CPU, parallel zu Qwen (GPU)
und TTS (CPU)
### Endpunkt `POST /v1/audio/transcriptions`
OpenAI-kompatibel (Multipart-Form-Data). Unterstützt `file`, `model`,
`language`, `prompt`, `temperature`, `response_format`.
| Parameter | Werte | Default |
|---|---|---|
| `file` | Audio-Datei (Pflicht: webm, wav, mp3, m4a, ogg, flac) | – |
| `model` | `whisper-1` (oder `whisper`) | `whisper-1` |
| `language` | `de`, `en`, … (optional) | Auto-Detektion |
| `prompt` | Kontext-Hinweis (optional) | – |
| `temperature` | 0.0–1.0 (optional) | 0.0 |
| `response_format` | `json` (Default), `verbose_json` | `json` |
Die Antwort ist **JSON** mit `text` (und optional `language`, `duration`
bei `verbose_json`).
Beispiele:
```bash
# WebM/Opus (z.B. aus Open WebUI-Mikrofon)
curl -s http://192.168.1.196:8081/v1/audio/transcriptions \
-F "file=@aufnahme.webm" \
-F "model=whisper-1"
# WAV mit expliziter Sprache
curl -s http://192.168.1.196:8081/v1/audio/transcriptions \
-F "file=@aufnahme.wav" \
-F "model=whisper-1" \
-F "language=de"
# Verbose-Format
curl -s http://192.168.1.196:8081/v1/audio/transcriptions \
-F "file=@aufnahme.wav" \
-F "model=whisper-1" \
-F "response_format=verbose_json"
```
### Discovery-Endpunkte
- `GET /v1/audio/models` – listet verfügbare Audio-Modelle
(`whisper-1` für STT, `kokoro-german` für TTS)
- `GET /v1/audio/voices` – listet verfügbare TTS-Stimmen
(`martin`, `victoria`)
### Verhalten
- **Kein GPU-Lock:** STT läuft CPU-only und greift nicht in den
GPU-Hotswap (Bild) oder Profilwechsel (Qwen) ein. STT-Requests können
parallel zu Chats, TTS und Bildgenerierung laufen.
- **Serialisierte Transkription:** Der Worker transkribiert nacheinander
(CPU-bound), parallele Requests werden intern gewartet.
- **`/status`** zeigt `stt.reachable`, `stt.ready`, `stt.model`,
`stt.threads`, `stt.language`, `stt.ffmpeg_exists`.
- **Fehler:** Worker down → `503` (`stt_failed`); ungültige Parameter →
`400`. OpenAI-kompatibles Fehlerformat.
### Benchmark (CPU-only, gemessen)
| Audio-Dauer | Transkription | RTF |
|---|---|---|
| 7.3 s | 8.9 s | 1.22× |
| 30 s | 16.8 s | 0.56× |
| 50 s | 18.5 s | 0.37× |
RTF < 1.0 bedeutet: Transkription ist schneller als Echtzeit.
RAM-Belegung des Workers: ~1.7 GB (inkl. Modell).
### Erforderliche Komponenten
- `whisper.cpp` (CPU-only Build, `/opt/mike-ai/whisper.cpp/build-cpu/`)
- `ggml-large-v3-turbo.bin` (`/opt/mike-ai/models/whisper/`)
- `ffmpeg` (für WebM/Opus/M4A/AAC-Konvertierung)
- Python 3.13 (nur Standardbibliothek, kein Venv nötig)
## Repository-Struktur
```
router/ai_profile_router.py # der Router (einzige Laufzeit-Datei)
router/image_worker.py # FLUX-Worker (eigener Prozess, JSON-Protokoll)
router/tts_worker.py # Kokoro-TTS-Worker (eigener Prozess, HTTP-API)
router/stt_worker.py # Whisper-STT-Worker (eigener Prozess, HTTP-API)
deploy/mike-ai-profile-router.service # systemd-Unit (Router)
deploy/mike-ai-kokoro.service # systemd-Unit (TTS-Worker)
deploy/mike-ai-whisper.service # systemd-Unit (STT-Worker)
deploy/install.sh # läuft auf dem Zielsystem (per SSH)
deploy/deploy.sh # läuft lokal: SCP + SSH
dev/ # lokale Tests (Mock-llama.cpp, Mock-Worker, Benchmarks)