Docker & Infrastruktur — OpenClaw Image fix, libportaudio2, aria.env.example

Wake-Word Fix — openwakeword API-Bug behoben
get-voices.sh — neues Script + README-Schritt
This commit is contained in:
2026-03-10 14:08:28 +01:00
parent c67da1d085
commit afcd45d32f
11 changed files with 114 additions and 17 deletions
+1
View File
@@ -9,6 +9,7 @@ FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
ffmpeg \
libsndfile1 \
libportaudio2 \
pulseaudio-utils \
alsa-utils \
&& rm -rf /var/lib/apt/lists/*
+35 -12
View File
@@ -296,22 +296,45 @@ class STTEngine:
class WakeWordDetector:
"""Erkennt das Wake-Word 'aria' im Audio-Stream."""
"""Erkennt das Wake-Word im Audio-Stream.
WAKE_WORD = "aria"
Nutzt ein Custom-Modell aus /voices/wake_aria.onnx falls vorhanden,
sonst das eingebaute 'hey_jarvis' als Fallback.
"""
CUSTOM_MODEL_PATH = "/voices/wake_aria.onnx"
FALLBACK_MODEL = "hey_jarvis"
THRESHOLD = 0.5
def __init__(self) -> None:
self.model: Optional[WakeWordModel] = None
self.wake_word_key: str = ""
def initialize(self) -> None:
"""Laedt das Wake-Word-Modell."""
logger.info("Lade Wake-Word-Modell...")
self.model = WakeWordModel(
wakeword_models=[self.WAKE_WORD],
inference_framework="onnx",
)
logger.info("Wake-Word-Modell geladen (Trigger: '%s')", self.WAKE_WORD)
custom_path = Path(self.CUSTOM_MODEL_PATH)
if custom_path.exists():
# Custom "aria" Modell vorhanden
self.model = WakeWordModel(
wakeword_models=[str(custom_path)],
)
self.wake_word_key = custom_path.stem
logger.info("Custom Wake-Word-Modell geladen: %s", custom_path)
else:
# Fallback auf eingebautes Modell
self.model = WakeWordModel()
self.wake_word_key = self.FALLBACK_MODEL
logger.warning(
"Kein Custom-Modell (%s) — nutze Fallback '%s'",
self.CUSTOM_MODEL_PATH,
self.FALLBACK_MODEL,
)
logger.info(
"Tipp: Custom Wake-Word trainieren → "
"https://github.com/dscripka/openWakeWord#training-new-models"
)
def detect(self, audio_chunk: np.ndarray) -> bool:
"""Prueft ob das Wake-Word im Audio-Chunk enthalten ist.
@@ -328,10 +351,10 @@ class WakeWordDetector:
prediction = self.model.predict(audio_chunk)
# openwakeword gibt Scores pro Modell zurueck
for key, score in prediction.items():
if score > self.THRESHOLD:
logger.info("Wake-Word erkannt! (Score: %.2f)", score)
return True
score = prediction.get(self.wake_word_key, 0)
if score > self.THRESHOLD:
logger.info("Wake-Word erkannt! (Score: %.2f)", score)
return True
return False
@@ -689,7 +712,7 @@ class ARIABridge:
async def audio_loop(self) -> None:
"""Wake-Word erkennen, aufnehmen, transkribieren, an aria-core senden."""
logger.info("Audio-Schleife gestartet — warte auf Wake-Word '%s'...", WakeWordDetector.WAKE_WORD)
logger.info("Audio-Schleife gestartet — warte auf Wake-Word '%s'...", self.wake_word.wake_word_key)
loop = asyncio.get_event_loop()