Skip to content

fix(voice): report played audio across an audio sink swap - #6967

Open
longcw wants to merge 1 commit into
mainfrom
longc/sink-swap-progress
Open

fix(voice): report played audio across an audio sink swap#6967
longcw wants to merge 1 commit into
mainfrom
longc/sink-swap-progress

Conversation

@longcw

@longcw longcw commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Problem

replace_audio_tail can replace the audio sink while a segment still plays.
Each sink counts its playback from the first frame it received, not from the start of the segment.
The recorder therefore put the audio of a new sink at the start of the segment, and it dropped what a detached sink played.
A sink that reports no runs of its own, such as a remote avatar worker, lost all of its audio once another sink reported.

Fix

Room I/O now reports its playhead when it clears its buffer, because a sink that the proxy detaches never reaches the playout wait.
The proxy also hears progress across the clear, and it moves each report onto the segment timeline.
For a sink that says nothing, the proxy reports on its behalf, and everything the sink received counts as played.
playback_started and playback_finished still go quiet before the clear, because they decide when a segment ends and that call belongs to the proxy.

When the proxy detaches a remote sink after a flush, the recording still counts its whole segment as played. That is all that is knowable once the sink is gone.

follow up of #6921 (comment)

Replacing the audio tail mid-segment left the recording wrong three ways.
A sink attached part-way through counts from its own zero, so its reports
landed at the start of the segment. A detached sink's playhead was never
heard, since the proxy stopped listening before clearing it. And a sink
that reports no runs of its own, such as a remote avatar worker, lost its
whole stretch once any other sink had reported.

Room I/O now reports its playhead from clear_buffer(), which a detaching
sink reaches when the playout wait does not. The proxy keeps listening for
progress across that clear, rebases each report onto the segment, and
reports for a sink that says nothing: all it was given counts as played,
the same assumption made when a segment ends on it.

playback_started and playback_finished stay unsubscribed before the clear.
They decide when a segment ends, which is the proxy's call to make, and a
clear can finish a segment that is still running.

Detaching a remote sink after a flush still records its whole segment as
played, which is all that is knowable once it is gone.
@longcw
longcw requested a review from a team as a code owner August 24, 2026 11:05

@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 potential bugs to report.

View in Devin Review to see 1 additional finding.

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