v2 - STT via Whisper for more precision and if nor available, twist to Vox

This commit is contained in:
pporcheret
2026-10-27 16:44:39 +01:00
parent 5ccb0a48c2
commit 5f82b1bdf2
49 changed files with 4667 additions and 329 deletions
+28
View File
@@ -302,6 +302,12 @@ def listen_once(stop_event: Optional[threading.Event] = None,
model_path = os.getenv("VOSK_MODEL_PATH", "")
sample_rate = int(os.getenv("VOSK_SAMPLE_RATE", "16000"))
# ALFRED_WYOMING_WHISPER_STT_V1: Vosk segments the utterance and
# provides UI partials. Wyoming Whisper replaces only its final transcript.
stt_engine = os.getenv("STT_ENGINE", "vosk").strip().lower()
wyoming_enabled = stt_engine in ("wyoming", "wyoming_whisper", "whisper")
wyoming_audio = bytearray()
wyoming_max_bytes = max(16000, int(os.getenv("STT_MAX_AUDIO_SECONDS", "30")) * sample_rate * 2)
if not model_path or not os.path.exists(model_path):
return STTResult(error=f"Modèle Vosk introuvable: {model_path}")
try:
@@ -311,6 +317,9 @@ def listen_once(stop_event: Optional[threading.Event] = None,
return STTResult(error=f"Init Vosk: {exc}")
def process(data: bytes) -> Optional[str]:
# ALFRED_WYOMING_WHISPER_STT_V1: retain the exact PCM heard by Vosk.
if wyoming_enabled and len(wyoming_audio) < wyoming_max_bytes:
wyoming_audio.extend(data[:wyoming_max_bytes - len(wyoming_audio)])
if on_level and data:
try:
a = np.frombuffer(data, dtype=np.int16).astype(np.float32)
@@ -321,6 +330,25 @@ def listen_once(stop_event: Optional[threading.Event] = None,
if rec.AcceptWaveform(data):
text = (json.loads(rec.Result() or "{}").get("text") or "").strip()
if text:
if wyoming_enabled and wyoming_audio:
# ALFRED_WYOMING_WHISPER_STT_V1: remote final STT, local fallback.
try:
from services.wyoming_stt import transcribe_pcm
whisper_text = transcribe_pcm(
bytes(wyoming_audio),
host=os.getenv("WYOMING_WHISPER_HOST", "192.168.1.13"),
port=int(os.getenv("WYOMING_WHISPER_PORT", "10300")),
language=os.getenv("WYOMING_WHISPER_LANGUAGE", "fr"),
sample_rate=sample_rate,
connect_timeout=float(os.getenv("WYOMING_WHISPER_CONNECT_TIMEOUT", "3")),
response_timeout=float(os.getenv("WYOMING_WHISPER_TIMEOUT", "20")),
)
if whisper_text:
print(f"[ALFRED STT] Whisper final : {whisper_text!r} (Vosk : {text!r})", flush=True)
return whisper_text
print("[ALFRED STT] Whisper réponse vide, secours Vosk", flush=True)
except Exception as exc:
print(f"[ALFRED STT] Whisper indisponible, secours Vosk : {exc}", flush=True)
return text
elif on_partial:
partial = json.loads(rec.PartialResult() or "{}").get("partial", "")