Nucleo propio: oye con whisper.cpp, piensa con un modelo de Ollama, habla con Piper, y hace RAG sobre los apuntes del usuario. 100% local, sin cuentas ni claves. Escrito bajo una restriccion dura, 4 GB de VRAM: el cerebro y whisper comparten tarjeta y solo caben porque estan dimensionados para ello. El RAG usa embeddings estaticos con busqueda hibrida; la voz clonada se sirve de una cache de frases. Incluye instalador (install.sh), requisitos, y documentacion del stack, del manejo de root y de las acciones. Los apuntes indexados y el diario NO se incluyen: son privados y el .gitignore los bloquea.
38 lines
1.6 KiB
Python
38 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
# Prueba de clonacion con F5-TTS (modelo espanol jpgallegoar/F5-Spanish).
|
|
# Descarga el checkpoint espanol (abierto) y sintetiza las mismas 3 frases que
|
|
# XTTS, para comparar de oido. Referencia: ref/jarvis_ref_corto.wav (12s).
|
|
import os, sys, time
|
|
DISPOSITIVO = sys.argv[1] if len(sys.argv) > 1 else "cuda"
|
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
|
REF = os.path.join(BASE, "ref", "jarvis_ref_corto.wav")
|
|
SALIDA = os.path.join(BASE, "ref", "muestras")
|
|
os.makedirs(SALIDA, exist_ok=True)
|
|
|
|
FRASES = [
|
|
"Buenas noches, señor. Todo está listo.",
|
|
"He encontrado tres ficheros que coinciden. ¿Cuál abro?",
|
|
"El procesador está a sesenta y un grados y quedan cuarenta gigabytes de memoria.",
|
|
]
|
|
|
|
print("descargando modelo espanol F5...", flush=True)
|
|
from huggingface_hub import hf_hub_download
|
|
ckpt = hf_hub_download("jpgallegoar/F5-Spanish", "model_1250000.safetensors")
|
|
vocab = hf_hub_download("jpgallegoar/F5-Spanish", "vocab.txt")
|
|
print(f" ckpt: {ckpt}", flush=True)
|
|
|
|
print(f"cargando F5-TTS en {DISPOSITIVO}...", flush=True)
|
|
t0 = time.time()
|
|
from f5_tts.api import F5TTS
|
|
# El modelo espanol se entreno sobre la arquitectura F5TTS_Base.
|
|
f5 = F5TTS(model="F5TTS_Base", ckpt_file=ckpt, vocab_file=vocab, device=DISPOSITIVO)
|
|
print(f" cargado en {time.time()-t0:.1f}s", flush=True)
|
|
|
|
for i, frase in enumerate(FRASES, 1):
|
|
t0 = time.time()
|
|
dst = os.path.join(SALIDA, f"f5_{i}.wav")
|
|
f5.infer(ref_file=REF, ref_text="", gen_text=frase, file_wave=dst,
|
|
remove_silence=True)
|
|
print(f" [{i}] {time.time()-t0:5.1f}s -> {dst}", flush=True)
|
|
print(f" «{frase}»", flush=True)
|
|
print("listo.", flush=True)
|