#!/usr/bin/env bash # Que el verde hable, y que hable IGUAL que el naranja. # # No es un detalle estetico. Si el verde sonara con una voz que Piper se # descarga por su cuenta —la GPL de OHF-Voice que trae Hermes de serie—, # comparar los dos carriles no diria nada: la mitad de la impresion de un # asistente de voz es el timbre. # # Por eso el TTS de Hermes va por comando (type: command, sin documentar en su # web pero si en tools/tts_tool.py) contra voz-verde.sh, que es un adaptador de # 15 lineas al mismo config/jarvis-piper.sh del naranja: mismo binario Piper # 1.2.0 MIT, mismo .onnx, misma cadena de audio. # # La prueba llama al adaptador EXACTAMENTE como lo llama Hermes: dos argumentos, # el WAV de salida y un FICHERO con el texto. Es donde estaba la trampa — # jarvis-piper.sh quiere el texto como argumento— y una interfaz mal encajada no # se ve hasta que suena mal. # # No suena nada: se genera el fichero y se mide. cd "$(dirname "$0")" && . ./comun.sh titulo "El adaptador" afirma "existe voz-verde.sh" test -x "$VERDE/voz-verde.sh" afirma "existe jarvis-piper.sh del naranja" test -x "$RAIZ/config/jarvis-piper.sh" titulo "Generar" TEXTO=$TMP/texto.txt WAV=$TMP/voz.wav rm -f "$WAV" printf 'A sus órdenes, señor. Todos los sistemas responden con normalidad.' > "$TEXTO" INICIO=$(date +%s.%N) "$VERDE/voz-verde.sh" "$WAV" "$TEXTO" >"$TMP/voz.log" 2>&1 SALIO=$? TARDO=$(awk "BEGIN{printf \"%.2f\", $(date +%s.%N) - $INICIO}") if [ $SALIO -ne 0 ] || [ ! -s "$WAV" ]; then echo " $(rojo FALLO) voz-verde.sh no genero el WAV (codigo $SALIO)" sed 's/^/ /' "$TMP/voz.log" | head -8 exit 1 fi echo " $(verde OK) WAV generado en ${TARDO}s"; _ok=$((_ok + 1)) titulo "El fichero" # soxi/ffprobe no estan garantizados: se lee la cabecera RIFF a mano, que son # cuatro campos en posiciones fijas y no depende de nada instalado. leer=$(python3 - "$WAV" <<'PY' import struct, sys, wave with wave.open(sys.argv[1]) as w: print(w.getframerate(), w.getnchannels(), w.getsampwidth() * 8, round(w.getnframes() / w.getframerate(), 2)) PY ) read -r HZ CANALES BITS SEGUNDOS <<<"$leer" comprueba "22050 Hz, como el naranja" "$HZ" "22050" comprueba "mono" "$CANALES" "1" comprueba "16 bits" "$BITS" "16" # Frase de ~4 s. Si sale mucho mas corta, Piper se comio el texto; si sale mucho # mas larga, el tono esta mal y sonaria a camara lenta. mayor_que "dura lo que una frase (s)" "$SEGUNDOS" 2 menor_que "y no se alarga de mas (s)" "$SEGUNDOS" 12 # Tiempo real: 0,34 s para 3,2 s de audio, medido el 15 ago. Es CPU, no toca la # grafica, asi que no compite con el modelo. RATIO=$(awk "BEGIN{printf \"%.2f\", $TARDO / $SEGUNDOS}") nota "sintesis $TARDO s para $SEGUNDOS s de audio (x$RATIO del tiempo real)" menor_que "sintetiza mas rapido de lo que dura" "$RATIO" 1 titulo "La misma voz que el naranja" # voz-verde.sh copia al NUCLEO (nucleo/boca/voz.py: POR_DEFECTO = "davefx"), no # al README, que describe sharvard y es del JARVIS sobre Newelle. Se compara # contra el nucleo porque es contra quien se va a comparar el carril. VOZ_VERDE=$(grep -oP 'JARVIS_PIPER_VOZ:-\K[^}]+' "$VERDE/voz-verde.sh") VOZ_NUCLEO=$(grep -oP 'POR_DEFECTO\s*=\s*"\K[^"]+' "$RAIZ/nucleo/boca/voz.py" 2>/dev/null) if [ -z "$VOZ_NUCLEO" ]; then nota "no pude leer la voz del nucleo; comparacion omitida" else comprueba "misma voz que el nucleo" "$VOZ_VERDE" "es_ES-${VOZ_NUCLEO}-medium" fi resumen