Skip to content

fix: drop caption segments that span a recording pause - #972

Open
nabossha wants to merge 2 commits into
attendee-labs:mainfrom
nabossha:fix/paused-captions-leak
Open

nabossha wants to merge 2 commits into
attendee-labs:mainfrom
nabossha:fix/paused-captions-leak

Conversation

@nabossha

@nabossha nabossha commented Aug 21, 2026 •

Copy link
Copy Markdown

What

Pausing a recording is supposed to keep the paused portion of the meeting out of all
artifacts. That works for the media pipeline and per-participant audio, but closed-caption
transcription leaks the paused speech
: captions arrive as growing segment texts keyed by
deviceId:captionId, and WebBotAdapter.handle_caption_update only drops updates while
recording_paused is set. The first caption update after resume carries the whole accumulated
segment — including everything said during the pause — and is recorded as an utterance with
the resume timestamp.

Reproduction (Google Meet, meeting_closed_captions)

  1. Bot in joined_recording, speaker talking.
  2. POST /bots/{id}/pause_recording, say something ("this is secret"), then
    POST /bots/{id}/resume_recording.
  3. GET /bots/{id}/transcript → "this is secret" appears verbatim, timestamped at the
    moment of resume.

(The async transcription path built from per-participant audio chunks is clean — those frames
are dropped while paused — which makes the caption leak easy to miss.)

Fix

New PausedCaptionFilter (no dependencies): any caption segment that sends an update during
a pause is frozen for good — its updates keep being dropped after resume, so the buffered
paused speech never reaches the caption manager. Segments that start after the resume pass
normally. Wired into WebBotAdapter.handle_caption_update, so it covers every platform that
uses the shared caption path.

The words spoken before the pause in a spanning segment are unaffected: they were already
upserted before the pause hit.

Known limitation: a segment that emits no update at all during a very short pause (<~1 s)
cannot be detected. In practice caption updates arrive continuously while someone speaks.

Tests

  • bots/tests/test_paused_caption_filter.py — plain unittest, 4 cases: spanning segment
    stays dropped after resume, new segment after resume passes, per-device keying, no-op
    without pause.
  • The existing pause/resume caption test in test_google_meet_bot_2.py still passes: it uses
    distinct caption ids per phase, which is exactly the case that keeps working.

version.json bumped 1.64.1 → 1.64.2 (fix).

Update (rebased onto v1.82.6)

Rebased onto 3cbeb69f. No functional change: the fix is identical, only the import
context in web_bot_adapter.py moved with the rebase. The version bump now lives in its own
commit and targets 1.82.7 (patch over 1.82.6 for this fix: PR). Ruff is clean; the filter
tests plus the google_meet and teams suites pass in Docker.

@nabossha
nabossha requested a review from a team as a code owner August 21, 2026 13:45
@noah-duncan

Copy link
Copy Markdown
Collaborator

Thanks! Very thoughtful of you to notice this.

Closed captions arrive as growing segment texts keyed by deviceId:captionId.
Ignoring caption updates only while the recording is paused is not enough to
keep paused speech out of the transcript: the first update after resume
carries the whole accumulated segment text, including the words spoken
during the pause, and gets recorded with the resume timestamp.

Freeze any segment that sends an update during a pause and keep dropping it
after resume; segments that start after the resume pass normally. Applies to
all platforms using WebBotAdapter caption handling.

Reproduced on Google Meet with meeting_closed_captions transcription:
speech during a pause showed up verbatim in the transcript after resume.
@nabossha
nabossha force-pushed the fix/paused-captions-leak branch from e7eabfd to fb3272e Compare October 8, 2026 22:17

This branch has not been deployed

No deployments
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.

3 participants