Skip to content

fix(huddle): fade partial streaming TTS on inference failure - #6332

Draft
johnmatthewtennant wants to merge 2 commits into
mainfrom
jtennant/harden-pocket-tts-streaming
Draft

fix(huddle): fade partial streaming TTS on inference failure#6332
johnmatthewtennant wants to merge 2 commits into
mainfrom
jtennant/harden-pocket-tts-streaming

Conversation

@johnmatthewtennant

Copy link
Copy Markdown
Contributor

Context

PR #5671 added an env-gated Pocket TTS streaming path that queues decoded audio while synthesis continues. If inference fails after emitting multiple blocks, the existing error path drops the retained final block. Already queued audio then ends abruptly without the normal fade-out.

This is a bug fix for the streaming path. It also carries forward the error and cancellation hardening worth preserving from #3257 without reusing that PR's older synthesis implementation.

Summary

Finish a partially emitted stream through the existing playback-boundary decorator when inference fails. The retained tail receives the normal final fade, while previously queued speech remains intact.

Changes

  • Extracts the streaming state machine behind a private test seam that can inject exact callback outcomes.
  • Appends and fades the retained final block on inference failure.
  • Preserves prior queued speech instead of clearing the shared persistent player.
  • Keeps cancellation fail-closed: a rejected append or stop signal never flushes retained audio.
  • Covers all three stop signals, append rejection, failures before output, failures after output, and final-block fade behavior.

Related issue

No issue found. Follow-up to #5671. Supersedes the streaming error and cancellation hardening from #3257.

Testing

The deterministic regression harness simulates a Pocket inference error after two audio callbacks. The target behavior queues one block and drops the retained tail; this branch queues both blocks and fades the final sample to zero.

The live desktop app has no safe deterministic control for forcing an inference failure after audio has already been emitted, so this specific error path was not manually injected in a real huddle. Normal streaming behavior remains env-gated in this PR.

Screenshots

Not applicable. This changes the native audio pipeline and has no visual UI change.

Reviewer-reproducible examples

The reproduction branch is origin/main plus only the private test seam and regression assertions. It intentionally retains the old error behavior.

Red: target behavior drops the retained tail

git fetch origin main jtennant/repro-pocket-tts-streaming-failure
git switch --detach origin/jtennant/repro-pocket-tts-streaming-failure
. ./bin/activate-hermit
just _ensure-sidecar-stubs
cargo test --manifest-path desktop/src-tauri/Cargo.toml --lib \
  inference_failure_fades_the_retained_final_block

Observed output:

test huddle::tts::streaming::tests::inference_failure_fades_the_retained_final_block ... FAILED
assertion `left == right` failed
  left: 1
 right: 2

Green: the retained tail is queued with a fade

git fetch origin jtennant/harden-pocket-tts-streaming
git switch --detach origin/jtennant/harden-pocket-tts-streaming
. ./bin/activate-hermit
just _ensure-sidecar-stubs
cargo test --manifest-path desktop/src-tauri/Cargo.toml --lib \
  inference_failure_fades_the_retained_final_block

Observed output:

running 1 test
test huddle::tts::streaming::tests::inference_failure_fades_the_retained_final_block ... ok

test result: ok. 1 passed; 0 failed

@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/harden-pocket-tts-streaming branch from df5c133 to b348a00 Compare August 19, 2026 18:33
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/harden-pocket-tts-streaming branch 2 times, most recently from 2b01e7f to f445345 Compare August 19, 2026 18:51
Signed-off-by: John Tennant <jtennant@squareup.com>
Signed-off-by: John Tennant <jtennant@squareup.com>
@johnmatthewtennant
johnmatthewtennant force-pushed the jtennant/harden-pocket-tts-streaming branch from f445345 to 0a4010a Compare August 19, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant