#!/usr/bin/env bash # El oido del verde: micro -> whisper LOCAL -> el agente. Nada sale de la maquina. # # ./escucha-verde.sh pulsar-para-hablar: graba, para con Enter, responde # ./escucha-verde.sh --habla ademas dice la respuesta en voz alta (voz del verde) # ./escucha-verde.sh --seguido no para: encadena turnos hasta Ctrl-C # # Por que existe: el TUI de Hermes no tiene microfono, y su STT nativo transcribe # notas de voz de mensajeria (Telegram/Discord), que saldrian de la maquina. Este # puente graba en local (pw-record/parec/arecord), transcribe con faster-whisper # 'small' (escucha_transcribe.py, en CPU) y se lo pasa al agente con `hermes chat`. # # AVISO honesto: el 4B verde con 65k de contexto y media red en CPU tarda minutos # por turno. Esto sirve para PROBAR que el verde escucha, no como asistente de # diario: para eso esta el naranja. La palanca de velocidad (KV cache q8_0) toca # el servicio de ollama y afectaria al naranja, asi que no se aplica aqui. set -uo pipefail RAIZ=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) VERDE=$RAIZ/verde PY=$RAIZ/nucleo/venv/bin/python [ -x "$PY" ] || PY=$(command -v python3) HERMES="$HOME/.hermes/hermes-agent/venv/bin/python $HOME/.hermes/hermes-agent/hermes" TMP=${TMPDIR:-/tmp}/jarvis-verde-escucha mkdir -p "$TMP" HABLA=0; SEGUIDO=0 for a in "$@"; do case "$a" in --habla) HABLA=1 ;; --seguido) SEGUIDO=1 ;; esac done verde() { printf '\033[32m%s\033[0m\n' "$1"; } gris() { printf '\033[90m%s\033[0m\n' "$1"; } # Devuelve el comando de grabacion a WAV 16 kHz mono, segun lo que haya. grabador_a() { local wav=$1 if command -v pw-record >/dev/null; then echo "pw-record --rate 16000 --channels 1 --format s16 $wav" ;; elif command -v arecord >/dev/null; then echo "arecord -q -r 16000 -c 1 -f S16_LE -t wav $wav" ;; elif command -v parec >/dev/null; then echo "parec --rate=16000 --channels=1 --format=s16le --file-format=wav $wav" ;; else echo ""; fi } un_turno() { local wav=$TMP/turno.wav; rm -f "$wav" local cmd; cmd=$(grabador_a "$wav") if [ -z "$cmd" ]; then echo "No hay grabador (instala pipewire-utils, alsa-utils o pulseaudio-utils)"; return 1 fi verde "🎙 Habla ahora... (Enter para parar)" $cmd >/dev/null 2>&1 & local pid=$! read -r _ /dev/null; wait "$pid" 2>/dev/null [ -s "$wav" ] || { echo "no se grabo nada"; return 1; } gris "…transcribiendo (local)…" local texto; texto=$("$PY" "$VERDE/escucha_transcribe.py" "$wav" 2>/dev/null) if [ -z "$texto" ]; then echo "no se entendio nada"; return 1; fi printf '\033[36m> %s\033[0m\n' "$texto" gris "…pensando (4B verde, puede tardar)…" local resp; resp=$($HERMES chat --reasoning none -q "$texto" 2>/dev/null) printf '\033[32m%s\033[0m\n' "$resp" if [ "$HABLA" = 1 ] && [ -n "$resp" ]; then local txt=$TMP/resp.txt wavr=$TMP/resp.wav printf '%s' "$resp" > "$txt" "$VERDE/voz-verde.sh" "$wavr" "$txt" >/dev/null 2>&1 && { command -v pw-play >/dev/null && pw-play "$wavr" 2>/dev/null || \ command -v aplay >/dev/null && aplay -q "$wavr" 2>/dev/null || true } fi } if [ "$SEGUIDO" = 1 ]; then echo "Modo seguido. Ctrl-C para salir." while true; do un_turno || true; echo; done else un_turno fi