Files
cluster-knaster/docs/auftraege/2026-10-12-sprachmodelle-nex.md
T
2026-10-12 21:07:11 +02:00

20 KiB
Raw Blame History

Auftrag: Sprachmodelle (Spracherkennung + Sprachausgabe) für NEX auf dem knaster-Cluster

Eingang 12.10.2026 (vom NEX-Team, ohne Schlüssel). Ausführung nach Task 3.2 (GPU-VMs mit Treiber), gern durch einen Subagenten. Im Plan als Task 6.5 geführt.

Abgleich mit dem echten Cluster (Stand 12.10.2026, vor Ausführung lesen)

Der Auftrag geht von einem älteren Bild aus. Es gilt:

Auftrag sagt Wirklichkeit
2 Knoten + QDevice 5 Knoten (pve44, pve46, pve48, pve52, pve61), 5 Stimmen, kein QDevice
Knoten A 2× P2000, Knoten B 2× M4000, GPU per LXC oder VM Eine Ubuntu-24.04-VM pro GPU-Knoten mit allen Karten (D2): gpu-pve44, gpu-pve46, gpu-pve48 je M4000 + P2000, gpu-pve52 nur M4000. Treiber R580 in der VM
Feste IP per DHCP-Reservierung D5 ist zurückgestellt. Gäste laufen per DHCP, der Nutzer hat keinen Zugriff auf den DHCP-Server. Vor der Abnahme klären: Reservierung durch die DHCP-Verwaltung oder statische IP außerhalb des DHCP-Bereichs

Daraus folgt für die Umsetzung:

  • Erkennung: whisper.cpp (CUDA 12, CMAKE_CUDA_ARCHITECTURES="52;61") auf einer M4000. Naheliegend ist gpu-pve52: Dort steckt nur die M4000, und Placement verteilt keine andere Rolle dorthin. Die P2000 bleiben für embed/rerank (pve44, pve46) und gpu-small (pve48). Die M4000 sind im Inventar disabled bis zum Benchmark-Tag (Task 3.3); die Messwerte aus 4. Abnahme liefern genau diesen Benchmark für whisper und gehören in Task 3.3.
  • Ausgabe Stufe 1 (Piper, CPU): laut Registry tts-de im Infra-LXC (infra, Task 5.2). Solange infra nicht steht, als Container in derselben GPU-VM wie die Erkennung (CPU reicht).
  • Firewall „nur von 192.168.100.29“: Proxmox-Firewall an der Netzkarte der VM (firewall=1, Regeln für 8178/8179) plus ufw in der VM.
  • Globale Vorgabe aus dem Plan passt: whisper-server auf Port 8178, nur von .29, stt.openai.base_url nur als IP-Literal.

Auftrag (Originaltext)

NEX sind Hermes-Agenten auf appsrv08 (192.168.100.29). Sprache läuft dort: Hermes → nex-router → LiteLLM → Sprach-Backend. Das Backend ist austauschbar (Eintrag in LiteLLM). Der Dienst auf dem Cluster ist das Rückfall-Modell. Solange kein Cloud-Anbieter Guthaben hat, ist er der einzige aktive Weg. Die NEX-Seite trägt danach nur IP:Port und Modellnamen in LiteLLM ein. Gebraucht werden zwei OpenAI-kompatible HTTP-Dienste im internen Netz. Ein Dienst für beides ist auch in Ordnung.

Formate laut Hermes-Code: mp3 als Standard, Opus für Sprachnachrichten, rohes PCM mit Sample-Rate-Header für das Streaming.

Hardware und Grenzen

  • Treiber R580, die letzte Serie für Maxwell/Pascal.
  • faster-whisper/CTranslate2 laufen nicht auf CC 5.2. Auf der M4000 nur whisper.cpp, und zwar als CUDA-12-Build, nicht CUDA 13 (-DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES="52;61").
  • PyTorch-Unterstützung für sm_50/sm_61 in aktuellen Wheels vorher prüfen (python -c "import torch; print(torch.cuda.get_arch_list())"), nicht annehmen. Keine Tensor-Cores: bei faster-whisper int8 oder int8_float32.

1. Spracherkennung (Pflicht)

  • Modell Whisper large-v3-turbo, Sprache fest de.
    • Empfehlung M4000: whisper.cpp whisper-server mit -m ggml-large-v3-turbo.bin -l de -bs 5 --convert --inference-path /v1/audio/transcriptions, ohne --print-realtime, --tmp-dir auf tmpfs (z. B. /run/nex-whisper). Nach dem Start einmal mit 1 s Stille aufwärmen.
    • Alternative P2000: speaches (faster-whisper) mit deepdml/faster-whisper-large-v3-turbo-ct2, int8_float32.
    • Optional mitmessen: primeline/whisper-large-v3-turbo-german.
  • Schnittstelle: POST /v1/audio/transcriptions, multipart
    • Felder: file, model, language=de, response_format.
    • file muss wav, mp3, ogg/opus, webm und m4a annehmen (Umwandlung mit ffmpeg).
    • response_format: json → {"text": "…"}, text, verbose_json (wenn möglich mit Wort-Wahrscheinlichkeiten).
    • Unbekannte Felder ignorieren, nicht mit Fehler antworten.

2. Sprachausgabe (Pflicht Stufe 1, optional Stufe 2)

  • Stufe 1: Piper Deutsch, CPU reicht. Stimmen: de_DE-thorsten-high und eine weibliche deutsche Stimme. Genauen Namen nennen. Server OpenAI-kompatibel, z. B. speaches (kann Piper) oder ein schlanker Wrapper.
  • Schnittstelle: POST /v1/audio/speech
    • JSON-Body {model, voice, input, response_format, speed}.
    • response_format muss können: mp3 (Standard), opus (im Ogg-Container), wav, flac, pcm (rohes int16, little-endian, mono; Sample-Rate im Header X-Audio-Sample-Rate oder in Content-Type: audio/pcm; rate=<Hz>).
    • Antwort möglichst gestreamt (chunked), damit die Wiedergabe früh beginnt.
  • Stufe 2 (optional, GPU, nach PyTorch-Prüfung): eine natürlichere deutsche Stimme.
    • Lizenz für kommerzielle Nutzung prüfen. Nach Stand des NEX-Teams sind XTTS-v2 (Coqui Public Model License) und die Gewichte von Fish Speech/OpenAudio nicht kommerziell.
    • Chatterbox Multilingual (MIT) ist ein Kandidat.
    • Kokoro hat nach diesem Stand keine deutsche Stimme. Prüfen, nicht voraussetzen.

3. Für beide Dienste

  • GET /health → 200.
  • Feste IP in 192.168.100.0/24 (siehe Abgleich oben). Ports zum Beispiel 8178 (Erkennung) und 8179 (Ausgabe).
  • Firewall: Zugriff nur von 192.168.100.29. LiteLLM läuft dort in einem Bridge-Netz und erscheint mit der Host-IP.
  • Kein API-Key nötig. Erzwingt der Server einen, einen festen Dummy-Wert nennen (kein Geheimnis).
  • Autostart nach Neustart (systemd oder Docker restart: unless-stopped), Energiesparen aus, Sicherheitsupdates.
  • Datenschutz: keine Ablage von Audio oder Text; Temp-Dateien nur im RAM, alte regelmäßig löschen; keine Transkripte oder vorgelesenen Texte in Logs.

4. Abnahme

Von appsrv08 aus prüfen, Testaudio ohne Kundendaten, danach löschen.

  • Erkennung:
    • curl -s -w ' %{time_total}s\n' -F file=@t10.wav -F model=whisper -F language=de -F response_format=json http://IP:8178/v1/audio/transcriptions
    • Text muss deutsch und plausibel sein.
    • Median aus 3 Läufen: 10 s Audio ≤ 4 s (Ziel ≤ 3 s), 60 s Audio ≤ 12 s. Den ersten Aufruf getrennt notieren.
  • Ausgabe: curl -s -o t.mp3 -w ' TTFB %{time_starttransfer}s gesamt %{time_total}s\n' -H 'Content-Type: application/json' -d '{"model":"piper","voice":"de_DE-thorsten-high","input":"Guten Tag, hier ist Ihr NEX-Assistent. Die Baubesprechung in Haslach ist am vierten November.","response_format":"mp3"}' http://IP:8179/v1/audio/speech
    • Ergebnis abspielbar, Zeit bis zum ersten Byte möglichst ≤ 1 s.
    • Dasselbe mit pcm (Sample-Rate-Header prüfen) und opus.
  • Last: 2 Erkennungen gleichzeitig. Mit nvidia-smi prüfen, dass GPU-Last und VRAM steigen.

5. Rückmeldung (genau so)

Je Dienst: Basis-URL (IP:Port) · Knoten und GPU · Software mit Version oder Image-Digest · Modellname(n), wie im Feld model erwartet · Stimmen-IDs · unterstützte response_format · PCM-Sample-Rate · Messwerte (Median, erster Aufruf, VRAM, RAM) · Autostart nach Neustart getestet (ja/nein) · Auffälligkeiten.

Gegenseite (NEX, zur Information)

Die Agenten fragen nur noch neutrale Namen an: nex-stt für die Erkennung, nex-tts für die Ausgabe. Welches Backend dahinter antwortet und in welcher Reihenfolge, legt allein LiteLLM fest: heute das Cluster, später ein Cloud-Anbieter davor und das Cluster als Rückfall. nex-router 0.2.3 wird um die Sprachausgabe (gestreamt) erweitert. Nach der Rückmeldung trägt das NEX-Team die Endpunkte in LiteLLM ein und testet die Kette. Live erst mit dem neuen Router-Image.

Rückmeldung (Stand 12.10.2026, Task 6.2)

Umgesetzt in gpu-pve52 (VM 252 auf pve52). Getestet in der VM (localhost) und von ops mit einer temporären ufw-Regel, die danach wieder entfernt wurde. Von appsrv08 noch nicht geprüft, das bleibt für das NEX-Team. Testaudio kam aus Piper (zwei Sätze zur Baubesprechung, keine Kundendaten) und wurde danach gelöscht.

Feste IP fehlt (D5):

  • Die VM hat ihre Adresse per DHCP: heute 192.168.100.174, MAC bc:24:11:92:4b:eb.
  • Die Adresse hat den Neustart überstanden, ist aber nicht garantiert.
  • Vor dem Eintrag in LiteLLM: Reservierung auf diese MAC einrichten oder eine statische Adresse vergeben.

Energiesparen und Updates:

  • Die VM hat kein Suspend und kein Energiesparen (Ubuntu-Server-Cloud-Image).
  • Die GPU läuft im Leerlauf in P5 mit 17 W. Der Kontext bleibt geladen, weil whisper-server läuft.
  • Die Energieeinstellungen der Proxmox-Knoten habe ich laut Vorgabe nicht angefasst.
  • Sicherheitsupdates laufen per unattended-upgrades.

API-Key: Keiner nötig, kein Dummy-Wert. Beide Dienste ignorieren das Feld model, jeder Wert geht.

Erkennung (nex-stt)

Basis-URL: http://192.168.100.174:8178

  • Pfad: POST /v1/audio/transcriptions
  • Zustand: GET /health → {"status":"ok"}, solange das Modell lädt: 503

Knoten und GPU: pve52, VM gpu-pve52, Quadro M4000 (8 GB, CC 5.2), Treiber 580.178.04

Software:

  • whisper.cpp whisper-server v1.9.4 (Commit 927cfce34f31707e17f2bff35c349632fb9e2c3a)
  • Build: CUDA 12.6.3, -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES="52;61", statisch gelinkt
  • Image knaster/nex-whisper:v1.9.4-cu12.6, ID sha256:be4987ff63df…
  • Basis-Images per Digest gepinnt: nvidia/cuda:12.6.3-{devel,runtime}-ubuntu24.04
  • ffmpeg 6.1.1 für --convert

Modell: ggml-large-v3-turbo.bin (f16)

  • Quelle: HF ggerganov/whisper.cpp, Revision 5359861c…
  • sha256 1fc70f77…e2bc69, gegen Hugging Face geprüft
  • Feld model: beliebig, z. B. whisper oder nex-stt

Parameter:

  • -l de -bs 5 --convert --inference-path /v1/audio/transcriptions --tmp-dir /run/nex-whisper
  • --tmp-dir liegt auf tmpfs (512 MB)
  • ohne --print-realtime, Flash-Attention an
  • Nach jedem Start wird mit 1 s Stille aufgewärmt.

Eingangsformate: wav, mp3, ogg/opus, webm/opus und m4a/aac, alle über ffmpeg getestet.

response_format:

  • json → {"text": "…"}
  • text
  • verbose_json: Segmente mit words[].probability, avg_logprob, no_speech_prob, dazu language_probabilities
  • außerdem srt und vtt

Unbekannte Felder werden ignoriert. Geprüft mit model=gpt-4o-transcribe, timestamp_granularities[]=word, foo=bar und stream=false, Antwort jeweils 200.

PCM-Sample-Rate: entfällt; ffmpeg wandelt intern auf 16 kHz mono.

Messwerte (M4000, -bs 5):

Messung Ergebnis
10 s Audio, erster Aufruf nach Start und Aufwärmen 3,00 s (nach docker restart), 2,94 s (erster Aufruf der Abnahmeserie)
10 s Audio, Median aus 3 Läufen 2,94 s (Grenze 4 s, Ziel ≤ 3 s erreicht)
60 s Audio, erster Aufruf 8,63 s
60 s Audio, Median aus 3 Läufen 8,63 s (Grenze 12 s)
5 s Audio, von ops über das Netz 2,43 s
Start bis bereit (Modell im Cache, inkl. Aufwärmen) 4,1 s
VRAM 1965 MiB nach dem Laden und bei 10-s-Aufrufen, bis 2179 MiB nach 60-s-Audio, im Paralleltest kein weiterer Anstieg
RAM des Containers 286 MiB
Leerlauf der Karte P5, 17 W

Last mit 2 Erkennungen gleichzeitig (je 60 s):

  • Antworten nach 8,8 s und 17,5 s. whisper-server arbeitet sie nacheinander ab (globaler Mutex), die zweite wartet.
  • GPU-Last stieg auf 100 %, Mittel 78 %. Der Leerlauf (0 %) wurde separat gemessen; der erste Wert im Log (85 %) war noch Nachlauf.
  • Der VRAM steigt nicht, er bleibt bei 2179 MiB, weil der Kontext einmal geladen wird.

Autostart nach Neustart getestet: ja. Die VM wurde über Proxmox neu gestartet (qm reboot 252). 34 s nach dem Boot lieferten beide /health 200, die erste Erkennung danach war normal.

Auffälligkeiten:

  1. Gleichzeitige Anfragen laufen nacheinander (siehe Last).
  2. Mindestdauer etwa 2,3 s pro Aufruf, auch bei kurzen Clips. Der Encoder rechnet immer ein 30-s-Fenster.
  3. Format der json-Antwort: Der Text beginnt mit einem Leerzeichen und hat Zeilenumbrüche zwischen den Segmenten. Für Hermes ggf. strip() bzw. Umbrüche durch Leerzeichen ersetzen.
  4. Content-Type bei text: text/html; charset=utf-8.
  5. Qualität am synthetischen Testaudio:
    • Sauber: „Baubesprechung in Haslach ist am 4. November um 10 Uhr“.
    • „NEX“ wurde meist als „NX“ erkannt.
    • Im Teil mit der leisen Kerstin-Stimme gab es einzelne Fehler, z. B. „Baugüro“ und „Baulätung“.
    • Echte Aufnahmen und die Dialekt-Testsätze stehen in Task 3.3 an.
  6. Log: Es enthält nur den Upload-Dateinamen und die Audiolänge (z. B. Received request: t10.wav), keinen Text. Gegen den Testtext gegrepped: 0 Treffer.
    • ffmpeg läuft mit -loglevel error.
    • Log-Rotation: Treiber local, 2 × 5 MB.
  7. Temp-Dateien:
    • Nur im tmpfs, nach jeder Anfrage gelöscht; nach den Tests 0 Dateien.
    • Bei ffmpeg-Fehlern bleibt eine Upload-Datei liegen. Ein Aufräumer löscht Dateien älter als 10 min.
  8. Endpunkt POST /load: Er existiert (Modellwechsel). Erreichbar ist er nur von .29, und im Container liegt nur dieses eine Modell.
  9. Proxmox-Firewall: Abweichend vom Abgleich oben ist sie nicht aktiviert (Vorgabe). Es gilt nur ufw in der VM:
    • 8178/8179 nur von 192.168.100.29
    • SSH aus 192.168.100.0/24
    • sonst deny incoming
    • Beide Dienste laufen im Host-Netz, weil veröffentlichte Docker-Ports ufw umgehen würden.
    • Negativtest von ops (.173): ohne Regel Zeitüberschreitung auf beiden Ports.

Ausgabe (nex-tts)

Basis-URL: http://192.168.100.174:8179

  • Pfad: POST /v1/audio/speech
  • Zustand: GET /health → {"status":"ok","voices":[…],"default":"de_DE-thorsten-high"}
  • außerdem GET /v1/models und GET /v1/audio/voices

Knoten und Hardware: pve52, VM gpu-pve52, nur CPU. Die VM hat 4 Kerne (i7-7700); der Container ist auf 3 Kerne und 2 GB begrenzt.

Software:

  • eigener schlanker Wrapper: FastAPI 0.141.1, uvicorn 0.53.0, piper-tts 1.8.0 (GPL-3.0, eigener Dienst), onnxruntime 1.30.0, ffmpeg 5.1.9
  • Image knaster/nex-tts-piper:1.8.0, ID sha256:d9e65ee77836…
  • Basis python:3.12-slim-bookworm, per Digest gepinnt

Warum nicht speaches: Der Wrapper ist klein und gut zu prüfen. Er streamt satzweise, setzt die PCM-Header nach Vorgabe und schreibt weder Text noch Audio auf die Platte. Der bisherige knaster-tts_server konnte nur wav.

Modellname (model): beliebig, z. B. piper oder nex-tts.

Stimmen-IDs:

  • de_DE-thorsten-high: männlich, 22050 Hz, CC0, Standard
  • de_DE-kerstin-low: weiblich, 16000 Hz, Datensatz CC0
  • Dateien aus HF rhasspy/piper-voices, Revision c10ece1a…, sha256 geprüft.
  • Kurzformen thorsten und kerstin gehen ebenfalls.
  • Unbekannte Stimmen (z. B. alloy) fallen ohne Fehler auf die Standardstimme. Der Header X-Voice nennt die verwendete Stimme.

Weitere weibliche Stimmen, nicht genommen:

  • de_DE-ramona-low und de_DE-eva_k-x_low: M-AILABS, Lizenz „See URL“, kommerzielle Nutzung nicht belegt
  • de_DE-mls-medium: mehrere Sprecher

response_format:

  • Standard ist mp3 (audio/mpeg).
  • opus (Ogg, 48 kHz, audio/ogg), aac, flac und pcm werden gestreamt (chunked). Die Header kommen erst mit dem ersten Audioblock, deshalb misst TTFB echtes Audio.
  • wav kommt vollständig mit korrektem Header; das passt zu knaster bench tts und zum Canary.
  • speed (0,25–4) wird auf length_scale abgebildet.
  • Unbekannte Felder werden ignoriert.
  • input ist auf 5000 Zeichen begrenzt.

PCM-Sample-Rate: 24000 Hz für alle Stimmen, wie OpenAI.

  • Format: int16 LE, mono, umgerechnet per ffmpeg.
  • Header: X-Audio-Sample-Rate: 24000 und Content-Type: audio/pcm; rate=24000.
  • Mit PCM_SAMPLE_RATE=0 käme die native Rate der Stimme.

Messwerte (Auftragssatz, thorsten-high, je 3 Läufe):

Format TTFB gesamt Audio
mp3 0,67–0,91 s 1,42–1,68 s 5,25 s
pcm 0,72–0,87 s 1,48–1,62 s 5,31 s
opus 0,64–0,72 s 1,54–1,61 s 5,28 s
  • Von ops über das Netz: mp3 TTFB 0,72 s.
  • Erste Synthese nach einem Neustart (wav, 10 s Audio): 2,7 s gesamt. Die Stimmen werden beim Start aufgewärmt.
  • RAM: 616 MiB. Kein VRAM.

Autostart nach Neustart getestet: ja, wie bei der Erkennung.

Auffälligkeiten:

  1. Log: kein Access-Log, Level warning.
    • Gegen den Testtext gegrepped: 0 Treffer.
    • Piper meldet gelegentlich Missing phoneme from id map (ohne Text).
    • onnxruntime meldet beim Start eine harmlose Telemetrie-Warnung.
  2. Gleichzeitige Synthesen: höchstens 2 (TTS_PARALLEL). Die CPU teilt sich der Dienst mit whisper-server, das die CPU aber kaum nutzt.
  3. Ablageort: Laut Registry (tts-de) gehört Piper in den Infra-LXC. Vorerst läuft es hier.

Stufe 2 (nur geprüft, nichts installiert)

PyTorch auf der M4000:

  • In einem Wegwerf-Container geprüft: torch 2.9.1+cu126, get_arch_list() = sm_50, sm_60, sm_70, sm_75, sm_80, sm_86, sm_90.
  • Die M4000 (5, 2) rechnet eine Matrixmultiplikation korrekt.
  • 2.9.1 ist die letzte Version mit cu126-Wheels. Laut den Build-Skripten haben cu128/cu129/cu130 kein sm_5x/sm_6x mehr, also ist das die Obergrenze für Maxwell/Pascal.

Chatterbox Multilingual (ResembleAI):

  • Lizenz MIT (HF-Karte), Deutsch enthalten.
  • Läuft grundsätzlich mit PyTorch ≤ 2.9.1 auf sm_52, aber ohne Tensor-Cores in fp32.
  • Langsam erwartet. Nicht gemessen.

Kokoro-82M: VOICES.md listet keine deutsche Stimme, nur en, ja, zh, es, fr, hi, it und pt-br.

XTTS-v2 und Fish Speech: nicht geprüft, laut NEX-Team nicht kommerziell.

Empfehlung: Stufe 2 mit tts-de-hq (Qwen3-TTS) auf der Ada (Task 6.4) statt auf der M4000.

Notiz für Task 3.3 (Benchmark M4000, whisper)

Ergebnis:

  • CC 5.2 rechnet mit dem CUDA-12.6-Build. system_info zeigt CUDA : ARCHS = 520,610.
  • large-v3-turbo f16 mit -bs 5: 10 s Audio in 2,94 s (RTF 0,29), 60 s in 8,63 s (RTF 0,14).
  • Mit -nfa (Flash-Attention aus) sind es 3,21 s für 10 s, also bleibt Flash-Attention an.
  • Speicher: VRAM 2,2 GB, RAM 0,3 GB.

Noch offen:

  • P2000 nicht gemessen
  • Dialekt-Testsätze
  • primeline/whisper-large-v3-turbo-german: bräuchte eine ggml-Umwandlung
  • Strom unter Last

Offener Punkt Registry: Den Slot stt-de habe ich nicht angelegt.

  • SlotSpec.kind (core registry.py) kennt kein stt, Placement (placement.py) und Canary ebenfalls nicht.
  • Ohne Core-Änderung schlägt knaster validate fehl, und der Canary würde den Slot als Chat proben.
  • Gehört zu 3.3 bzw. 5.2, zusammen mit dem Umzug von tts-de.

Betrieb

Dateien im Repo:

  • deploy/compose/nex-speech/ (Compose, .env.example, Dockerfiles, piper/app.py)
  • Rolle platform/proxmox/ansible/roles/nex-speech
  • Playbook platform/proxmox/ansible/playbooks/nex-speech.yml, nur für gpu-pve52

Ausrollen von ops:

cd /root/cluster-knaster && git pull
cd platform/proxmox/tofu && . /root/.config/knaster/tofu.env && bash ../scripts/refresh-vm-access.sh
cd ../ansible && ansible-playbook playbooks/nex-speech.yml

Was die Rolle macht:

  • ufw-Regeln setzen und ufw einschalten
  • docker-buildx installieren
  • Modelle nach /srv/models/{whisper,piper} laden, mit sha256
  • Compose nach /opt/nex-speech kopieren, .env aus den Rollen-Variablen schreiben
  • bauen und starten, danach auf /health beider Dienste warten
  • Ein zweiter Lauf ändert nichts (changed=0).

Build:

  • Der erste whisper-Build dauert in der VM etwa 15 min.
  • Das devel-Image (11,5 GB) bleibt als Cache liegen. Freier Platz auf / danach: 18 GB.

Prüfen in der VM:

  • curl -s localhost:8178/health; curl -s localhost:8179/health
  • sudo docker compose -f /opt/nex-speech/docker-compose.yml ps
  • Logs mit sudo docker logs nex-stt bzw. nex-tts. Sie enthalten keine Texte.

Firewall in der VM:

  • sudo ufw status
  • Zum Testen von einem anderen Rechner eine Regel nur vorübergehend setzen: sudo ufw insert 1 allow from <IP> to any port 8178:8179 proto tcp, danach sudo ufw delete allow from <IP> to any port 8178:8179 proto tcp.
  • Weitere Compose-Stacks in dieser VM mit veröffentlichten Ports (ports:) umgehen ufw. Für Sprachdienste deshalb im Host-Netz bleiben.

Updates:

  • Ubuntu-Sicherheitsupdates laufen per unattended-upgrades. Der NVIDIA-Treiber ist gehalten.
  • Images sind gepinnt. Ein Wechsel geht nur bewusst über die Rollenvariablen nex_speech_env:
    • whisper: WHISPER_TAG und WHISPER_COMMIT gemeinsam
    • Piper: requirements.txt und PIPER_TTS_VERSION
  • Danach das Playbook erneut laufen lassen.

Parameter ändern: In nex_speech_env, z. B. WHISPER_EXTRA_ARGS: "-nfa" oder PCM_SAMPLE_RATE: "0", dann das Playbook laufen lassen.