lexia / scripts /validar_audio_local.py
davidhf2026's picture
LexIA 2026-09-16 19:37
efe917e
Raw History Blame Contribute Delete
2.21 kB
"""Ejecuta TTS y STT locales sobre un audio efímero, sin robot ni red.
python -m scripts.validar_audio_local
Sintetiza una frase con Piper y se la da a transcribir a faster-whisper. Es la
forma de comprobar la voz **sin micrófono**: si lo que vuelve se parece a lo que
salió, las dos mitades del audio funcionan. El audio no toca el disco.
"""
from __future__ import annotations
import json
import time
import numpy as np
from lexia.core.paths import runtime_root
from lexia.legal.local_asr import LocalWhisperTranscriber
from lexia.legal.voice import cargar_voz
PHRASE = "La documentación técnica es obligatoria para los sistemas de inteligencia artificial de alto riesgo."
def main() -> None:
target = runtime_root() / "reports" / "validacion-audio-local.json"
target.parent.mkdir(parents=True, exist_ok=True)
started = time.perf_counter()
try:
voice = cargar_voz(descargar=False)
tts_started = time.perf_counter()
chunks = list(voice.sintetizar(PHRASE))
tts_seconds = time.perf_counter() - tts_started
audio = np.concatenate(chunks) if chunks else np.empty(0, dtype=np.int16)
if not audio.size:
raise RuntimeError("Piper no produjo audio")
stt_started = time.perf_counter()
transcript = LocalWhisperTranscriber().transcribe(audio)
payload: dict[str, object] = {
"outcome": "ok",
"tts_input": PHRASE,
"tts_seconds": round(tts_seconds, 3),
"audio_samples": int(audio.size),
"audio_seconds": round(audio.size / 16_000, 3),
"stt_output": transcript,
"stt_seconds": round(time.perf_counter() - stt_started, 3),
"total_seconds": round(time.perf_counter() - started, 3),
}
except Exception as exc:
payload = {
"outcome": "failed",
"error_type": type(exc).__name__,
"error": str(exc),
"total_seconds": round(time.perf_counter() - started, 3),
}
raise
finally:
target.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
print(target)
if __name__ == "__main__":
main()