#!/usr/bin/env bash # Voz de JARVIS con la clonada (XTTS-v2) servida desde cache. # # jarvis-voz.sh # # Si el texto esta pre-generado en cache_voz/, lo sirve al instante (un cp, sin # tocar GPU). Si no, cae a Piper. La clave es sha1(texto normalizado), la misma # que calcula generar_cache_voz.py -> los aciertos son exactos. # # El clon ya trae el tono correcto, asi que en un acierto NO se aplica el # descenso de tono de Piper; solo se copia. En un fallo, Piper hace lo suyo # (incluido su rubberband) como hasta ahora. set -uo pipefail # La raiz se deduce de donde esta este fichero, no del $HOME de nadie: asi el # arbol se puede mover o clonar en otra maquina y sigue funcionando sin editar # rutas. `cd -P` resuelve enlaces simbolicos, que el lanzador de escritorio # puede invocarlo por uno. RAIZ=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) BASE=$RAIZ/voz CACHE=$BASE/cache_voz PIPER=$RAIZ/config/jarvis-piper.sh SALIDA=${1:-} TEXTO=${2:-} [ -n "$SALIDA" ] || { echo "falta el fichero de salida" >&2; exit 1; } [ -n "$TEXTO" ] || { echo "sin texto que decir" >&2; exit 1; } # clave = sha1(texto con espacios colapsados y recortado), identica a la de # Python: re.sub(r'\s+',' ',t).strip() -> sha1(utf-8) T=$(printf '%s' "$TEXTO" | tr -s '[:space:]' ' ' | sed 's/^ //; s/ $//') KEY=$(printf '%s' "$T" | sha1sum | cut -d' ' -f1) HIT=$CACHE/$KEY.wav if [ -f "$HIT" ]; then cp -f "$HIT" "$SALIDA" exit 0 fi # fallo de cache -> registrar la frase (normalizada) para calentar la cache # luego con la voz clonada, y de momento reescribir siglas + Piper. printf '%s\n' "$T" >> "$BASE/misses.log" 2>/dev/null || true TEXTO2=$(python3 "$BASE/pronuncia.py" "$TEXTO" 2>/dev/null) [ -n "$TEXTO2" ] || TEXTO2=$TEXTO exec "$PIPER" "$SALIDA" "$TEXTO2"