Mensajes de voz

Una nota de voz llega como texto. La transcripción ocurre en la entrada, antes de que el agente se ejecute.

Mensajes de voz

Envía una nota de voz a tu bot de Telegram y el agente recibe texto. El audio se transcribe al entrar, antes de que exista una sesión y antes de cualquier decisión de enrutado, así que lo que llega al agente es un mensaje corriente.

No siempre fue así. El gateway guardaba el fichero en el espacio de trabajo del agente y le pasaba la ruta, dejando que el agente averiguara por su cuenta cómo escuchar: encontrar un transcriptor, instalarlo, ejecutarlo, leer la salida. Cada nota de voz se convertía en un pequeño proyecto de investigación. Era lento, salía distinto cada vez, y gastaba una verja de permisos solo para leer el mensaje que acababa de llegar.

Nada que configurar

Si ya tienes una conexión de modelo con OpenAI o con Groq, la transcripción ya funciona. Pepe reutiliza esa credencial y le pide al provider su modelo de transcripción (whisper-1 en OpenAI, whisper-large-v3-turbo en Groq) en lugar del modelo de chat con el que se configuró la conexión. Envía una nota de voz y se responde. No hay nada que ajustar.

Cómo se elige la ruta

Pepe prueba estas rutas en este orden, y cualquiera de ellas puede faltar:

  1. media.audio.model: una conexión de modelo, referida por su nombre. La cadena de fallbacks de esa conexión también se aplica aquí, así que el failover no cuesta nada extra.
  2. media.audio.command: un comando local, por ejemplo whisper-cli -f {file}. {file} se sustituye por la ruta del audio. Esto se prueba antes de la detección automática, y es a propósito: quien configuró un transcriptor local lo hizo para que el audio no salga de la máquina, y saltárselo para llamar a un provider echaría por tierra ese propósito.
  3. Detección automática: la ruta sin configuración descrita arriba.
  4. Nada disponible: el fichero va al agente, que se las arregla con las herramientas que tiene. Esa vía queda como red de seguridad; no es la puerta de entrada.

Configurar esto

Apunta la transcripción a una conexión de modelo concreta, o a un comando local, desde la CLI:

pepe media audio --model groq --language es --echo true
pepe media audio --command "whisper-cli -f {file}"   # mantiene el audio en la máquina
pepe media audio off                                 # vuelve a la detección automática

--echo true devuelve la transcripción al chat, para que quien habló vea qué se entendió. Las mismas opciones están en la página Config del panel, y en pepe setup bajo Media.

Por qué importa transcribir primero

Como las palabras existen antes de que se ejecute el enrutado, el enrutado puede leerlas. De ahí salen dos consecuencias, ninguna posible mientras la transcripción solo aparecía dentro del turno del agente:

El audio se vuelve texto; la foto se vuelve visión. El habla se transcribe en la puerta. Una foto se envía al modelo como una imagen que de verdad puede ver (en un modelo con visión, más abajo). Un documento se extrae a texto.

Responder de vuelta

Responde a una nota de voz con otra nota de voz. Apagado por defecto; apunta media.tts a una conexión de modelo que sirva un /audio/speech compatible con OpenAI y se enciende:

pepe media tts --model openai --voice nova
pepe media tts off

La respuesta en texto sigue siendo el registro que queda guardado. El audio es un extra, y tiene un límite de tamaño para que una respuesta larga nunca se convierta en un clip de cinco minutos. Un fallo del TTS es silencioso: la respuesta en texto ya se envió, así que no se pierde nada, solo no lleva voz ese turno. Las mismas opciones están en la página Config del panel, y en pepe setup bajo Media.

Fotos

Envía una foto a tu bot de Telegram y, en un modelo con visión, el agente ve la imagen de verdad, no un nombre de archivo. Antes recibía solo una línea de texto («el usuario envió una foto, guardada en ») mientras que la imagen en sí nunca llegaba al modelo, así que el agente se quedaba adivinando, o inventando, qué había en ella. Ahora la imagen va junto con el mensaje.

Está desactivado a menos que digas que el modelo ve. No todos los endpoints compatibles con OpenAI aceptan una imagen, y enviar una a un modelo solo de texto es un error, así que la visión es opcional por conexión:

{
  "models": {
    "gpt4o": {
      "base_url": "https://api.openai.com/v1",
      "api_key": "${OPENAI_API_KEY}",
      "model": "gpt-4o",
      "vision": true
    }
  }
}

Con vision activo, una foto (con o sin pie) llega al modelo como imagen en el turno en que se recibe. Funciona igual en conexiones compatibles con OpenAI, Anthropic y Responses/Codex. La imagen acompaña solo ese turno: como una transcripción, el registro que queda es la respuesta del agente sobre ella, no los bytes, así que nunca infla la sesión ni se reenvía en cada turno. Un modelo sin vision vuelve al comportamiento anterior (la ruta del archivo en el prompt, para que el agente lo abra con sus propias herramientas).

Telegram ya envía cada foto en varios tamaños preescalados, así que Pepe elige el mayor que cabe en el tope de bytes, sin ninguna biblioteca de procesamiento de imagen que instalar. Un álbum de fotos se envía como varias imágenes juntas. Los límites están en media.image y ambos tienen valores por defecto:

{
  "media": {
    "image": { "max_mb": 5, "max_parts": 4 }
  }
}

Configuración

Todas las claves son opcionales y viven en media.audio, dentro de ~/.pepe/config.json:

{
  "media": {
    "audio": {
      "model": "groq",
      "language": "es",
      "max_mb": 20,
      "timeout": 60,
      "echo": true
    }
  }
}

Para mantener el audio en la máquina, usa un comando en lugar de una conexión:

{
  "media": {
    "audio": {
      "command": "whisper-cli -f {file}",
      "timeout": 120
    }
  }
}

Salvaguardas