Skip to main content
Mande uma mensagem de voz no Telegram e a resposta volta como voice note — transcrição na entrada (Whisper embarcado por padrão, zero config), síntese na saída, com qualquer backend TTS configurado. Tudo aqui é agnóstico a provedor: do say do macOS ao motor embarcado Kokoro.

Modos (CHATCLI_GATEWAY_VOICE_REPLY)

Valores booleanos legados seguem válidos: truealways, falsenever. Um valor desconhecido cai em auto — um typo nunca silencia o gateway.
O daemon herda o ambiente da shell que executou /gateway start — e o .env nunca sobrescreve variável já exportada. Se o comportamento não bater com o .env, confira o modo efetivo no boot do daemon: gateway.log registra voice replies enabled (mode=...).

Controle por conversa — tool @voice

Cada conversa manda na própria preferência pedindo em linguagem natural: o modelo chama a tool @voice, e a escolha fica gravada por sessão (sobrevive a restart do daemon) com precedência sobre o modo global. A preferência fica em ~/.chatcli/gateway_voice_prefs.json (escrita atômica), chaveada por plataforma:chat. Hierarquia de decisão: preferência da conversamodo globalin-kind.

Escrita para o ouvido (speech-aware)

Quando a resposta vai virar áudio, duas camadas garantem fala natural:
  1. O modelo sabe antes de escrever: uma diretiva avisa que a resposta será falada — prosa conversacional, frases curtas, sem emojis, sem listas/tabelas/markdown.
  2. Garantia dura no sanitizador: antes da síntese, StripForSpeech achata markdown (código removido, links viram rótulo, tabelas viram prosa) e remove emojis e pictogramas — motores de TTS leem o nome Unicode deles em voz alta, enterrando a mensagem. Acentos do português ficam intactos.
O texto visual no chat continua com a formatação completa; só o áudio é higienizado.

Voice note que toca (transcode)

Backends que ignoram o formato pedido (o say do macOS emite aiff, espeak emite wav) produziam um arquivo que o Telegram mostra com tamanho mas não reproduz. Com ffmpeg no PATH, o gateway transcoda wav/aiff → OGG/Opus (perfil de voice note: 48 kHz mono) para qualquer provedor; formatos já comprimidos passam direto, e sem ffmpeg o clipe original segue como arquivo de áudio — degradação visível, nunca resposta perdida.

Pipeline completo

A decisão “esta resposta fala?” é uma regra única (preferência da conversa → modo global → in-kind) compartilhada entre o runner e o agent loop — os dois nunca divergem.

Solução de problemas


Relacionado