#!/usr/bin/env python3 """¿El clon falla porque las frases son cortas? La referencia son 25 segundos de habla seguida. Lo que JARVIS dice de verdad son acuses de segundo y medio: "Voy, señor". XTTS arranca cada generacion sin contexto, y en frase corta no le da tiempo a asentar la voz antes de terminar. Si es eso, el parecido deberia subir con la longitud del texto — y la solucion no seria tocar parametros sino generar mas largo y recortar. Se mide con repeticiones porque XTTS muestrea: una sola pasada por longitud seria ruido, que es el error que ya se cometio dos veces hoy. python prueba_longitud.py [cuda|cpu] [repeticiones] """ import os import statistics import sys import tempfile import torch DISPOSITIVO = sys.argv[1] if len(sys.argv) > 1 else "cuda" REPES = int(sys.argv[2]) if len(sys.argv) > 2 else 4 BASE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, BASE) from clonador import CONDICIONADO, GENERACION, referencias os.environ.setdefault("COQUI_TOS_AGREED", "1") PATRON = os.path.join(BASE, "ref", "jarvis_lento_b.wav") MEDIR = dict(gpt_cond_len=30, gpt_cond_chunk_len=6, max_ref_length=30) # mismo registro, longitud creciente TEXTOS = [ ("muy corta (~1s)", "Voy, señor."), ("corta (~2s)", "Enseguida, señor. Ahora mismo."), ("media (~5s)", "Enseguida, señor. He revisado el sistema y todo está en orden."), ("larga (~10s)", "Enseguida, señor. He revisado el sistema y todo está en orden. " "La temperatura ronda los sesenta y tres grados y quedan " "cuarenta y un gigabytes de memoria libre."), ("muy larga (~20s)", "Enseguida, señor. He revisado el sistema y todo está en orden. " "La temperatura ronda los sesenta y tres grados y quedan " "cuarenta y un gigabytes de memoria libre. El disco principal " "va al sesenta por ciento y no he detectado ningún proceso " "anómalo. ¿Desea que ejecute el análisis de red ahora o " "prefiere que espere?"), ] def main(): from TTS.api import TTS import soundfile as sf api = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(DISPOSITIVO) modelo = api.synthesizer.tts_model def emb(ruta): _, e = modelo.get_conditioning_latents(audio_path=[ruta], **MEDIR) return e patron = emb(PATRON) def parecido(ruta): return float(torch.nn.functional.cosine_similarity( patron.squeeze().float(), emb(ruta).squeeze().float(), dim=0)) gpt, hablante = modelo.get_conditioning_latents( audio_path=referencias(), **CONDICIONADO) print(f" {REPES} repeticiones por longitud · referencia a batir: 0.84-0.95\n") print(f" {'texto':18s} {'dur':>6s} {'parecido':>9s} {'desv':>7s}") print(" " + "-" * 45) with tempfile.TemporaryDirectory() as tmp: for etiqueta, texto in TEXTOS: puntos, duraciones = [], [] for r in range(REPES): out = modelo.inference( text=texto, language="es", gpt_cond_latent=gpt, speaker_embedding=hablante, enable_text_splitting=False, **GENERACION) d = os.path.join(tmp, f"{len(puntos)}_{r}.wav") sf.write(d, out["wav"], 24000) duraciones.append(len(out["wav"]) / 24000) puntos.append(parecido(d)) print(f" {etiqueta:18s} {statistics.mean(duraciones):5.1f}s " f"{statistics.mean(puntos):9.4f} {statistics.pstdev(puntos):7.4f}", flush=True) if __name__ == "__main__": main()