# Installation ## Docker Install 1) `curl -fsSL https://get.Docker.com -o get-Docker.sh` 2) `sudo sh get-Docker.sh` 3) `sudo usermod -aG docker $USER` 4) `newgrp docker` ## Pfade 1) Anlegen des Ordners: `mkdir -p ~/vosk-mqtt` 2) Reinwechseln: `cd /home/pi/vosk-mqtt/` 3) Dockerfile anlegen: `nano Dockerfile` und mit folgendem Inhalt füllen: ``` FROM python:3.11-slim ENV DEBIAN_FRONTEND=noninteractive # Audio-Bibliotheken für sounddevice/PortAudio + ALSA-Tools # UND libatomic1 für Vosk (fehlt im slim-Image) RUN apt-get update && apt-get install -y --no-install-recommends \ portaudio19-dev \ alsa-utils \ libatomic1 \ && rm -rf /var/lib/apt/lists/* # Python-Pakete: Vosk, Sounddevice, Paho-MQTT RUN pip install --no-cache-dir \ vosk \ sounddevice \ paho-mqtt WORKDIR /app # Standard-Umgebungsvariablen ENV MQTT_HOST=mosquitto \ MQTT_PORT=1883 \ MQTT_TOPIC=klassengelaber \ VOSK_LANG=de \ DEVICE_ID=-1 COPY stt_mqtt.py . CMD ["python", "stt_mqtt.py"] ``` 4) Python-Skript anlegen: `nano stt_mqtt.py` und mit folgendem Inhalt füllen ``` #!/usr/bin/env python3 import os import sys import json import queue import sounddevice as sd from vosk import Model, KaldiRecognizer import paho.mqtt.client as mqtt # --- Konfiguration aus Umgebungsvariablen --- MQTT_HOST = os.getenv("MQTT_HOST", "localhost") MQTT_PORT = int(os.getenv("MQTT_PORT", "1883")) MQTT_TOPIC = os.getenv("MQTT_TOPIC", "klassengelaber") VOSK_LANG = os.getenv("VOSK_LANG", "de") DEVICE_ID = int(os.getenv("DEVICE_ID", "-1")) # Ideale Sample-Rate für Vosk (Pi-schnell) VOSK_SAMPLERATE = 16000 q = queue.Queue() def audio_callback(indata, frames, time, status): """Callback wird von sounddevice für jeden Audio-Block aufgerufen.""" if status: print(status, file=sys.stderr) q.put(bytes(indata)) def main(): # --- MQTT-Client aufsetzen --- client = mqtt.Client() client.connect(MQTT_HOST, MQTT_PORT, 60) client.loop_start() # --- Audio-Device bestimmen --- if DEVICE_ID >= 0: device = DEVICE_ID else: device = None # default device device_info = sd.query_devices(device, "input") native_samplerate = int(device_info["default_samplerate"]) print(f"Native Sample-Rate des Mikrofon: {native_samplerate} Hz") # Wir nutzen VOSK_SAMPLERATE (16000 Hz) für Vosk. # sounddevice konvertiert automatisch, wenn wir samplerate=VOSK_SAMPLERATE setzen. samplerate = VOSK_SAMPLERATE print(f"Nutze Eingabegerät: {device_info['name']} @ {samplerate} Hz (für Vosk)") # --- Vosk-Modell laden --- print(f"Lade Vosk-Modell für Sprache: {VOSK_LANG}") model = Model(lang=VOSK_LANG) rec = KaldiRecognizer(model, samplerate) # --- Audio-Stream öffnen mit angepassten Parametern --- # blocksize=4000 -> 4000 Samples @ 16000 Hz = 250 ms # latency="high" -> mehr Buffer, weniger Overflow with sd.RawInputStream( samplerate=samplerate, blocksize=4000, device=device, dtype="int16", channels=1, latency="high", callback=audio_callback, ): print("#" * 80) print("Live-Transkription läuft. Strg+C zum Beenden.") print("#" * 80) try: while True: data = q.get() if rec.AcceptWaveform(data): # Finales Ergebnis res = json.loads(rec.Result()) text = res.get("text", "").strip() if text: print(f"FINAL: {text}") client.publish(MQTT_TOPIC, payload=text, qos=0, retain=False) else: # Optional: Teil-Ergebnis pres = json.loads(rec.PartialResult()) ptext = pres.get("partial", "").strip() if ptext: print(f"PARTIAL: {ptext}", end="\r") except KeyboardInterrupt: print("\nStoppe…") finally: client.loop_stop() if __name__ == "__main__": main() ``` ## Docker build Bauen des Container-Images imd Projektordner `docker build -t vosk-mqtt .` ## Docker run Ausführen des Docker-Containers (ggfs. später per Systemdienst starten!) ``` docker run --rm --name vosk-mqtt --device /dev/snd:/dev/snd --group-add audio -e MQTT_HOST=192.168.213.12 -e MQTT_PORT=1883 -e MQTT_TOPIC=fi24b/klassengelaber -e VOSK_LANG=de -e DEVICE_ID=-1 vosk-mqtt:latest ```