Skip to content
KNOOP edited this page Aug 27, 2026 · 3 revisions

Text to Speech (Voice Replies)

Ava supports two TTS playback modes for voice assistant replies: Standard TTS (URL-based) and Streaming TTS (PCM-based). The mode is selected in Settings → Voice → Voice Replies.

0.5.9–0.6.1 steadily hardened streaming TTS across different Home Assistant and TTS combinations, so silent or broken replies are far less common. 0.6.3 comprehensively rebuilt TTS playback across both classic and streaming modes. 0.7.3 added TTS volume as a HA-controllable number entity and preserve-original-URL for HTTPS setups.


Standard TTS

Standard TTS waits until Home Assistant generates the full voice reply, then downloads and plays it from a URL.

Flow:

  1. HA sends TTS_START with the reply text (displayed as subtitle)
  2. HA sends TTS_END with the TTS audio URL
  3. Ava downloads the audio file and plays it via ExoPlayer
  4. On playback completion, Ava sends announce_finished to HA

Characteristics:

  • Better compatibility — works with any HA TTS provider
  • Supports floating subtitle overlay (word-by-word or full text)
  • Supports wake sound and stop sound
  • Higher latency — first audio is heard only after the full reply is generated and downloaded
  • HTTP streaming playback with configurable connect/read timeout (30s)

Early TTS URL: HA may include the TTS URL in RUN_START before the conversation even begins. Ava caches this URL and uses it when TTS_END arrives, reducing latency.


Streaming TTS

Streaming TTS starts playing audio while the reply is still being generated on the HA side. HA sends PCM audio chunks in real time.

Flow:

  1. HA sends TTS_START — Ava enters Responding state
  2. HA sends TTS_STREAM_START — Ava opens an AudioTrack (16 kHz, 16-bit, mono PCM)
  3. HA sends PCM audio chunks via VoiceAssistantAudio messages — Ava writes them to AudioTrack in real time
  4. HA sends TTS_STREAM_END — Ava drains remaining audio, then completes

Characteristics:

  • Faster first response — audio starts playing as soon as the first PCM chunk arrives
  • No floating subtitle overlay (subtitles are suppressed in streaming mode because text arrives in fragments)
  • Requires HA server with streaming TTS output support (HA SPEAKER feature flag)
  • PCM audio is played via raw AudioTrack, not ExoPlayer
  • Volume scaling is applied per-sample on PCM data before writing to the track
  • Buffered chunk handling: if PCM chunks arrive before TTS_STREAM_START, they are buffered and flushed when the stream opens (max 256 frames)

Streaming TTS Reliability (0.5.9–0.6.1)

Streaming TTS is great for low-latency replies, but not every Home Assistant TTS setup produces valid PCM audio in every situation. Ava now handles the common failure cases without leaving you with silence:

  • Empty stream fallback (0.5.9): If a server announces a stream but no usable audio arrives, Ava falls back to the standard URL path. It only switches if real PCM data starts arriving, and avoids duplicate playback if late stream data appears.
  • No-audio stream protection (0.6.0): Some servers send TTS_STREAM_START and TTS_STREAM_END events without actually transmitting any PCM. Ava now waits for enough real audio data before the PCM path takes over, so an empty stream can no longer interrupt a URL voice reply that has already started. A watchdog also stops the assistant from getting stuck in Responding when the end event never arrives.
  • Relative media paths and out-of-order events (0.6.1): Some Home Assistant speak responses provide a relative media path instead of a full URL; Ava resolves it through the authenticated base address used for cover and media requests. The streaming state machine also recovers if a PCM stream opens but never becomes audible, or if TTS_STREAM_END arrives before any real audio.

In other words: if streaming works, you get the faster PCM reply. If the server advertises a stream but cannot deliver audio, you still get the URL reply — not silence.

TTS Playback Rebuild (0.6.3)

TTS playback has been comprehensively rebuilt across both classic and streaming modes:

  • Long responses are no longer terminated by a fixed 20-second timeout. Ava now follows actual playback progress, uses duration information when available, and distinguishes active playback, rebuffering, network failure, and a genuinely stalled stream.
  • If streaming PCM provides no usable audio, stops unexpectedly, or misses an upstream completion event, Ava can recover through URL playback without playing both sources.
  • A stale playback callback could previously terminate the next voice session immediately after a progressive TTS response. Playback state is now fully detached between sessions, fixing intermittent first-wake and follow-up wake failures.
  • Failed starts, prolonged buffering, audio-focus loss, and missing stream-end events are handled independently, allowing voice sessions to finish cleanly and media playback to resume normally.

Use Original TTS URL (0.6.3)

Home Assistant installations serving TTS directly over HTTPS can now enable Use original TTS URL. Ava plays the address returned by Home Assistant instead of rewriting it to LAN HTTP, preventing the silent address timeout reported in #152.

This option is disabled by default, leaving existing LAN configurations unchanged.

Path: Ava Settings → Voice Replies → Maintenance → Use original TTS URL

Feature flag negotiation: When streaming TTS is enabled in settings, Ava sets the SPEAKER feature flag in the VoiceAssistantConfigurationRequest. HA uses this to decide whether to send PCM streams.


Mode Comparison

Feature Standard TTS Streaming TTS
First audio latency Higher (wait for full reply) Lower (play while generating)
Floating subtitles Yes No
Wake sound Yes Yes
Stop sound Yes Yes
Server requirement Any HA TTS provider HA with streaming output support
Playback engine ExoPlayer (HTTP) AudioTrack (raw PCM)
Audio format Any (URL-based) 16 kHz 16-bit mono PCM
Whisper response Yes Yes

Announcement Playback

Ava supports HA's VoiceAssistantAnnounceRequest for proactive announcements (e.g., timer finished, ask_question). This is separate from the conversation TTS flow.

Flow:

  1. HA sends AnnounceRequest with media_id (and optional preannounce_media_id)
  2. Ava ducks media playback, plays the announcement audio
  3. On completion, Ava sends announce_finished to HA
  4. If start_conversation=true, Ava starts a new voice pipeline to listen for the user's response (10s timeout)

Preannounce: If a preannounce_media_id is provided, Ava plays it first (e.g., "Attention:"), then plays the main media. A 3-second load timeout skips the preannounce if it fails to start.


Voice volume

Settings → Voice → Voice replies.

Wake sounds and spoken replies use a TTS volume separate from music. While speaking, Ava sets media volume to the TTS level, then restores it. Changing TTS volume during a reply takes effect immediately.

Setting Description Default
Media volume Current device media volume (reference)
TTS volume Level written to media volume during those replies (15%–100%) 30%
Show in Home Assistant Show a live TTS volume number entity under Configuration in Home Assistant for automations Off

Volume-key changes during a reply are applied after speech ends. This does not change Volume Follow on the media-player settings page.


Pipeline Error Messages (i18n)

Ava displays localized toast messages for voice pipeline errors. Error messages are determined by the error code from HA and displayed in the user's locale.

Supported languages: English (default), Chinese (zh), German (de), Russian (ru), Portuguese (pt), Vietnamese (vi).

Locale detection: Ava uses LocaleUtils to detect the system locale at runtime. If the locale is not one of the supported languages, English is used as fallback.

Error Codes and Messages

Error Code Pattern String Key English Message
stt-no-text pipeline_error_no_speech Speech detected, no text
timeout / timed-out pipeline_error_no_response Response timed out, possibly network delay or busy service
stt-* / intent-* / tts* pipeline_error_config Voice processing paused, config may need a look
cloud-auth pipeline_error_cloud_auth Cloud auth issue, re-login
wake / duplicate pipeline_error_wake Wake signal anomaly, retry
(other) pipeline_error_unknown Temporary issue, will retry shortly
(HA disconnected) pipeline_error_ha_disconnected Server offline, check network
(HA start failed) pipeline_error_ha_start_failed Pipeline init issue, check config
(TTS playback) pipeline_error_tts_playback Voice reply playback failed: TTS address timed out, check the address

Localized Examples

Language pipeline_error_no_speech pipeline_error_tts_playback
English Speech detected, no text Voice reply playback failed: TTS address timed out, check the address
Chinese 检测到语音,但无文本 语音回复播放失败:TTS 地址超时请检查地址
German Sprache erkannt, kein Text Sprachantwort-Wiedergabe fehlgeschlagen: TTS-Adresse timed out, Adresse prüfen
Russian Речь есть, текста нет Ошибка воспроизведения голосового ответа: тайм-аут адреса TTS, проверьте адрес
Portuguese Voz detectada, sem texto Falha na reprodução da resposta por voz: endereço TTS expirou, verifique o endereço
Vietnamese Có giọng nói, không có văn bản Phát phản hồi giọng nói thất bại: địa chỉ TTS hết thời gian, kiểm tra địa chỉ

TTS Playback Volume and Ducking

  • TTS playback uses USAGE_MEDIA with AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
  • When TTS starts, Ava requests audio focus, which may duck other media players
  • On TTS completion, audio focus is released, allowing other media to resume
  • Non-root Android cannot give TTS a separate volume path, so Ava temporarily writes system media volume (STREAM_MUSIC) to the TTS level during a reply, then restores the remembered system volume when speech ends
  • Changing TTS volume (settings or HA entity) during a reply takes effect immediately; the system volume bar shows the live device level, including that temporary write

Settings Reference

All TTS-related settings are in Settings → Voice → Voice Replies.

Setting Description Default
TTS mode Standard or Streaming Standard
Floating subtitle overlay Show subtitles in floating window during conversations Off
System volume Live device media volume; adjustable for comparison; remember-and-restore around TTS
TTS volume Level used while speaking; temporarily written to system media volume 30%
Show in Home Assistant Show a live TTS volume number entity under Configuration in Home Assistant for automations Off
Usage guide Explains Android limits, comparison, restore, and HA automation examples

Recommended TTS Engine

AI Hub TTS (Kokoro)

AI Hub TTS is a Home Assistant add-on based on the Kokoro model. It is the recommended TTS engine for Ava.

Features:

  • Fully offline — no internet required after model download
  • 26 high-quality voices
  • CPU inference, generation < 1 second
  • Wyoming protocol with auto-discovery — HA picks it up automatically
  • Memory usage < 500 MB

Installation:

  1. In Home Assistant: Settings → Add-ons → Add-on Store
  2. Click ⋮ → Repositories → Add https://github.com/truemanshum/ai-hub-tts
  3. Refresh and install AI Hub TTS
  4. First start auto-downloads the model (~500 MB)
  5. Settings → Voice Assistants → select AI Hub TTS as the TTS engine

Configuration:

voice: af_heart      # Voice selection
sample_rate: 24000   # Sample rate
debug: false          # Debug mode

With Ava: Works in both Standard and Streaming TTS modes. For Streaming TTS, ensure the HA voice assistant pipeline has streaming output enabled.


Preserve Original TTS URL (0.7.3)

By default, Ava rewrites TTS URLs to use the LAN address for faster local playback. In HTTPS setups or reverse-proxy configurations, this rewriting can break playback — the rewritten URL may not be reachable or may fail certificate validation.

Preserve original TTS URL disables the rewriting. Ava plays from the URL exactly as Home Assistant returns it.

Path: Settings → Voice Config → Voice Replies → Use original TTS URL


TTS Volume as HA Entity (0.7.3)

Ava's TTS volume can be exposed as a number entity in Home Assistant, allowing automations to adjust how loud Ava speaks without touching the device.

Setting Description
Show in Home Assistant Expose TTS volume as a number.* entity
TTS volume Level used while speaking; temporarily written to system media volume during TTS, then restored

Automation example:

# Speak louder at night
service: number.set_value
target:
  entity_id: number.your_device_name_tts_volume
data:
  value: 60

Back to Voice Control

Clone this wiki locally