[P1] ZARA-010 — Make every configured TTS provider produce playable audio or fail cleanly #11

Closed
opened 2026-07-18 19:19:49 +00:00 by lost-rob0t · 0 comments
lost-rob0t commented 2026-07-18 19:19:49 +00:00 (Migrated from github.com)

Problem

TTS provider behavior is inconsistent beyond the config-name mismatch fixed in ZARA-002:

  • Piper uses --output-raw, but wake playback sends the returned bytes to soundfile, which expects a decodable container.
  • Qwen HTTP calls have no explicit client timeout and can hang a turn indefinitely.
  • Qwen upload/change methods open files without closing them.
  • Starting a new synthesis only sets the previous stop event; overlapping tasks/player processes can race.
  • TTS task failures are logged but not surfaced to the response pipeline.

Required fix

  • Define the audio format returned by each provider and decode/play it correctly.
  • Add connection/read/total timeouts and cancellation support.
  • Close file handles and HTTP sessions deterministically.
  • Enforce single-flight TTS playback with a clear replace/cancel policy.
  • Return structured synthesis/playback status without crashing the wake loop.

Required tests

  • Provider contract tests for local Piper/espeak, Qwen, Edge, and ElevenLabs using mocked subprocess/HTTP/SDK data.
  • Tests for timeout, cancellation, empty audio, invalid audio, overlapping responses, and client close.
  • Add scripts/test-tts.sh using generated fixture audio and no live provider credentials.

Acceptance

  • Each enabled provider either yields playable audio in its declared format or a bounded actionable failure.
  • A replacement utterance cannot overlap the prior player.
  • All resources close after normal completion, cancellation, and error.

Branch

fix/zara-010-tts-contracts

Dependencies

ZARA-002, ZARA-009.

## Problem TTS provider behavior is inconsistent beyond the config-name mismatch fixed in ZARA-002: - Piper uses `--output-raw`, but wake playback sends the returned bytes to `soundfile`, which expects a decodable container. - Qwen HTTP calls have no explicit client timeout and can hang a turn indefinitely. - Qwen upload/change methods open files without closing them. - Starting a new synthesis only sets the previous stop event; overlapping tasks/player processes can race. - TTS task failures are logged but not surfaced to the response pipeline. ## Required fix - Define the audio format returned by each provider and decode/play it correctly. - Add connection/read/total timeouts and cancellation support. - Close file handles and HTTP sessions deterministically. - Enforce single-flight TTS playback with a clear replace/cancel policy. - Return structured synthesis/playback status without crashing the wake loop. ## Required tests - Provider contract tests for local Piper/espeak, Qwen, Edge, and ElevenLabs using mocked subprocess/HTTP/SDK data. - Tests for timeout, cancellation, empty audio, invalid audio, overlapping responses, and client close. - Add `scripts/test-tts.sh` using generated fixture audio and no live provider credentials. ## Acceptance - Each enabled provider either yields playable audio in its declared format or a bounded actionable failure. - A replacement utterance cannot overlap the prior player. - All resources close after normal completion, cancellation, and error. ## Branch `fix/zara-010-tts-contracts` ## Dependencies ZARA-002, ZARA-009.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/zara#11
No description provided.