Arreglado el boton PARAR y repaso de portabilidad
PARAR no pausaba de verdad: el HUD estaba entero para el estado "parado" pero el backend nunca mandaba el campo "parar" en el evento controles, asi que el boton no alternaba ni pausaba la escucha. Ahora pausa (el bucle de escucha descarta el audio en pausa) y alterna a "reanudar". Portabilidad (para que encaje en otros portatiles y torres, no solo en el equipo del autor): - microfono: pw-record / parec / arecord (PipeWire, PulseAudio o ALSA) - whisper: binario del build local o del PATH; modelos por JARVIS_WHISPER_MODELOS o busqueda en varios sitios; CUDA en LD_LIBRARY_PATH solo si existe - README: la tabla de portabilidad refleja audio y whisper
This commit is contained in:
parent
55e967b940
commit
a0b9afe2f9
5 changed files with 102 additions and 23 deletions
|
|
@ -26,6 +26,7 @@ con tres agujeros, y aqui se cierran los tres:
|
|||
"""
|
||||
import collections
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
|
|
@ -50,13 +51,31 @@ MAXIMO_S = 25.0
|
|||
|
||||
|
||||
def _grabador(fuente=None):
|
||||
"""La orden para capturar crudo a la salida estandar."""
|
||||
if fuente:
|
||||
pw = ["pw-record", "--target", fuente]
|
||||
else:
|
||||
pw = ["pw-record"]
|
||||
return pw + ["--rate", str(FRECUENCIA), "--channels", str(CANALES),
|
||||
"--format", "s16", "-"]
|
||||
"""La orden para capturar crudo (s16 mono) a la salida estandar.
|
||||
|
||||
Se prueba pw-record (PipeWire), parec (PulseAudio) y arecord (ALSA), en ese
|
||||
orden, la primera que exista en el sistema. Asi el microfono funciona en
|
||||
cualquier Linux —una torre con PulseAudio, un equipo con solo ALSA— y no
|
||||
solo donde hay PipeWire. Los tres sacan el mismo crudo (s16 little-endian,
|
||||
mono, 16 kHz) por la salida estandar, que es lo que lee el detector."""
|
||||
r, c = str(FRECUENCIA), str(CANALES)
|
||||
if shutil.which("pw-record"):
|
||||
cmd = ["pw-record", "--rate", r, "--channels", c, "--format", "s16"]
|
||||
if fuente:
|
||||
cmd += ["--target", fuente]
|
||||
return cmd + ["-"]
|
||||
if shutil.which("parec"):
|
||||
cmd = ["parec", "--rate=" + r, "--channels=" + c, "--format=s16le"]
|
||||
if fuente:
|
||||
cmd += ["-d", fuente]
|
||||
return cmd
|
||||
if shutil.which("arecord"):
|
||||
cmd = ["arecord", "-q", "-r", r, "-c", c, "-f", "S16_LE", "-t", "raw"]
|
||||
if fuente:
|
||||
cmd += ["-D", fuente]
|
||||
return cmd
|
||||
# ninguno instalado: se devuelve pw-record para que el fallo sea claro
|
||||
return ["pw-record", "--rate", r, "--channels", c, "--format", "s16", "-"]
|
||||
|
||||
|
||||
class Captura:
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import atexit
|
|||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
|
|
@ -64,13 +65,40 @@ import urllib.error
|
|||
import urllib.request
|
||||
|
||||
RAIZ = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
BINARIO = os.path.join(RAIZ, "voz", "whisper-cuda", "whisper.cpp", "build", "bin",
|
||||
"whisper-server")
|
||||
MODELOS = os.path.expanduser(
|
||||
"~/.var/app/io.github.qwersyk.Newelle/config/models/whisper/whisper.cpp/models")
|
||||
|
||||
# Las libs de ggml estan al lado del binario y CUDA en /usr/local. Fuera del
|
||||
# flatpak esto es una linea; dentro era media pagina de flatpak-spawn.
|
||||
# El binario de whisper-server: el build local del repo si esta compilado, y si
|
||||
# no, el que haya en el PATH (asi vale un whisper.cpp instalado del sistema, en
|
||||
# cualquier distro). Cada quien lo compila para su plataforma —CUDA, ROCm,
|
||||
# Metal o CPU—; aqui solo se busca donde esta.
|
||||
_LOCAL = os.path.join(RAIZ, "voz", "whisper-cuda", "whisper.cpp", "build", "bin",
|
||||
"whisper-server")
|
||||
BINARIO = _LOCAL if os.path.exists(_LOCAL) else (shutil.which("whisper-server") or _LOCAL)
|
||||
|
||||
|
||||
def _dir_modelos():
|
||||
"""Donde estan los ggml-*.bin. Se puede fijar con JARVIS_WHISPER_MODELOS;
|
||||
si no, se prueba junto al build, el sitio estandar del usuario, y por
|
||||
compatibilidad la ruta del antiguo flatpak. Gana el primero que TENGA un
|
||||
modelo de verdad —el dir del source de whisper.cpp existe pero suele estar
|
||||
vacio, asi que mirar solo si el dir existe elegiria mal."""
|
||||
import glob
|
||||
env = os.environ.get("JARVIS_WHISPER_MODELOS")
|
||||
if env:
|
||||
return os.path.expanduser(env)
|
||||
for c in (os.path.join(os.path.dirname(_LOCAL), "..", "..", "models"),
|
||||
"~/.local/share/jarvis/whisper/models",
|
||||
"~/.var/app/io.github.qwersyk.Newelle/config/models/whisper/whisper.cpp/models"):
|
||||
ruta = os.path.normpath(os.path.expanduser(c))
|
||||
if glob.glob(os.path.join(ruta, "ggml-*.bin")):
|
||||
return ruta
|
||||
return os.path.expanduser("~/.local/share/jarvis/whisper/models")
|
||||
|
||||
|
||||
MODELOS = _dir_modelos()
|
||||
|
||||
# Las libs de CUDA, solo si estan: en un equipo AMD o CPU no hay /usr/local/cuda,
|
||||
# y meterlo en LD_LIBRARY_PATH a la fuerza no aporta nada. Se añade mas abajo
|
||||
# solo si el directorio existe.
|
||||
LIBS = "/usr/local/cuda/lib64"
|
||||
|
||||
# Un prompt largo no ayuda: Whisper empieza a "oir" esas palabras donde no las
|
||||
|
|
@ -223,8 +251,10 @@ class Oido:
|
|||
if not self.gpu:
|
||||
orden.append("--no-gpu")
|
||||
|
||||
entorno = {**os.environ,
|
||||
"LD_LIBRARY_PATH": LIBS + ":" + os.environ.get("LD_LIBRARY_PATH", "")}
|
||||
# CUDA en LD_LIBRARY_PATH solo si existe; en AMD/CPU no estorba.
|
||||
entorno = dict(os.environ)
|
||||
if os.path.isdir(LIBS):
|
||||
entorno["LD_LIBRARY_PATH"] = LIBS + ":" + os.environ.get("LD_LIBRARY_PATH", "")
|
||||
self._proc = subprocess.Popen(
|
||||
orden, env=entorno, cwd=os.path.dirname(BINARIO),
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue