151 lines
4.4 KiB
Markdown
151 lines
4.4 KiB
Markdown
# 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
|
|
``` |