Skip to content

Fix recurring double captions on transcribe: reset caption track on regenerate (#356/#287) - #424

Merged
maboa merged 2 commits into
mainfrom
fix/caption-track-reset
Jul 28, 2026
Merged

Fix recurring double captions on transcribe: reset caption track on regenerate (#356/#287)#424
maboa merged 2 commits into
mainfrom
fix/caption-track-reset

Conversation

@maboa

@maboa maboa commented Jul 28, 2026

Copy link
Copy Markdown
Member

Problem

A newly transcribed clip shows its subtitles overlaid on the previous clip's subtitles — the recurring "double captions" of #356/#287, which earlier fixes never fully closed.

Root cause

The <video> and its <track id="hyperplayer-vtt"> are reused across media swaps. Left in showing mode, Chromium keeps the previous media's active cue painted after track.src is reassigned (the new media starts at time 0 where often no cue is active yet, so the region never repaints).

There are two caption-(re)generation paths and only one was fixed:

  • Recents / file load (renderTranscript) already tears the track down via resetCaptionTrack — removes the stale <track> and inserts a fresh empty one.
  • Transcribe / regenerate — every transcription client (AssemblyAI, Parakeet, Deepgram, Whisper) dispatches hyperaudioGenerateCaptionsFromTranscript, and that handler reused the existing track and only reassigned .src. That's the exact stale-paint pattern the reset was invented to prevent, so the transcribe path kept regressing.

Fix

Reset the caption track in hyperaudioGenerateCaptionsFromTranscript, the from-scratch regenerate entry point:

let track = (typeof resetCaptionTrack === 'function' && resetCaptionTrack())
  || document.querySelector('#hyperplayer-vtt');

Scoped there deliberately — the live-edit sanitise path calls generateCaptionsFromTranscript directly and must not reset, or every keystroke would swap the track and churn the caption paint. caption.js re-looks-up the track by id, so the fresh same-id element is fully compatible, and generateCaptionsFromTranscript restores showing/hidden mode afterward.

Test

Adds __TEST__/e2e/caption-track-reset.spec.mjs — drives two consecutive regenerations and asserts the track is torn down and rebuilt (fresh element, exactly one <track> / TextTrack). Verified:

  • passes on the fix
  • fails on the reverted one-line change (sameElement: expected false, received true)
  • passes again once restored

Also

  • Cache-bust editor-core.js?v=0.8.8 and bump the app version marker to 0.8.8 so browsers pick up the change.

Fixes #356. Fixes #287.

Update: second half of the fix (fcc323c)

Resetting the <track> drops the old cue's data, but on a paused video the browser never re-composites its native caption overlay, so the previous cue's pixels stayed stranded on screen under the new captions. The load path avoids this via the media-reload relayout; the transcribe path leaves the already-loaded video paused, so nothing repaints the overlay.

Fix: after regenerating, toggle the caption track's display mode (hiddenshowing) to force the overlay to rebuild, flushing the stale ::cue paint. Guarded to showing so it is a no-op for audio-only media (mp3/m4a are deliberately hidden) and harmless during playback. Confirmed in-browser: the lingering caption is gone.

maboa added 2 commits July 28, 2026 17:13
…n't linger (#356/#287)

The <video> and its <track id="hyperplayer-vtt"> are reused across media swaps.
Left in 'showing' mode, Chromium keeps the previous media's active cue painted
after track.src is reassigned, so a freshly transcribed clip shows its captions
on top of the old clip's line — the recurring "double captions" of #356/#287.

The Recents/file-load path (renderTranscript) already fixed this via
resetCaptionTrack, which removes the stale <track> and inserts a fresh empty one.
But every transcription client dispatches hyperaudioGenerateCaptionsFromTranscript,
and that handler reused the existing track and only reassigned .src — the exact
stale-paint pattern the reset was written to prevent. So the load path was clean
while the transcribe path kept regressing.

Reset the track in hyperaudioGenerateCaptionsFromTranscript, the from-scratch
regenerate entry point. Scoped there deliberately: the live-edit sanitise path
calls generateCaptionsFromTranscript directly and must not reset, or every
keystroke would swap the track and churn the caption paint. caption.js re-looks-up
the track by id, so the fresh same-id element is fully compatible, and
generateCaptionsFromTranscript restores showing/hidden mode afterward.

Adds an e2e regression test that drives two consecutive regenerations and asserts
the track is torn down and rebuilt (fresh element, one track / TextTrack); it
fails on the pre-fix reused-track behaviour.

Cache-bust editor-core.js?v=0.8.8 and bump the app version marker to 0.8.8.
…ptions don't linger (#356/#287)

Resetting the <track> element (previous commit) drops the old cue's DATA, but on
a PAUSED video the browser never re-composites its native caption overlay, so the
previous cue's PIXELS stay stranded on screen under the new captions. The load
path avoids this because loading new media forces a full video relayout; the
transcribe/regenerate path leaves the already-loaded video paused, so nothing
repaints the overlay.

After regenerating, toggle the caption track's display mode (hidden -> showing) to
force the overlay to rebuild, flushing the stale paint. Guarded to 'showing' so it
is a no-op for audio-only media (mp3/m4a are deliberately hidden) and harmless
during playback. Confirmed in-browser: the lingering caption is gone.

Extends the regression test to assert the toggle path settles back on 'showing'
(the native ::cue paint itself is not inspectable headlessly).

Cache-bust editor-core.js?v=0.8.9 and bump the app version marker to 0.8.9.
@maboa
maboa merged commit 6bcc706 into main Jul 28, 2026
1 check passed
@maboa
maboa deleted the fix/caption-track-reset branch July 28, 2026 15:42
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.

Captions from the previous media aren't cleared when loading a file from Recents Occassionally two sets of captions are shown contemporarily

1 participant