JARVIS/config/muestra_voz.py
sito 8e4bc8ad94 JARVIS: asistente de voz local para Linux
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.
2026-08-16 15:34:37 +02:00

66 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Genera muestras de la voz JARVIS: seca y con tratamiento.
Se ejecuta DENTRO del flatpak, que es donde viven Kokoro y ffmpeg:
flatpak run --command=python3 io.github.qwersyk.Newelle//master \
~/COFRE/CODERS/JARVIS/config/muestra_voz.py
Sirve para juzgar la voz de oido antes de montar una conversacion entera,
y para comparar el efecto del filtro (que es la mitad del caracter JARVIS).
Deja los wav en ~/COFRE/CODERS/JARVIS/muestras/.
"""
import os
import subprocess
import sys
sys.path.insert(0, "/app/share/newelle")
# Los modulos que Newelle instala bajo demanda (kokoro-onnx, soundfile...) no
# van al site-packages del sistema sino a config/pip, que la app añade al
# sys.path al arrancar. Un script suelto tiene que hacerlo a mano.
sys.path.insert(0, os.path.expanduser(
"~/.var/app/io.github.qwersyk.Newelle/config/pip"))
from gi.repository import Gio # noqa: E402
from newelle.handlers.tts.kokoro_handler import KokoroTTSHandler # noqa: E402
from newelle.handlers.tts.tts import jarvis_audio_filter # noqa: E402
FRASE = ("Good evening, sir. All systems are running locally. "
"You have 846 gigabytes free and the GPU is idle.")
SALIDA = os.path.expanduser("~/COFRE/CODERS/JARVIS/muestras")
CONFIG = os.path.expanduser("~/.var/app/io.github.qwersyk.Newelle/config")
def main():
os.makedirs(SALIDA, exist_ok=True)
settings = Gio.Settings.new("io.github.qwersyk.Newelle")
handler = KokoroTTSHandler(settings, os.path.join(CONFIG, "models"))
if not handler.is_installed():
print("Kokoro no instalado, instalando (pip + modelos, tarda)...")
handler.install()
print("instalado")
voz = handler.get_current_voice()
print(f"voz: {voz}")
seca = os.path.join(SALIDA, "jarvis_seca.wav")
handler.save_audio(FRASE, seca)
print(f"seca: {seca} ({os.path.getsize(seca)} bytes)")
filtro = jarvis_audio_filter()
tratada = os.path.join(SALIDA, "jarvis_tratada.wav")
subprocess.run(
["ffmpeg", "-hide_banner", "-loglevel", "error",
"-i", seca, "-af", filtro, "-y", tratada],
check=True,
)
print(f"tratada: {tratada} ({os.path.getsize(tratada)} bytes)")
print(f"filtro: {filtro}")
return 0
if __name__ == "__main__":
sys.exit(main())