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:
@@ -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
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user