# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. > Sprache: Code-Kommentare, Doku und Commits auf Deutsch. ## Projektziel Lokale, schnelle, zuverlässige Spracherkennung, nicht blockierend. Baustein für Smarthome (Home Assistant via Wyoming, ESP32/Arduino als Audio-Clients) und **STT-Pendant zu `chatterbox-tts-cli`** (`~/chatterbox-tts-cli`: CLI-Kern + FastAPI-Service + MCP-Adapter + systemd-User-Service, Port 9999). Bewährtes STT-Vorbild: `~/my_voice_assistant_v3` (`app/providers/stt/faster_whisper.py`, `app/api/ws.py`). Git-Remote auf kitux.de (Forgejo) geplant, noch nicht eingerichtet. ## Dokumentation `README.md` (Überblick) · `BEDIENUNGSANLEITUNG.md` (Anwender, vollständige Tabelle der `STT_*`-Variablen) · `docs/API.md` (HTTP/WebSocket/Wyoming-Protokoll) · `docs/ENTWICKLER.md` (Architektur, Nebenläufigkeitsregeln, Tests, Erweitern). Bei Änderungen an Schnittstellen, Optionen oder Umgebungsvariablen die betroffenen Dokumente mitpflegen. ## Befehle ```bash .venv/bin/python -m pytest # Unit-Tests, ohne Modell (~9 s) .venv/bin/python -m pytest -m integration # echtes Whisper small/CPU + Silero, espeak-ng-Sprache (~20 s) .venv/bin/python -m pytest tests/test_service.py::test_ws_stream_with_vad_emits_transcripts_per_utterance CUDA_VISIBLE_DEVICES=GPU-83ba6d1f-ebbe-f8c8-1433-153e0ebc3866 .venv/bin/python stt_service.py # Port 9998, Wyoming 10300 .venv/bin/python stt_cli.py datei.wav | --once | --local --model small datei.wav ``` `.venv` ist mit `--system-site-packages` auf miniforge-Base angelegt (faster-whisper, fastapi, onnxruntime kommen von dort); nur `wyoming` ist in der venv installiert. Tests immer mit `.venv/bin/python`, sonst fehlt `wyoming`. ## Architektur - `stt_core.py` — reine Logik, kein print/sys.exit. `SttEngine` (Modell einmal laden, Lade-Versuche cuda→cpu mit `cpu_model`, `_run_lock` serialisiert Inferenz, `condition_on_previous_text=False`, Halluzinationsfilter `is_hallucination`), Audio-Hilfen (`decode_audio_bytes` via PyAV für jedes Format, `pcm16_to_float` mit Kanalwahl, `StreamResampler` via soxr), `UtteranceSegmenter` (Streaming-Endpointing über 512-Sample-Fenster; Wahrscheinlichkeitsfunktion injizierbar, Standard `SileroProb`). - `stt_service.py` — `create_app(engine, settings, vad_config, prob_fn_factory)` als Fabrik (Tests injizieren `FakeEngine`/`EnergyProb` aus `tests/conftest.py`). `TranscriptionWorker` = ThreadPoolExecutor(1) + Zähler `pending` → `Overloaded`/503. Preload läuft als erster Worker-Job, ohne den Start zu blockieren. `_StreamSession` = WebSocket-Protokoll (Empfangsschleife legt Äußerungen in eine Queue, `_consume` transkribiert der Reihe nach; `send_lock`, weil zwei Tasks senden). - `stt_wyoming.py` — Wyoming-Handler im selben Prozess/Worker; nimmt HA-Audio komplett an (externe VAD), `transcript_names/terms` → Whisper-`hotwords`; Verbindung wird nach dem Transkript geschlossen (HA-Konvention). - `stt_cli.py` — Client: Dateien per `POST /transcribe`, Mikrofon per `/ws/stream`; `--local` nutzt den Kern direkt. stdout nur Transkripte, stderr Status. Default-Mikrofon über das ALSA-Gerät `pulse` (PortAudios Default ist hier die falsche Onboard-Karte); ReSpeaker XVF3800 → automatisch Kanal 1 (ASR-Ausgang). - `legacy/stt.py`, `legacy/stt_respeaker.py` — **historische** Einzelskripte, nicht weiterentwickeln. Sprache: `language=None` → Config-Default, `"auto"` → Erkennung, `"de-DE"` → `"de"` (`SttEngine.resolve_language`). ## Umgebung GPUs: T600 + 2× RTX 3090. `nvidia-smi` zählt in PCI-Reihenfolge, CUDA „fastest first“ → GPU immer per `CUDA_VISIBLE_DEVICES=GPU-` pinnen. GPU 1 belegt llama.cpp/ollama fast komplett; der Dienst läuft auf GPU 2 (`large-v3-turbo` ≈ 2,4 GB) neben chatterbox-tts und open-notebook-stt (:8902). HF-Modelle unter `$HF_HOME`.