> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Respostas em Voz no Gateway

> O gateway responde voz com voz por padrão, cada conversa liga/desliga pedindo em linguagem natural, e a fala é escrita para o ouvido — em qualquer backend TTS.

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](/pt/features/chat-gateway)), síntese na saída, com **qualquer** backend TTS configurado. Tudo aqui é **agnóstico a provedor**: do `say` do macOS ao [motor embarcado Kokoro](/pt/features/text-to-speech).

***

## Modos (`CHATCLI_GATEWAY_VOICE_REPLY`)

| Valor             | Comportamento                                                                        |
| ----------------- | ------------------------------------------------------------------------------------ |
| `auto` *(padrão)* | **Responde na mesma moeda**: mensagem de voz → resposta com áudio; texto → só texto. |
| `always`          | Toda resposta final sai com áudio anexado.                                           |
| `never`           | Respostas só em texto.                                                               |

Valores booleanos legados seguem válidos: `true` → `always`, `false` → `never`. Um valor desconhecido cai em `auto` — um typo nunca silencia o gateway.

```bash theme={"system"}
# padrão já é auto; só é preciso exportar para always/never
export CHATCLI_GATEWAY_VOICE_REPLY=always
```

<Warning>
  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=...)`.
</Warning>

***

## 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**.

| Pedido na conversa                          | Efeito                                                 |
| ------------------------------------------- | ------------------------------------------------------ |
| "responde em áudio" / "quero ouvir sua voz" | `@voice on` — toda resposta desta conversa sai com voz |
| "para de mandar áudio"                      | `@voice off` — só texto nesta conversa                 |
| "volta ao normal"                           | `@voice auto` — de volta ao padrão (voz responde voz)  |

A preferência fica em `~/.chatcli/gateway_voice_prefs.json` (escrita atômica), chaveada por `plataforma:chat`. Hierarquia de decisão: **preferência da conversa** → **modo global** → *in-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

```text theme={"system"}
voice note (Telegram) ─→ transcrição (whisper local-first) ─→ agent loop
                                                                 │ diretiva speech-aware
                                                                 ▼
texto da resposta ─→ StripForSpeech ─→ TTS (qualquer backend) ─→ transcode ogg/opus ─→ sendVoice
```

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

| Sintoma                         | Causa provável                                         | Verificação                                            |
| ------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ |
| Tudo volta com áudio, até texto | Modo `always` ativo (env exportada na shell do daemon) | `gateway.log`: `voice replies enabled (mode=...)`      |
| Áudio chega mas não toca        | Formato cru sem ffmpeg para transcodar                 | `which ffmpeg`; instale para voice notes nativas       |
| Nunca responde em voz           | Modo `never`, ou nenhum backend TTS                    | `/config` → *Integrações · Gateway · Resposta em voz*  |
| Voz errada para o idioma        | Vozes do motor embarcado                               | `CHATCLI_TTS_VOICE` (en) / `CHATCLI_TTS_VOICE_PT` (pt) |

***

## Relacionado

* [Text-to-Speech](/pt/features/text-to-speech) — backends, motor embarcado Kokoro, `@speak`
* [Chat Gateway](/pt/features/chat-gateway) — transcrição de entrada, plataformas, daemon
* [Conversation Hub](/pt/features/conversation-hub) — continuidade entre canais
