UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

103 lines (87 loc) • 7.4 kB
--- summary: "Per-channel audio formats, transcoding, and what Auto-TTS sends" title: "Text-to-speech output and Auto-TTS behavior" read_when: - You need the audio format a channel receives - You are debugging voice-note delivery or transcoding - You want to know when Auto-TTS summarizes or truncates a reply --- ## Output formats TTS voice delivery is channel-capability driven. Channel plugins advertise whether voice-style TTS should ask providers for a native `voice-note` target or keep normal `audio-file` synthesis, and whether the channel transcodes non-native output before sending. One-off speech requests from the agent tool and `/tts` commands use the same channel delivery rules as automatic replies. Telegram also advertises captioned final TTS. With `tts.mode: "final"` and Auto-TTS set to `always` (or eligible `inbound` mode), streamed text is held until synthesis finishes and sent as the voice-note caption. Text beyond Telegram's caption limit follows the voice note as a normal text message. If synthesis or a proven pre-send delivery step fails, OpenClaw sends the visible text instead. `tagged` mode keeps its normal streaming behavior, and text inside a `[[tts:text]]` block remains audio-only. After synthesis, OpenClaw persists batch TTS output in the media store under `tool-speech-synthesis`. The reply uses that stable media path instead of a provider temporary file, and normal media maintenance prunes expired output. Local CLI providers may still use `{{OutputPath}}` as scratch space before OpenClaw imports the completed bytes. See [Media playback](/nodes/media-playback) for inline-player formats and limits. | Target | Format | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | Feishu / Matrix / Telegram / WhatsApp | Voice-note replies prefer **Opus** (`opus_48000_64` from ElevenLabs, `opus` from OpenAI). 48 kHz / 64 kbps balances clarity and size. | | Other channels | **MP3** (`mp3_44100_128` from ElevenLabs, `mp3` from OpenAI). 44.1 kHz / 128 kbps is the default balance for speech. | | Talk / telephony | Provider-native **PCM** (Inworld 22050 Hz, Google 24 kHz), or `ulaw_8000` from Gradium for telephony. | Per-provider notes: - **Feishu / WhatsApp transcoding:** when a voice-note reply lands as MP3/WebM/WAV/M4A or another likely audio file, the channel plugin transcodes it to 48 kHz Ogg/Opus with `ffmpeg` (`libopus`, 64 kbps) before sending the native voice message. WhatsApp sends the result through the Baileys `audio` payload with `ptt: true` and `audio/ogg; codecs=opus`. On transcode failure: Feishu catches the error and falls back to sending the original file as a plain attachment; WhatsApp has no fallback, so the send itself fails rather than posting an incompatible PTT payload. - **MiniMax:** MP3 (`speech-2.8-hd` model, 32 kHz sample rate) for normal audio attachments; transcoded to 48 kHz Opus with `ffmpeg` for channel-advertised voice-note targets. - **Xiaomi MiMo:** MP3 by default, or WAV when configured; transcoded to 48 kHz Opus with `ffmpeg` for channel-advertised voice-note targets. - **Local CLI:** uses the configured `outputFormat`. Voice-note targets are converted to Ogg/Opus and telephony output is converted to raw 16 kHz mono PCM with `ffmpeg`. - **Google Gemini:** returns raw 24 kHz PCM. OpenClaw wraps it as WAV for audio attachments, transcodes it to 48 kHz Opus for voice-note targets, and returns PCM directly for Talk/telephony. - **Gradium:** WAV for audio attachments, Opus for voice-note targets, and `ulaw_8000` at 8 kHz for telephony. - **Inworld:** MP3 for normal audio attachments, native `OGG_OPUS` for voice-note targets, and raw `PCM` at 22050 Hz for Talk/telephony. - **xAI:** MP3 by default; audio-file synthesis may use `mp3`, `wav`, `pcm`, `mulaw`, or `alaw` for both buffered and streaming output. Voice-note targets use MP3 for streaming and buffered fallback because xAI's `pcm`, `mulaw`, and `alaw` outputs are headerless raw audio. Buffered synthesis uses xAI's batch REST `/v1/tts` endpoint; `textToSpeechStream` uses native `wss://api.x.ai/v1/tts`. This is not the realtime voice contract. Native Opus voice-note format is not supported. - **Microsoft:** uses `microsoft.outputFormat` (default `audio-24khz-48kbitrate-mono-mp3`). - The bundled transport accepts an `outputFormat`, but not all formats are available from the service. - Output format values follow Microsoft Speech output formats (including Ogg/WebM Opus). - Telegram `sendVoice` accepts OGG/MP3/M4A; use OpenAI/ElevenLabs if you need guaranteed Opus voice messages. - If the configured Microsoft output format fails, OpenClaw retries with MP3. - When no explicit voice override is set and the default English voice is used, OpenClaw auto-switches to a Chinese neural voice (`zh-CN-XiaoxiaoNeural`, `zh-CN` locale) if the reply text is CJK-dominant. OpenAI and ElevenLabs choose output formats per channel as listed above. An explicit OpenAI `responseFormat` overrides that selection; a format that is not voice-note compatible may be delivered as an audio file or transcoded by a channel that supports conversion. ## Auto-TTS behavior When `tts.auto` is enabled, OpenClaw: - Keeps terminal slash and plugin command replies text-only, including with `auto: "always"`. Explicit speech requests such as `/tts audio` and `/tts latest` still send audio. Commands that continue into an assistant run keep the normal auto-TTS behavior for the assistant's answer. - Skips TTS if the reply already contains structured media. - Skips very short replies (under 10 chars). - Skips replies dominated by fenced code; inline code and surrounding prose remain eligible for speech. - Summarizes long replies when summaries are enabled, using `summaryModel` (or `agents.defaults.model.primary`). Summary model access uses the replying agent's credentials and ownership. - Attaches the generated audio to the reply. - In `mode: "final"`, sends TTS after streamed text completes. Channels without captioned-final support receive an audio-only supplement; Telegram puts text within its caption limit on the voice note and sends overflow as follow-up text. Generated media goes through the same channel media normalization as normal reply attachments. If the reply exceeds `maxLength`, OpenClaw never skips audio outright: - **Summary on** (default) and a summary model is available: summarizes the text to roughly `maxLength` chars, then synthesizes the summary. - **Summary off**, summarization fails, or no API key is available for the summary model: truncates the text to `maxLength` chars and synthesizes the truncated text. ```text Reply -> TTS enabled? no -> send text yes -> has media / short? yes -> send text no -> length > limit? no -> TTS -> attach audio yes -> summary enabled and available? no -> truncate -> TTS -> attach audio yes -> summarize -> TTS -> attach audio ```