Skip to content

Add --save-audio flag to record streamed PCM to WAV#186

Merged
alexkroman merged 1 commit into
mainfrom
claude/tender-galileo-9pttyu
Jun 16, 2026
Merged

Add --save-audio flag to record streamed PCM to WAV#186
alexkroman merged 1 commit into
mainfrom
claude/tender-galileo-9pttyu

Conversation

@alexkroman

Copy link
Copy Markdown
Collaborator

Adds a --save-audio flag to assembly stream that tees the streamed PCM audio to a WAV file while transcribing, enabling callers to keep a verbatim recording of the audio sent to the streaming API without owning capture themselves.

Key changes

  • New aai_cli/streaming/record.py module: Implements tee_wav() generator that yields PCM chunks unchanged while writing them to disk as a 16-bit mono WAV, and validate_target() to check the output path's parent directory exists before streaming starts.

  • --save-audio CLI option: Added to aai_cli/commands/stream/__init__.py with validation that the path is writable and the parent directory exists.

  • Validation & mutual exclusivity:

    • Rejects --save-audio with --from-stdin (can't tee multiple sources to one file)
    • Rejects --save-audio with --system-audio (mic and system streams can't share one file)
    • Rejects --save-audio with --show-code (generated SDK code doesn't tee audio)
    • Validates the output path's parent directory exists before credentials/audio are opened, so path errors surface cleanly upfront
  • Integration into streaming session: StreamSession.stream_one() wraps the audio iterable with tee_wav() when save_audio is set, writing at the source's true sample rate.

  • Comprehensive test coverage:

    • Unit tests for tee_wav() behavior (unchanged passthrough, valid WAV output, early close handling, empty streams, unopenable paths)
    • Integration tests for the flag (tees streamed PCM correctly, not written when unset, rejects incompatible flag combinations, validates parent directory)

Implementation details

The tee is implemented as a generator that writes each chunk to disk and yields it onward unchanged, ensuring the API receives exactly what was captured. The WAV header's length fields are patched on generator close (including via GeneratorExit on Ctrl-C), so even interrupted runs leave valid, playable WAV files. The recording is always mono 16-bit PCM at the source's sample rate, matching the shape the streaming API receives.

https://claude.ai/code/session_01MiPAW6mr1pYQuAE123HGxD

Tee exactly the bytes sent to the streaming API to a 16-bit mono WAV while
transcribing, without altering the live transcript. This lets a downstream
consumer (e.g. an ensemble that compares live turns against an async
re-transcribe) keep the audio without owning capture itself.

- New streaming/record.py: tee_wav() writes each chunk at the source's true
  rate and yields it onward; the header is patched on exhaustion or early
  close (Ctrl-C) so a partial recording is still a valid WAV. validate_target()
  rejects a missing parent dir up front, before credentials.
- StreamSession gains save_audio; the single-source path tees in stream_one.
- Rejected combinations (clear usage errors): --system-audio/--system-audio-only
  (two streams can't share one file), --from-stdin (batch is many sources), and
  --show-code (generated SDK code doesn't tee).

https://claude.ai/code/session_01MiPAW6mr1pYQuAE123HGxD
@alexkroman alexkroman enabled auto-merge June 16, 2026 19:39
@alexkroman alexkroman added this pull request to the merge queue Jun 16, 2026
Merged via the queue into main with commit 394cd29 Jun 16, 2026
19 checks passed
@alexkroman alexkroman deleted the claude/tender-galileo-9pttyu branch June 16, 2026 19:45
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.

2 participants