Repository navigation
Add Stereo Call Recording Core For STS - #1596
Conversation
The agreed scope from the TTS/STT/STS work, as a foundation rather than a reachable feature: nothing wires this to a call yet. Left is the person and right is the bot. A mono mix is no use for the one thing a call recording is for, which is working out afterwards who said what, and the bot's own voice reaches the microphone through the room anyway, so a mix cannot even separate them reliably. The two sides are not the same rate, which is the thing most likely to ship broken: the capture path resamples the microphone to 16 kHz while the providers speak back at their own rate, and Gemini is 24 kHz. One WAV has one sample rate, so each track is brought to the file's rate before the interleave. Writing the 24 kHz track in beside 16 kHz audio plays the bot fast and an octave high, which would make a debugging recording useless. Uncompressed WAV on purpose: this is off by default and exists to find out what a call actually said, so lossless means evidence rather than a lossy copy of it, and it is the only part verifiable without a live microphone. 26 tests, no platform fakes needed. Co-authored-by: Jay Wedgeworth <12656028+jaywedgeworth22@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
| Autofix run https://github.com/Simple-With-Us/BotFleet/actions/runs/42158134143 started for `sentry[bot]`'s tagged request. Owner/sentry request: exempt from the per-bot cap (owner rule 2026-10-20). |
…ate, freeze on empty stop, release raw audio, typed-array WAV fill, unique call-id file names
…ount frames past it, no unbounded silence allocation
|
Follow-up on the review replies, head 3516afe: this adds a behavior the first push did not have, so it is recorded here. Each track is now capped at 3600 s of audio ( Limits: a call longer than an hour records only its first hour on that track, and the caller has to read Evidence: |
This comment has been minimized.
This comment has been minimized.
…inite cap validation, release before WAV build, build failures contained, cappedFrames, monotonic default clock, fake clocks in tests
… the monotonic default clock
|
Correction to two replies on the previous review round (head d007c5d): two things I said were untested now have tests.
|
… optional chaining
|
@kody start-review Please review head ec7dbb5. The 10 threads from your last review are fixed or answered with evidence and resolved. This head changes behavior (bot-only gap padding, silence stored as counts, finite cap validation, release before WAV build, monotonic default clock), so it needs a fresh look. CI is green. |
Kody Review CompleteGreat news! 🎉 Keep up the excellent work! 🚀 Kody Guide: Usage and ConfigurationInteracting with Kody
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
Refs AFC-618
Summary
Adds core STS call-recording primitives that produce lossless, uncompressed stereo WAV files for post-call debugging, with the person on the left channel and the bot on the right so speakers remain distinguishable. The source documents recording as off by default and retains lossless audio as debugging evidence.
src/lib/sts/recorder.tsrecords user and bot PCM16 audio independently, copies reused decode buffers, drops incomplete trailing bytes, and contains recording failures so they do not interrupt a call.src/lib/sts/recorder.test.tsadds coverage for WAV headers and sizes, channel placement, silence padding, empty and truncated input, reused buffers, finalized recordings, elapsed time, resampling, mixed sample rates, file naming, and retention boundaries.No test execution results or live-call runtime verification are reported.
Unresolved Review Findings
The automated review reports eight findings: three high severity and five medium severity.
null as never, bypassing TypeScript’s frame-type check.stop()before any audio is recorded does not freeze the recorder, allowing subsequent writes.SAFE_NAMErule.Summary
droppedFrames.Tests
Open review findings
The supplied automated review reported 10 unresolved findings: 9 medium and 1 low.
maxTrackSecondscan bypass or defeat the recording cap.stop()to permanently lose the recording.droppedFramescombines rate errors with recording-cap rejections.Summary
Updates the STS stereo call recorder core that captures user and bot audio into one WAV with left=user and right=bot, aligned on a shared clock and emitted at the recording sample rate. The diff is limited to the recorder module and tests; no STS call-path integration is included.
Changes
droppedFramescounts all refused frames and newcappedFramescounts only cap refusals.maxTrackSecondsvalues (NaN, zero, negative, infinite) fall back toMAX_TRACK_SECONDS, preventing an unbounded cap or a cap that discards every frame.performance.now()when available withDate.now()fallback, so wall-clock steps do not change recording placement or duration.stop()releases raw track chunks before allocating the WAV to lower peak memory, and catches WAV build failures so teardown receivesnullinstead of an exception; a failed build loses that recording and laterstop()calls returnnull.stop()remains idempotent.buildWavinjection point for failure-path testing.Tests
nowfunction.Review
Automated code review reported no issues in the reviewed changes.