""" tts_sample.py — genera y reproduce una muestra de las 3 voces (lesky, monstruo, gnomos) llamando al endpoint Modal. Guarda los WAV en samples/ y los reproduce en orden (macOS `afplay`). Sirve para oír cómo quedan las clonaciones. Uso: python tools/tts_sample.py python tools/tts_sample.py "https://otra-url.modal.run" # URL distinta (opcional) OJO: si una voz suena neutra (no clonada), falta `modal deploy tools/tts_modal.py` tras añadir su .mp3 — los conds se cargan al arrancar el contenedor. """ import os import sys import time import json import subprocess import urllib.request URL = sys.argv[1] if len(sys.argv) > 1 else \ "https://vegagallegopablo--chatterbox-tts-turbo-tts-speak.modal.run" SAMPLES = { "lesky": "Heh heh heh! Welcome to my shop, little one. The treasure? Oh, it's mine.", "monstruo": "So... another little challenger crawls into my alley. How adorable. I will crush you.", "gnomos": "Wait, wait, no! It was MY turn to be on top! Move over, you're squashing my hat!", } OUT_DIR = "samples" os.makedirs(OUT_DIR, exist_ok=True) def synth(text, voice): d = json.dumps({"text": text, "voice": voice}).encode() req = urllib.request.Request(URL, data=d, headers={"Content-Type": "application/json"}) t = time.time() with urllib.request.urlopen(req, timeout=180) as r: audio = r.read() return audio, time.time() - t for voice, text in SAMPLES.items(): print(f"\n🎙 {voice}: «{text}»") try: audio, dt = synth(text, voice) except Exception as e: print(f" ❌ fallo: {e}") continue path = os.path.join(OUT_DIR, f"sample_{voice}.wav") with open(path, "wb") as f: f.write(audio) print(f" ✅ {len(audio)} bytes · {dt:.2f}s · {path}") try: subprocess.run(["afplay", path]) # suena por los altavoces (macOS) except FileNotFoundError: print(" (sin afplay: reprodúcelo a mano)") print(f"\nListo. WAV en {OUT_DIR}/")