JARVIS/config/set_ruido.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

60 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""Endurece la escucha para que no se dispare con ruido de fuera.
flatpak run --command=python3 io.github.qwersyk.Newelle//master \
~/COFRE/CODERS/JARVIS/config/set_ruido.py [--suave]
NO es reconocimiento de hablante: Newelle no distingue quien habla, no hay
nada de eso en el codigo. Esto solo sube el liston de que se considera voz.
Para que responda unicamente a una persona haria falta un modelo de huella
vocal (ECAPA, Resemblyzer) delante del STT, que es otro proyecto.
Las tres capas, de menos a mas efectiva:
1. la palabra clave, que ya filtra casi todo
2. estos umbrales
3. supresion de ruido en PipeWire (RNNoise), antes de que el audio llegue
a la app; esa vale para todo el sistema y no cuesta CPU a Newelle
Valores por defecto de Newelle: energia 300, VAD 1.
"""
import sys
from gi.repository import Gio
SCHEMA = "io.github.qwersyk.Newelle"
# vad-aggressiveness va de 0 a 3: cuanto descarta lo que no suena a voz.
DURO = {
"wakeword-energy-threshold": 800, # por debajo de esto ni escucha
"wakeword-vad-aggressiveness": 3,
}
SUAVE = {
"wakeword-energy-threshold": 500,
"wakeword-vad-aggressiveness": 2,
}
def main():
perfil = SUAVE if "--suave" in sys.argv else DURO
settings = Gio.Settings.new(SCHEMA)
print("antes:")
for clave in perfil:
print(f" {clave} = {settings.get_int(clave)}")
for clave, valor in perfil.items():
settings.set_int(clave, valor)
Gio.Settings.sync()
print("despues:")
for clave in perfil:
print(f" {clave} = {settings.get_int(clave)}")
ok = all(settings.get_int(c) == v for c, v in perfil.items())
print("verificado" if ok else "FALLO: no quedo como se pidio")
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())