Skip to content

berd-call: wait for playback room instead of failing long Siri replies - #405

Closed
johnmatthewtennant wants to merge 1 commit into
mainfrom
jtennant/berd-call-long-siri-replies
Closed

johnmatthewtennant wants to merge 1 commit into
mainfrom
jtennant/berd-call-long-siri-replies

Conversation

@johnmatthewtennant

Copy link
Copy Markdown
Contributor

Summary

A Siri reply longer than about a minute of speech failed outright with Siri synthesis exceeded its bounded PCM queue. Siri renders audio faster than playback drains it, and the native callback refused new audio once 60 seconds were pending, which cancelled the reply.

The callback now waits for room when that bound is full. Playback frees room as it goes, so long replies play to the end. The bound still caps memory, and shorter replies never wait on playback. Cancelling a reply releases a waiting callback.

Related issue

None.

Testing

  • Against real Siri (voice Aaron) with a reply well over a minute, holding playback while Siri rendered ahead: the reply failed with exceeded its bounded PCM queue before the change and completed after it.
  • New unit test: a reply of 1.5 times the bound, with playback starting only once the bound is full, plays every frame. It failed before the change.
  • New unit test: a callback waiting on a full queue returns as soon as the reply is cancelled.

Siri renders faster than playback drains, and the native callback
failed the whole reply once 60 seconds of audio were pending. It now
waits for room when the bound is full and keeps it as a memory cap.

Signed-off-by: John Tennant <jtennant@block.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnmatthewtennant

Copy link
Copy Markdown
Contributor Author

🤖 Folded into #416 for review and merge.

johnmatthewtennant added a commit that referenced this pull request Oct 22, 2026
…rols (#416)

## Summary

Several improvements to Berd Call’s speech playback, Siri voices,
microphone controls and experimental Realtime Spokesperson. These also
provide the voice preview and advanced Spokesperson options used by the
Buzz Berd Call plugin.

**Speech playback and recovery**
- Long Siri replies play to completion through a bounded playback queue.
- Session restarts wait for playing and queued speech, including
Spokesperson audio, for up to 60 seconds. End Call interrupts
immediately.
- Failed status sounds release microphone suppression, and native render
errors are detected even when the audio engine reports running.
- Calls shut down cleanly when their stream reader exits. PCM overflow
diagnostics preserve the original error and input ordering.

**Siri voices**
- Download voices from the menu bar, with support for the macOS 27
download service and earlier versions.
- Keep existing voices installed when downloading another, recognize
installed assets consistently, and display names for code-named voices.
- Preview Apple’s voice samples with `berd-call voices preview`;
stopping the preview process stops playback.

**Microphone controls**
- Automatic input muting persists across session restarts and follows
output-device changes, using device names with CoreAudio metadata as a
fallback.

**Experimental Realtime Spokesperson**
- Group the experimental toggle and voice controls above End Call,
persist the selected voice, and expose advanced settings through
`--spokesperson-options`.
- Bring playback loudness close to Siri with gain limiting.
- Abort voice changes promptly, recover interrupted input resets, and
acknowledge pending input controls in order before shutdown.
- Allow separate Realtime, transcription and synthesis keys through
`OPENAI_REALTIME_API_KEY`, `OPENAI_STT_API_KEY` and
`OPENAI_TTS_API_KEY`, with `OPENAI_API_KEY` as the shared fallback.

### Related issue

Related Berd Call work: [persistent Auto input
muting](#403), [long Siri
replies](#405) and [separate OpenAI
service keys](#415).

### Testing

- Native Siri downloads preserve previously installed voices; voice
samples play through the default output and stop on SIGTERM. A Siri
reply longer than a minute plays to completion.
- Native call checks verify automatic muting across restarts and
output-device changes. Deterministic regressions verify that restarts
wait for audio ingress and playback drain.
- Local Realtime integration verifies voice-change cancellation, reset
ordering and shutdown acknowledgements. The production CLI audio pipe
verifies gain limiting across streamed chunks.
- Captured Spokesperson audio measures -19.0 LUFS against Siri’s -18.8
LUFS, with a -0.4 dBTP peak.
- Recovery regressions exercise failed status cues and native render
errors. Local HTTP integration verifies service-specific key selection
and shared-key fallback.

---------

Signed-off-by: Nora <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
Signed-off-by: John Tennant <jtennant@block.xyz>
Signed-off-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz>
Signed-off-by: Quinn <a0d9f90f86da5f023099d22b8e3599af162d9423a422d8f385a12815de879cf2@buzz.block.builderlab.xyz>
Co-authored-by: Nora <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz>
Co-authored-by: Quinn <a0d9f90f86da5f023099d22b8e3599af162d9423a422d8f385a12815de879cf2@buzz.block.builderlab.xyz>
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