2026-06-08 10:11:20 +00:00
2026-06-08 10:11:20 +00:00

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"]
  1. 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
Description
No description provided
Readme 25 KiB