Fix recurring double captions on transcribe: reset caption track on regenerate (#356/#287) - #424
Merged
Conversation
…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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 inshowingmode, Chromium keeps the previous media's active cue painted aftertrack.srcis 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:
renderTranscript) already tears the track down viaresetCaptionTrack— removes the stale<track>and inserts a fresh empty one.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:Scoped there deliberately — the live-edit sanitise path calls
generateCaptionsFromTranscriptdirectly and must not reset, or every keystroke would swap the track and churn the caption paint.caption.jsre-looks-up the track by id, so the fresh same-id element is fully compatible, andgenerateCaptionsFromTranscriptrestoresshowing/hiddenmode 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:sameElement: expected false, received true)Also
editor-core.js?v=0.8.8and bump the app version marker to0.8.8so 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 (
hidden→showing) to force the overlay to rebuild, flushing the stale::cuepaint. Guarded toshowingso it is a no-op for audio-only media (mp3/m4aare deliberately hidden) and harmless during playback. Confirmed in-browser: the lingering caption is gone.