How Subtitle Timing Shift and Rescaling Work
After reading this, you will know when a subtitle file needs a constant offset versus a linear rescale, how to compute both by hand, and how to avoid the mistakes that leave dialogue still out of sync.
What subtitle shifting fixes
A subtitle file is a list of timestamps paired with lines of text. Each cue says "show this text from 00:01:12,500 to 00:01:15,000." When the timing is wrong, the words appear too early or too late relative to the audio.
Consider a film where every line lands 2.5 seconds late. A character's mouth stops moving, and only then does the subtitle appear. The fix is to move every timestamp earlier by 2.5 seconds. That is a constant shift: the same number is subtracted from every start and end time.
The Subtitle Shifter reads an SRT or WebVTT file, applies either a constant offset or a linear rescale to every timestamp, and exports a corrected file. Nothing is uploaded; the work happens in your browser.
When to shift and when to rescale
The choice depends on how the error behaves over time. There are two clean cases.
If the subtitles are off by the same amount at minute 1 and at minute 90, you have a fixed delay. A constant shift corrects it. This usually comes from a release that starts with a few extra seconds of logos or a different intro.
If the subtitles are almost perfect at the start but drift further out as the film runs, the two files were timed at different frame rates. Early cues look fine because the error near time zero is tiny. By the end it can exceed several seconds. A constant shift cannot fix this, because there is no single number that is right everywhere. You need to stretch or compress the whole timeline, which is a linear rescale.
If subtitles drift gradually out of sync over the film, a constant shift will fix the start and break the end, or fix the end and break the start. Watch two widely separated scenes before you decide. A matching error at both points means shift; a growing error means rescale.
The math behind both operations
A constant shift adds a fixed offset b (in seconds) to every timestamp t:
Here t is the original time of a cue edge, t' is the new time, and b is the offset. Use b \lt 0 to move subtitles earlier and b \gt 0 to move them later. The gap between any two cues never changes, because the same number is added to both.
A linear rescale multiplies by a slope a and then adds an offset b:
The slope a stretches (a \gt 1) or compresses (a \lt 1) the timeline. A constant shift is just the special case a = 1.
For a frame-rate mismatch the slope is the ratio of the two rates. If subtitles were timed for 23.976 fps video but your copy runs at 25 fps, playback is faster, so the subtitle times must be compressed by:
That is roughly a 4.1% compression. Over a 90-minute (5400-second) film, the last cue moves earlier by about 5400 \times (1 - 0.95904) = 221 seconds if b = 0. That large number is why a constant shift never rescues a frame-rate error.
Fixing a rescale from two known points
You rarely know the frame rates for certain. What you can do is find two moments where you know the correct time. Pick an early line and a late line, note when each should appear, and solve for a and b.
Given original times t_1, t_2 and their correct targets t_1', t_2':
The slope is the ratio of how much the corrected times span to how much the original times span. The offset then anchors the line so it passes through the first point.
Choose your two reference cues far apart, ideally near the start and near the end. If they are close together, small timing errors in your measurements get amplified when you divide by the tiny span t_2 - t_1.
Reproducing the demo: a 2.5 second delay
The demo applies a constant shift of b = -2.5 seconds to move late subtitles earlier. Take three cues from the sample file.
- Cue 1 starts at
00:00:05,000, which is 5.000 s. New time: 5.000 - 2.5 = 2.500 s, or00:00:02,500. - Cue 2 starts at
00:01:12,500, which is 72.500 s. New time: 72.500 - 2.5 = 70.000 s, or00:01:10,000. - Cue 3 starts at
01:30:00,000, which is 5400.000 s. New time: 5400.000 - 2.5 = 5397.500 s, or01:29:57,500.
The shift is the same 2.5 seconds at every point, from 5 seconds in to 90 minutes in. That is the signature of a constant offset: the correction does not grow.
Comparing the two corrections visually
Plotting new time against original time makes the difference obvious. A constant shift is a line parallel to the diagonal. A rescale is a line with a different slope that fans away from the diagonal as time increases.
Common mistakes
The most frequent error is applying a shift when a rescale is needed. You sync the opening scene, feel satisfied, then find the ending is minutes off. Check the last scene before you commit.
The second mistake is confusing the sign of the offset. If subtitles appear late, they need a negative offset to move earlier. If they appear early, use a positive offset. Test one line and confirm the direction before trusting the whole file.
A third mistake is guessing the frame-rate ratio backward. Compressing when you should stretch doubles the error instead of removing it. The four common ratios are worth memorizing.
| From | To | Slope a | Effect |
|---|---|---|---|
| 23.976 | 25 | 0.9590 | compress |
| 25 | 23.976 | 1.0427 | stretch |
| 23.976 | 24 | 0.9990 | compress |
| 24 | 25 | 0.9600 | compress |
A fourth mistake is losing precision by rounding to whole seconds. SRT stores milliseconds and WebVTT does the same, so keep at least three decimal places through the calculation. Rounding 70.0004 s to 70 s is fine; rounding to 70 s from 70.4 s can push a fast-cut line onto the wrong shot.
Related tools
If your player rejects the file format rather than the timing, the problem is not the timestamps. Convert between SRT and WebVTT first with the Subtitle Converter, then correct timing here. Both formats use the same timestamp arithmetic, so a shift or rescale computed for one applies unchanged to the other.
Frequently asked questions
Why are my subtitles slightly off from the very start?
A fixed delay, often from an intro of a different length. Measure the gap on one early line and apply a constant shift equal to that gap. If the gap is 2.5 seconds late, shift by b = -2.5.
Why do subtitles start fine but end minutes off?
Frame-rate mismatch. The error is small near time zero and grows with time. Use a linear rescale. For a 23.976 to 25 fps case the slope is 0.95904, moving the final cue of a 90-minute film about 221 seconds earlier.
Does shifting change the reading speed of a line?
No. A constant shift adds the same value to the start and end of every cue, so its duration is unchanged. A rescale multiplies both edges, so a 3.0 second cue becomes 3.0 \times 0.95904 = 2.877 seconds, a change of 123 milliseconds that viewers will not notice.
Can I find the rescale without knowing the frame rates?
Yes. Note the correct time for one early line and one late line, then use the two-point formula. If line one should play at 5 s (currently 5 s) and line two at 5179 s (currently 5400 s), then a = (5179 - 5) / (5400 - 5) = 0.9590.
Will this work on both SRT and VTT files?
Yes. Both formats store times as hours, minutes, seconds and milliseconds, so the same offset and slope apply. The only difference is the punctuation of the timestamp, which the tool handles for you.