Skip to content

Fix three bugs in the subtitle resync tool - #562

Merged
Andrews54757 merged 1 commit into
Andrews54757:mainfrom
Nawid3333:upstream-pr/subtitle-syncer
Oct 9, 2026
Merged

Andrews54757 merged 1 commit into
Andrews54757:mainfrom
Nawid3333:upstream-pr/subtitle-syncer

Conversation

@Nawid3333

Copy link
Copy Markdown
Contributor

What breaks

Three bugs in the subtitle resync tool, all user-visible:

  1. The whole track is redrawn every frame. renderTracks() picked the
    cues to draw with

    return cue.startTime <= maxTime || cue.endTime >= minTime;

    which is true for every cue: any cue starts before the right edge
    (start <= max) or ends after the left edge (end >= min). The
    intended window test is the conjunction - cues that overlap the visible
    range - so the entire track stayed in the DOM and every cue was
    repositioned on every frame, instead of only the handful on screen.

  2. Every shift key press threw a TypeError. shiftSubtitles() called
    this.onVideoTimeUpdate(), a method SubtitleSyncer does not have. The
    EventEmitter caught and logged it, so the shift still applied, but the
    console filled with

    TypeError: this.onVideoTimeUpdate is not a function
    
  3. A right-click started a drag. The track started grabbing on any
    mouse button. After a right-click, the context menu swallows the
    mouseup, so the track kept following the pointer with no button held.

The fix

  • Filter with && - the cues that overlap the visible window:

    return cue.startTime <= maxTime && cue.endTime >= minTime;
  • Drop the call to the method that does not exist. The timeline redraws on
    its own; the cues in view are refreshed immediately instead:
    this.lastUpdate = 0 (the render throttle) before re-rendering.

  • Left button only, as the time ticks in the same UI already do:
    if (e.button !== 0) return;

  • After a keyboard shift, lastUpdate = 0 also makes cues that moved into
    view appear right away instead of up to 500 ms later.

Diff: 1 file, 8 insertions, 2 deletions.

Why this can't break anything else

  • Blast radius of the file: SubtitleSyncer.mjs is the resync tool's
    own controller, instantiated only when the subtitle-resync UI is open.
    Normal subtitle playback (SubtitlesManager) does not run this code.
  • Change 1 is a pure filter correction: the same cues used to be drawn
    every frame; now only the overlapping ones are. A cue either overlapped
    the window or it did not - || included all of them, && includes
    exactly the intended set. Cues outside the window were invisible anyway;
    they were just kept in the DOM.
  • Change 2 removes a call to a method that does not exist - there is no
    behavior to preserve. The redraw it was meant to trigger is covered by
    lastUpdate = 0 on the next render tick, which is the file's own
    throttle mechanism.
  • Change 3 restricts an input from "any button" to "left button only" -
    strictly fewer grab starts, and the tick marks elsewhere in the same UI
    already used the identical guard.

Verification

  • Build: npm ci + node localescript.mjs + node build.mjs (this
    repo's own build path) - all three targets build.
  • Each fix exercised: cue window - a track whose cues straddle the
    visible range now renders only overlapping cues; shift keys - no
    TypeError in the console, cues repositioned immediately; right-click on
    the track - context menu opens, no drag follows.
  • Lint: eslint with this repo's .eslintrc.js (google config): no
    problems.
  • Diff shape: git diff --numstat against main:
    8 2 chrome/player/ui/subtitles/SubtitleSyncer.mjs.

- renderTracks() picked the cues to draw with `start <= max || end >= min`,
  which is true for every cue, so the whole track was kept in the DOM and
  repositioned on every frame. It now uses `&&`, the cues that overlap the
  visible window.
- shiftSubtitles() called this.onVideoTimeUpdate(), which SubtitleSyncer
  does not have, so every shift key press while the tool was open threw a
  TypeError (caught and logged by EventEmitter).
- The track started a drag on any mouse button. After a right-click the
  context menu swallows the mouseup and the cues followed the pointer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

2 participants