Subtitle Timing Shifter
Resync out-of-sync SRT and WebVTT subtitles in your browser. Apply a constant offset, fix framerate drift with 23.976/25 presets, or solve the timing with a two-point sync, then download or convert between SRT and VTT.
Drop an .srt or .vtt file here
Everything runs in your browser — nothing is uploaded.
Positive = subtitles appear later. Negative = earlier.
Why subtitles fall out of sync
A subtitle file is nothing but a list of timestamps. It has no link to the video it was written for, so it only stays correct as long as the video's timeline matches the one the subtitler worked against. There are exactly two ways that assumption breaks, and they need different fixes.
Constant offset — the subtitles are late or early by the same amount everywhere. This is almost always an edition mismatch: your copy has a studio logo, an anti-piracy card, or an extra distributor bumper at the head that the subtitler's copy did not, so every line is pushed by those few seconds. Extended, unrated and director's cuts also introduce offsets, though those can change partway through the film if whole scenes were inserted.
Progressive drift — the subtitles are roughly right at the start but grow steadily wrong, often by a minute or more by the credits. That is a framerate mismatch: the subtitles were timed against a release running at a different frame rate than yours. The error is proportional to elapsed time, so no single offset can fix it — the whole timeline has to be scaled.
Telling the two apart in 30 seconds
Do not judge sync from the opening scene alone. Check it in two places — near the beginning and near the very end — and compare the error you measure at each.
- Same error at both ends: constant offset. Use Shift. If the subtitles run 3.2 seconds early at minute 2 and still 3.2 seconds early at minute 105, enter +3.2.
- Small error early, large error late: framerate drift. Use Stretch. An error that grows from about 0 to roughly 4.5 minutes across a 2-hour film is the classic 25 fps versus 23.976 fps case.
- Error jumps at one point, then stays flat: a different cut of the film with an inserted or removed scene. Neither tool fixes this in one pass — split the file and shift each half separately.
- Error grows and there is also an offset: both problems at once. Use Two-point sync, which solves the scale and the offset together.
Framerate ratios: PAL, NTSC and film
Film is shot at 24 fps. PAL territories broadcast at 25 fps and historically achieved that by simply running the film 4% fast ("PAL speedup"). NTSC territories use 24000/1001 ≈ 23.976 fps and 30000/1001 ≈ 29.97 fps, the fractional rates left over from the introduction of colour to a 30 fps black-and-white system. To retime a subtitle file, multiply every timestamp by source fps ÷ target fps.
| Subtitles made for | Video plays at | Multiply times by | Drift over 2 hours |
|---|---|---|---|
| 23.976 | 25 | 0.959040 | −4 min 55 s |
| 25 | 23.976 | 1.042708 | +5 min 08 s |
| 24 | 25 | 0.960000 | −4 min 48 s |
| 25 | 24 | 1.041667 | +5 min 00 s |
| 24 | 23.976 | 1.001000 | +7.2 s |
| 29.97 | 25 | 1.198800 | +23 min 51 s |
The number to remember: 25 ÷ 23.976 = 1.0427. A PAL-timed subtitle file played against a 23.976 fps source needs its timestamps multiplied by roughly 1.0427 — that is the 4.27% PAL speedup, and it is by far the most common cause of drifting subtitles.
23.976 and 29.97 are shorthand. The exact values are 24000/1001 and 30000/1001, and this tool uses the exact fractions. Over a 2-hour film the rounding difference is about half a second, which is enough to notice.
The two-point sync method
If you do not know the source framerate — or the file has both an offset and drift — you do not need to guess. Two known-correct points fully determine a linear retiming, because a subtitle file only ever needs a scale and an offset:
- 1. Load the file. The tool fills the two anchor boxes with the current start times of the first and last cue.
- 2. Find the first line in the video. Seek to where that dialogue is actually spoken and note the player's timecode. Use frame stepping or a 0.25× playback speed if you want sub-second accuracy.
- 3. Find the last line. Same thing near the end of the film. Choose a line with a clear, unambiguous audio cue.
- 4. Enter both times as hh:mm:ss.mmm or plain seconds. The tool solves the scale and offset and applies them to every cue.
- 5. Check the preview. If the solved scale lands near a known ratio like 1.0427 or 0.9590, you have confirmed a framerate mismatch and your anchors are good. A scale far from 1.0 with anchors close together means one of your two readings is wrong.
Pick anchors as far apart as possible. A timing error in either reading is divided by the gap between them, so anchors two hours apart tolerate a half-second mistake, while anchors five minutes apart amplify the same mistake into visible drift across the rest of the film.
SRT and WebVTT, side by side
SubRip (.srt) is the older, near-universal format used by desktop players. WebVTT (.vtt) is the W3C format that HTML5 <track> elements require — browsers will not load an .srt file. The same cue in both:
SubRip (.srt)
WebVTT (.vtt)
- Decimal separator: SRT uses a comma (20,000); WebVTT uses a period (20.000). This single character is the most common reason a converted file silently fails to load.
- Header: WebVTT files must begin with the literal string WEBVTT. SRT has no header.
- Cue numbering: SRT requires a sequential integer before every cue. In WebVTT the line before the timestamp is an optional free-text cue identifier, not an index.
- Hours field: SRT always writes hh:mm:ss,mmm. WebVTT permits mm:ss.mmm when the cue is under an hour.
- Cue settings: WebVTT allows positioning directives after the timestamp — align, position, line, size, vertical. This tool preserves them verbatim. SRT has no equivalent, so they are dropped when converting to SRT.
- Blocks SRT lacks: WebVTT adds NOTE comments, STYLE blocks carrying CSS ::cue rules, and REGION definitions. These are carried through when the output is WebVTT.
- Encoding: WebVTT must be UTF-8. Legacy SRT files are frequently Windows-1252 or an ISO-8859 variant, which is why accented characters sometimes arrive as mojibake — re-save the source as UTF-8 first.