Skip to content

fix(voice): place recorded audio where it actually played - #6921

Open
longcw wants to merge 1 commit into
mainfrom
longc/recording-real-playout
Open

fix(voice): place recorded audio where it actually played#6921
longcw wants to merge 1 commit into
mainfrom
longc/recording-real-playout

Conversation

@longcw

@longcw longcw commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Problem

RecorderIO rebuilds the agent channel by inference. It collects the frames it forwarded, places them from the wall-clock moment playback_finished arrives, and pads the difference with silence. Nothing measures where the audio really went.

Four conditions break that inference: a sink that runs dry inside a segment, a late flush, audio discarded on pause(), and a microphone that stops delivering. Each one moves the audio, and none of them records the gap. A slow TTS or a muted participant may hit it.

Fix

A sink that owns its playback device now reports where its audio went. AudioOutput gains playback_progressed next to playback_started and playback_finished, and _ParticipantAudioOutput reports one run at a time off its own queue. Each report is past tense, so it is never revised, and a jump in its offset describes audio the sink discarded rather than played.

RecorderIO places both channels on one absolute timeline and leaves unwritten time silent. When a sink reports nothing, the recorder uses its segment endpoints instead, which is all a remote avatar worker can know. That removes the pause reconstruction, the end-anchored padding, and the playback_position truncation.

RecorderIO built the agent channel by re-composition: it collected the
frames it forwarded, then placed them from the wall-clock moment
playback_finished arrived and padded the difference with silence. Nothing
measured where the audio went, so a sink that ran dry mid-segment, a late
flush, audio discarded on pause, or a microphone that stopped delivering
all moved the audio around instead of recording the gap.

Sinks that own their playback device now report it. AudioOutput gains
playback_progressed alongside playback_started and playback_finished, and
_ParticipantAudioOutput reports one run at a time off its own queue:
where the run sits in the segment, and when it began to play. Reports are
past tense, so they are never revised, and an offset jump describes audio
that was discarded rather than played. A sink that reports nothing is
described by its segment endpoints instead, which is all a remote avatar
worker can know.

RecorderIO places both channels on one absolute timeline and leaves
unwritten time silent. That drops the pause reconstruction, the
end-anchored padding and the playback_position truncation.
@longcw
longcw requested a review from a team as a code owner August 20, 2026 09:22

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

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