README.md hinzugefügt
This commit is contained in:
151
README.md
Normal file
151
README.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# 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
|
||||
```
|
||||
Reference in New Issue
Block a user