# Guía técnica de implantación, respuestas Audio+Texto y reconocimiento de voz en OpenClaw

## Actualización operativa, Transcripción de Audio, STT en OpenClaw vía Telegram

### Arquitectura

Telegram (audio `.oga`) → OpenClaw Gateway → `transcribe_audio.py` → `faster-whisper` → texto

### 1. Dependencias del servidor

```bash
# FFmpeg (convertir .oga → .wav)
sudo apt install -y ffmpeg

# faster-whisper (motor STT)
pip3 install --user faster-whisper
```

### 2. Script de transcripción

Ubicación:

`~/.openclaw/scripts/transcribe_audio.py`

```python
#!/usr/bin/env python3
import sys, subprocess, tempfile, os
from faster_whisper import WhisperModel

audio_path = sys.argv[1]

# Convertir a WAV 16kHz mono (formato óptimo para Whisper)
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
    wav_path = tmp.name

subprocess.run([
    "ffmpeg", "-y", "-i", audio_path,
    "-ar", "16000", "-ac", "1", "-f", "wav", wav_path
], capture_output=True)

# Transcribir con faster-whisper
model = WhisperModel("small", device="cpu", compute_type="int8")
segments, info = model.transcribe(wav_path, language="es", vad_filter=True)

text = " ".join(seg.text.strip() for seg in segments)
print(text)

os.unlink(wav_path)
```

Permisos:

```bash
chmod +x ~/.openclaw/scripts/transcribe_audio.py
```

### 3. Configuración en openclaw.json

En `~/.openclaw/openclaw.json`, dentro del bloque `tools.media`:

```json
{
  "tools": {
    "media": {
      "audio": {
        "command": "python3 ~/.openclaw/scripts/transcribe_audio.py {{MediaPath}}",
        "timeout": 120
      }
    }
  }
}
```

### 4. Reiniciar el servicio

```bash
# silvio-server (systemd user)
systemctl --user restart openclaw-gateway.service

# Hetzner (systemd system)
sudo systemctl restart openclaw.service
```

### 5. Parámetros clave y por qué

- **Modelo:** `small`, equilibrio precisión/velocidad en CPU
- **Idioma:** `es`, forzar español evita alucinaciones por autodetección
- **compute_type:** `int8`, reduce RAM y acelera en CPU
- **vad_filter:** `True`, ignora silencios y mejora precisión
- **Formato:** WAV 16kHz mono, estándar Whisper y evita artefactos de `.oga`
- **Timeout:** `120s`, útil para audios largos de Telegram

### 6. Verificación

Enviar un audio por Telegram al bot. En logs debería verse la transcripción.

```bash
journalctl --user -u openclaw-gateway.service -f
```

Buscar trazas relacionadas con la transcripción del audio.

### 7. Solución de problemas

- **Sin transcripción:** script no encontrado, verificar ruta en `openclaw.json`
- **Texto en inglés:** idioma no forzado, añadir `language="es"`
- **Alucinaciones:** modelo demasiado pequeño o sin VAD, usar `small` + `vad_filter=True`
- **Timeout:** audio largo o CPU lenta, subir timeout o usar un modelo más ligero
- **Error ffmpeg:** instalar `ffmpeg`

---

## 1. Propósito

Este documento describe una implantación reutilizable para OpenClaw con dos capacidades coordinadas:

- **TTS de salida** para que el asistente responda con **texto + audio**.
- **STT de entrada** para que las notas de voz del usuario se conviertan en texto utilizable por el agente.

La guía está pensada para una instalación operativa en servidor o estación Linux con OpenClaw ya desplegado.

---

## 2. Alcance

Esta implantación cubre:

- configuración de TTS automático para respuestas finales
- selección de voz femenina en español
- transcripción local de audios mediante `faster-whisper`
- validación funcional extremo a extremo
- diagnóstico básico y rollback

No cubre:

- instalación inicial completa de OpenClaw
- hardening del host
- telephony / voice-call
- alta disponibilidad

---

## 3. Resultado esperado

Tras aplicar este procedimiento, el sistema debe cumplir lo siguiente:

1. El asistente responde en **texto**.
2. Cada respuesta final se entrega también como **audio TTS**.
3. Los audios recibidos del usuario se transcriben localmente.
4. La voz configurada para TTS queda en `es-ES-XimenaNeural`.
5. El reconocimiento de voz en español mejora respecto a la configuración base, usando un modelo `small` con parámetros más robustos.

---

## 4. Arquitectura de la solución

La solución queda dividida en dos flujos:

### 4.1 Flujo de entrada, STT

1. El usuario envía una nota de voz.
2. OpenClaw descarga el archivo de audio.
3. OpenClaw ejecuta un modelo de audio tipo `cli`.
4. Ese modelo llama a `python3 /home/kevin/.openclaw/scripts/transcribe_audio.py {{MediaPath}}`.
5. El script usa `faster-whisper` para transcribir en español.
6. La transcripción se incorpora al contexto del agente.

### 4.2 Flujo de salida, TTS

1. El agente genera una respuesta final en texto.
2. OpenClaw aplica la política `messages.tts`.
3. Se sintetiza audio usando el proveedor `microsoft`.
4. La voz seleccionada es `es-ES-XimenaNeural`.
5. El usuario recibe respuesta en texto y audio.

---

## 5. Prerrequisitos

### 5.1 Requisitos funcionales

- OpenClaw instalado y operativo.
- Acceso al host donde corre el gateway.
- Capacidad para reiniciar el gateway tras cambios de configuración.
- Python 3 disponible en el sistema.
- Dependencias de `faster-whisper` instaladas.
- `edge-tts` disponible si se va a validar inventario de voces locales.

### 5.2 Comprobaciones recomendadas

```bash
python3 --version
edge-tts --list-voices | grep Ximena
openclaw status --deep
```

### 5.3 Condiciones operativas

- El host debe poder ejecutar procesos Python locales.
- El usuario debe aceptar que un reinicio del gateway puede interrumpir momentáneamente la sesión activa.

---

## 6. Componentes implantados

### 6.1 Script de transcripción STT

Ruta recomendada de producción:

`/home/kevin/.openclaw/scripts/transcribe_audio.py`

No depender de una ruta relativa dentro del workspace para el gateway.

Código implantado:

```python
import sys
from functools import lru_cache
from faster_whisper import WhisperModel


@lru_cache(maxsize=1)
def get_model():
    model_size = "small"
    return WhisperModel(model_size, device="cpu", compute_type="int8")


def transcribe_audio_file(audio_file_path):
    model = get_model()
    segments, info = model.transcribe(
        audio_file_path,
        beam_size=5,
        language="es",
        vad_filter=True,
        condition_on_previous_text=False,
        temperature=0,
    )

    transcription = " ".join(segment.text.strip() for segment in segments).strip()
    print(transcription)


if __name__ == "__main__":
    if len(sys.argv) > 1:
        audio_path = sys.argv[1]
        transcribe_audio_file(audio_path)
    else:
        print("Usage: python3 transcribe_audio.py <audio_file_path>")
```

### 6.2 Justificación técnica del ajuste STT

Se sustituyó una configuración menos precisa por una más robusta para español:

- `model_size = "small"` en lugar de `base`
- `vad_filter=True` para recortar silencios y mejorar segmentación
- `condition_on_previous_text=False` para evitar arrastre de contexto erróneo
- `temperature=0` para reducir variabilidad en la decodificación

Este ajuste resolvió errores observados en pruebas reales de voz, especialmente en frases como:

- “¿Cómo te llamas?”
- “Dime qué día es hoy.”
- “Dime cuál es tu nombre.”

---

## 7. Implantación de STT en OpenClaw

### 7.1 Configuración requerida

Aplicar:

```bash
openclaw config set tools.media.audio.models.0.type cli
openclaw config set tools.media.audio.models.0.command python3
openclaw config set tools.media.audio.models.0.timeoutSeconds 120
openclaw config set tools.media.audio.models.0.args '["/home/kevin/.openclaw/scripts/transcribe_audio.py", "{{MediaPath}}"]' --strict-json
```

### 7.2 Estado objetivo

La sección efectiva debe equivaler a:

```json
{
  "tools": {
    "media": {
      "audio": {
        "models": [
          {
            "type": "cli",
            "command": "python3",
            "timeoutSeconds": 120,
            "args": ["/home/kevin/.openclaw/scripts/transcribe_audio.py", "{{MediaPath}}"]
          }
        ]
      }
    }
  }
}
```

### 7.3 Verificación puntual del script

Se puede probar sin pasar por OpenClaw:

```bash
python3 /home/kevin/.openclaw/scripts/transcribe_audio.py /ruta/al/audio.ogg
```

---

## 8. Implantación de TTS automático, Audio+Texto

### 8.1 Objetivo funcional

La respuesta del asistente debe entregarse siempre en dos formatos:

- texto visible
- audio TTS de la respuesta final

### 8.2 Configuración requerida

Aplicar:

```bash
openclaw config set messages.tts.enabled true
openclaw config set messages.tts.auto always
openclaw config set messages.tts.mode final
openclaw config set messages.tts.provider microsoft
openclaw config set messages.tts.providers.microsoft.enabled true
openclaw config set messages.tts.providers.microsoft.lang es-ES
openclaw config set messages.tts.providers.microsoft.voice es-ES-XimenaNeural
```

### 8.3 Estado objetivo

La configuración efectiva debe quedar equivalente a:

```json
{
  "messages": {
    "tts": {
      "enabled": true,
      "auto": "always",
      "mode": "final",
      "provider": "microsoft",
      "prefsPath": "~/.openclaw/settings/tts.json",
      "providers": {
        "microsoft": {
          "enabled": true,
          "voice": "es-ES-XimenaNeural",
          "lang": "es-ES"
        }
      }
    }
  }
}
```

### 8.4 Consideraciones operativas

- `auto: always` fuerza intento de audio en todas las respuestas.
- `mode: final` evita sintetizar texto intermedio o commentary.
- `provider: microsoft` activa la ruta de síntesis compatible con la voz seleccionada.
- La voz seleccionada en esta implantación es `es-ES-XimenaNeural`.

---

## 9. Inventario de voces femeninas en español

Voces útiles detectadas para pruebas:

- `es-ES-ElviraNeural`
- `es-ES-XimenaNeural`
- `es-MX-DaliaNeural`
- `es-AR-ElenaNeural`
- `es-CO-SalomeNeural`

### 9.1 Cambio de voz

Ejemplo:

```bash
openclaw config set messages.tts.providers.microsoft.voice es-MX-DaliaNeural
openclaw gateway restart
```

---

## 10. Aplicación de cambios

Tras modificar configuración, reiniciar el gateway:

```bash
openclaw gateway restart
```

En despliegues con `systemd --user`, también puede utilizarse:

```bash
systemctl --user restart openclaw-gateway.service
```

### 10.1 Nota de operación

Un reinicio del gateway puede cortar la ejecución de la sesión actual. Esto es esperable. La validación debe realizarse con el siguiente mensaje entrante.

---

## 11. Procedimiento de validación

### 11.1 Validación de STT

Enviar varias notas de voz cortas en español y confirmar transcripción correcta.

Casos recomendados:

- “¿Cómo te llamas?”
- “Dime qué día es hoy.”
- “Dime cuál es tu nombre.”

Criterio de aceptación:

- la frase reconocida coincide de forma fiable con el audio real
- no aparecen sustituciones sistemáticas graves

### 11.2 Validación de TTS

Enviar mensajes normales al asistente y comprobar:

1. hay respuesta textual
2. hay audio adjunto
3. la voz es `Ximena`
4. el audio corresponde a la respuesta final

### 11.3 Validación extremo a extremo

Secuencia mínima:

1. enviar audio del usuario
2. verificar que el sistema lo entiende correctamente
3. solicitar una respuesta del asistente
4. verificar que vuelve texto + audio

---

## 12. Diagnóstico y troubleshooting

### 12.1 Síntoma, STT falla o devuelve transcripciones ajenas al audio real

Posibles causas:

- la ruta configurada del script STT no existe realmente para el gateway
- OpenClaw no está ejecutando el script esperado
- se está usando una ruta relativa no fiable en vez de una ruta absoluta estable
- modelo demasiado pequeño o segmentación débil

Acción correctiva recomendada:

- mover el script a `/home/kevin/.openclaw/scripts/transcribe_audio.py`
- configurar `tools.media.audio.models.0.args` con ruta absoluta
- ampliar `timeoutSeconds` a `120`
- reiniciar el gateway
- dentro del script usar `small`, `vad_filter=True`, `condition_on_previous_text=False`, `temperature=0`, `beam_size=5`

Nota importante:

En esta implantación, la causa raíz real no fue solo la precisión del modelo, sino que OpenClaw no estaba usando de forma fiable el script `outbox/transcribe_audio.py`. Al fijar una ruta absoluta estable dentro de `~/.openclaw/scripts/`, las pruebas reales de audio empezaron a comportarse correctamente.

### 12.2 Síntoma, aparece texto pero no audio

Comprobar:

```bash
openclaw config get messages.tts.enabled
openclaw config get messages.tts.auto
openclaw config get messages.tts.provider
openclaw config get messages.tts.providers.microsoft.voice
```

Valores esperados:

- `true`
- `always`
- `microsoft`
- `es-ES-XimenaNeural`

Si los valores son correctos, reiniciar gateway.

### 12.3 Síntoma, se sintetiza contenido no deseado

Comprobar que `messages.tts.mode` sea:

```bash
final
```

Esto limita la síntesis a la respuesta final.

### 12.4 Síntoma, el reinicio interrumpe la prueba

Comportamiento esperado. Reanudar validación tras reconexión y enviar un mensaje nuevo.

---

## 13. Rollback

Si se necesita volver a una configuración anterior:

### 13.1 Desactivar TTS automático

```bash
openclaw config set messages.tts.enabled false
openclaw gateway restart
```

### 13.2 Volver a otra voz

```bash
openclaw config set messages.tts.providers.microsoft.voice es-ES-ElviraNeural
openclaw gateway restart
```

### 13.3 Retirar el STT basado en script

Reconfigurar `tools.media.audio.models` al proveedor o comando anterior, o eliminar la entrada activa.

---

## 14. Configuración final validada en esta implantación

### 14.1 TTS

```json
{
  "auto": "always",
  "provider": "microsoft",
  "prefsPath": "~/.openclaw/settings/tts.json",
  "providers": {
    "edge": {
      "enabled": true,
      "voice": "es-ES-AlvaroNeural",
      "lang": "es-ES"
    },
    "microsoft": {
      "enabled": true,
      "voice": "es-ES-XimenaNeural",
      "lang": "es-ES"
    }
  },
  "enabled": true,
  "mode": "final"
}
```

### 14.2 STT

```json
{
  "models": [
    {
      "command": "python3",
      "type": "cli",
      "timeoutSeconds": 60,
      "args": ["outbox/transcribe_audio.py", "{{MediaPath}}"]
    }
  ]
}
```

---

## 15. Evidencia de cambio

### 15.1 Mejora de STT

Commit asociado:

- `93c8598` - `Improve Spanish STT accuracy for voice notes`

### 15.2 Documento de implantación

Commit asociado:

- `dc0d95e` - `Add deployment manual for audio text and STT setup`

---

## 16. Recomendación de uso en nuevas instalaciones

Para replicar esta solución en otro entorno:

1. verificar dependencias
2. desplegar el script `outbox/transcribe_audio.py`
3. configurar `tools.media.audio.models`
4. configurar `messages.tts`
5. reiniciar gateway
6. ejecutar validación con audios reales y respuestas reales
7. fijar la voz elegida según preferencia del usuario

---

## 17. Resumen ejecutivo

Esta implantación convierte OpenClaw en un asistente conversacional con entrada y salida por voz en español:

- **entrada**: STT local con Faster-Whisper ajustado para mejor precisión
- **salida**: TTS automático en todas las respuestas finales
- **voz activa**: `es-ES-XimenaNeural`
- **modo de entrega**: texto + audio

La solución ha sido validada con pruebas reales y deja una base reutilizable para futuras instalaciones.
