Skip to content
All guides

How to Fix Out-of-Sync Subtitles: Shift, Stretch and Re-Time

Diagnose why subtitles are out of sync and fix them properly: shift all cues by a constant offset, stretch timing to correct frame-rate drift, and re-time individual sections after edits.

  • timing
  • sync
  • srt

Out-of-sync subtitles are one of the most common subtitle problems, and one of the most annoying for viewers. The good news: almost every sync problem falls into one of three patterns, and each has a specific, mechanical fix. The trick is diagnosing which one you have before you start dragging cues around.

Step 1: Diagnose the type of drift

Pick three moments in the video — one near the start, one in the middle and one near the end. At each, note how far the subtitle is from the spoken line. Write it down as a number: “+2.0 s late”, “−0.5 s early”.

Then compare:

What you measureDiagnosisFix
Same offset at start, middle and endConstant offsetShift all cues
Offset grows steadily over timeLinear drift (usually frame rate)Stretch between two sync points
Fine, then suddenly wrong after a pointEdit mismatch (cut or added footage)Shift only from that point on
Random errors throughoutBad alignmentRe-time cue by cue, or regenerate

Don’t skip the measurement. Applying a constant shift to a file with linear drift fixes one part of the video and breaks the rest.

Fix 1: Constant offset — shift everything

A constant offset usually happens when subtitles were made for a version of the video with a different intro, a logo sting or a few seconds of black at the start.

The fix is to add or subtract the same amount from every timestamp. If the subtitles appear 2.0 seconds late, shift them by −2.0 s.

Testing the offset in a player

Before changing the file, find the exact value in a player:

  • VLC: press G and H to move the subtitle delay in 50 ms steps while the video plays. The current delay is shown on screen.
  • mpv: press z and Z (Shift+z) to adjust subtitle delay in 100 ms steps.

Once it looks right, use that value to fix the file permanently — player settings don’t travel with the file.

Shifting with FFmpeg

FFmpeg can apply an offset while rewriting a subtitle file:

# Subtitles are 2 seconds early: delay them by 2 seconds
ffmpeg -itsoffset 2 -i subs.srt -c copy subs_fixed.srt

A negative -itsoffset moves subtitles earlier, but cues that would end up before zero can be dropped or clamped, so check the beginning of the result.

Shifting with a script

If you prefer to understand exactly what happens, a short Python script does the job:

import re
from datetime import timedelta

OFFSET = timedelta(seconds=-2.0)
pattern = re.compile(r"(\d{2}):(\d{2}):(\d{2}),(\d{3})")

def shift(m):
    h, mi, s, ms = map(int, m.groups())
    t = timedelta(hours=h, minutes=mi, seconds=s, milliseconds=ms) + OFFSET
    t = max(t, timedelta(0))
    total_ms = int(t.total_seconds() * 1000)
    h, rem = divmod(total_ms, 3_600_000)
    mi, rem = divmod(rem, 60_000)
    s, ms = divmod(rem, 1000)
    return f"{h:02}:{mi:02}:{s:02},{ms:03}"

with open("subs.srt", encoding="utf-8") as f:
    text = f.read()

with open("subs_fixed.srt", "w", encoding="utf-8") as f:
    f.write(pattern.sub(shift, text))

Fix 2: Linear drift — stretch the timing

If subtitles start in sync but get progressively later (or earlier), the timing needs to be scaled, not just shifted. The classic cause is a frame-rate mismatch: subtitles timed for one version of a video being used with another.

Common ratios:

Subtitle timed forVideo plays atScale factor
23.976 fps25 fps (PAL speed-up)23.976 ÷ 25 ≈ 0.959
25 fps23.976 fps25 ÷ 23.976 ≈ 1.043
24 fps23.976 fps24 ÷ 23.976 = 1.001

PAL speed-up (playing 24 fps film at 25 fps) makes the whole video about 4% shorter, which is why the error becomes obvious within a few minutes. The 24 → 23.976 mismatch is tiny — about 3.6 seconds over an hour — so it may only show up late in long videos.

Two-point synchronisation

You don’t need to know the cause to fix linear drift. You only need two reference points:

  1. Find a line near the start and note its current subtitle time (old₁) and the time it is actually spoken (new₁).
  2. Do the same for a line near the end (old₂, new₂).

Every timestamp t then becomes:

scale  = (new₂ − new₁) / (old₂ − old₁)
t_new  = new₁ + (t − old₁) × scale

This handles offset and drift at the same time. Pick reference lines that are clearly spoken and far apart — the further apart, the more accurate the result.

Desktop tools such as Subtitle Edit offer this as “point synchronisation”, and it is a core feature of subtitle studios like CutMySub.

Fix 3: Edit mismatch — shift from a point onward

Sometimes subtitles are perfect for the first ten minutes, then jump out of sync and stay that way. That almost always means footage was cut or added at that point: an ad break removed, a scene trimmed, a sponsor segment inserted.

To fix it:

  1. Find the first cue that is wrong.
  2. Measure the new offset from that point.
  3. Shift only that cue and everything after it.
  4. Check the end of the video. If there’s another jump, repeat for the next segment.

If footage was removed, some cues may now refer to content that no longer exists. Delete those, and check nothing overlaps at the join.

Fix 4: Bad alignment — re-time cue by cue

If errors are random — some cues early, some late, some fine — the problem is the timing itself, not a global offset. This is common with old fan-made files and some auto-generated captions.

Options:

  • Regenerate the timing. Some tools can re-align existing text to the audio (“forced alignment”), which keeps your corrected words but recomputes the timestamps.
  • Re-time manually on a waveform. Speech shows up clearly as peaks; drag each cue’s start to the beginning of the peak and its end to where the speech stops.

When re-timing by hand, a few guidelines keep things readable:

  • Start a cue at the first syllable — a frame or two early is fine.
  • Keep at least a short gap between consecutive cues (many style guides use two frames) so viewers notice the change.
  • Don’t leave cues on screen across a shot change if you can avoid it.
  • Avoid cues shorter than about one second.

Preventing sync problems in the first place

  • Generate subtitles from the final cut. Captioning a rough cut guarantees you’ll be fixing sync later.
  • Keep the frame rate consistent. Export the video at the same frame rate the subtitles were timed against.
  • Start at zero. If your export adds black frames or a bumper at the start, add them before captioning.
  • Version your files. Name subtitle files to match the video version they belong to (episode3_v2_final.srt).

Quick checklist

  1. Measure the offset at the start, middle and end.
  2. Same everywhere → shift.
  3. Growing over time → two-point stretch.
  4. Sudden jump → shift from that point.
  5. Random → re-align or re-time manually.
  6. Re-check the start, end and any joins before publishing.

If you are also splitting or joining files as part of the fix, see how to split or merge SRT files, which covers re-numbering and offsets at the join.

· srt

How to Split or Merge SRT Files Without Breaking the Timing

Step-by-step guide to splitting an SRT file at a timestamp, merging several SRT parts into one, and combining two subtitle tracks — with the offset and renumbering rules that keep everything in sync.

· subtitle formats

SRT vs VTT vs ASS: Subtitle Formats Explained

What SRT, WebVTT and ASS subtitle files are, how their syntax differs, what each supports for styling and positioning, and which one to use for YouTube, the web, video editors and burned-in captions.

· burn-in

How to Burn Subtitles Into a Video: Hardsubs vs Softsubs

The difference between hardcoded (burned-in) and soft subtitles, when to use each, and step-by-step ways to burn SRT or ASS captions into a video with FFmpeg, HandBrake or your video editor.

Back to all guides