"""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()