Skip to content
OneKitly

Out-of-Sync Subtitles: How to Measure the Offset and Shift an SRT by an Exact Number of Seconds

Published 8/5/2026 · 15 min read · Developer tools

Daniel Okonkwo

Daniel OkonkwoFront-end developer and tech writer at OneKitly

Web performance · File formats

Checked against 4 sources

View profile
In short

Measure the offset before you shift anything. Find one unmistakable line of dialogue near the start, note the exact time it is spoken in the player, subtract the cue's start stamp, and you have the offset in seconds — then repeat the measurement near the end of the film. If the two figures agree, the track carries a constant offset and one shift fixes the whole file: paste the SRT in, enter the offset in seconds (positive delays the subtitles, negative moves them earlier) and take the corrected file. If the second figure is larger than the first, it is not an offset at all, it is drift, and no shift will fix it. Drift almost always means a frame-rate mismatch. A track authored against a 25 fps master and played on a 23.976 fps transfer — 23.976 being 24000/1001 exactly — needs its timestamps multiplied by 1.042708, not moved: the error grows 2.5625 seconds for every minute of running time, which is one second every 23.4 seconds and 3 minutes 50.6 seconds across a 90-minute subtitle timeline. The gentler pair, 24 against 23.976 or 30 against 29.97, is exactly 1.001 — only 5.4 seconds over the same 90 minutes, which is why it gets misdiagnosed as a constant offset for the first half hour. One behaviour to know before you enter a negative value: a cue the shift pushes entirely before zero is removed, not flattened, and an amber line above the output counts how many went. A cue straddling zero keeps its real end and starts at 00:00:00,000. That also makes a large negative shift a workable way to trim an intro — the cues inside it go, everything after keeps its spacing, and you are told what was lost.

Measure the offset at two points instead of guessing it once. If it is constant, one shift fixes the file. If it grows, it is a frame-rate mismatch — 25 fps against 23.976 drifts 2.5625 seconds every minute — and no shift will ever fix that.

Measure the offset, do not eyeball it

Pick a line of dialogue you cannot mistake — a name, a number, a shout, anything with a hard consonant at the start. Play the film, pause on the frame where the sound begins, and read the player's clock. Then find that same line in the subtitle file and read its start stamp. The offset is the video time minus the cue time. If the video says 00:04:12.500 and the cue says 00:04:09,000, the subtitles are running 3.5 seconds early and the offset you need is +3.5 seconds.

Now do it a second time, as close to the end of the film as you can find a clean line. This second measurement is the whole diagnosis, and skipping it is the reason people shift the same file four times and never fix it. Two numbers that agree within a few tenths mean a constant offset: one shift, done. Two numbers that differ by minutes mean the file is not offset at all, it is running at the wrong speed, and every shift you apply will fix one end of the film while making the other end worse.

One practical note on reading the clock: most players show the position to a tenth of a second, and a tenth is well below what an audience notices, so there is no need for frame accuracy here. What you do need is honesty about which instant you measured. Measure the instant the sound starts, not the instant you notice it, and measure the same kind of instant both times — otherwise your two readings differ by your own reaction time and you invent a drift that is not there.

When the offset grows: the frame-rate arithmetic

The same film exists in two families of running speed, and the subtitle file remembers which one it was written against. The film family runs at 24 frames per second, or at 24000/1001 — 23.976 — on any transfer that had to live inside the American colour-television timing. The broadcast family of most of Europe runs at 25. Those are not decorative labels: ffmpeg's own rate abbreviations spell them out as exact fractions, film = 24/1, pal = 25/1, ntsc-film = 24000/1001, ntsc = 30000/1001. A subtitle file made for one and played on the other does not sit in the wrong place, it moves at the wrong speed.

The correction is a multiplication, not an addition. Timestamps written for a 25 fps version, played on a 23.976 fps version, have to be multiplied by 25 ÷ (24000/1001) = 25025/24000 = 1.042708. Read that as a rate of error and it becomes something you can recognise on sight: 2.5625 seconds of drift for every minute of running time, one full second every 23.4 seconds. Across a 90-minute subtitle timeline it accumulates to 230.6 seconds — 3 minutes 50.6 seconds. Turned round, a line that belongs at the 90-minute mark of the 23.976 transfer carries a 25 fps stamp of 86 minutes 18.8 seconds and appears 3 minutes 41.2 seconds early.

The dangerous pair is the small one. Going between 24 and 23.976, or between 30 and 29.97, is a ratio of exactly 1.001, which over the same 90 minutes is 5.4 seconds. For the first twenty minutes that is invisible; by the last reel it is a full sentence out of place. People shift such a file by two seconds, watch the opening happily, and hit the same problem an hour later — because it was never an offset. Two measurements taken an hour apart tell you which of the two you have in about ninety seconds of work.

This tool shifts and does not rescale, and that is worth saying plainly rather than leaving you to discover it. If your two measurements disagree, the file needs every timestamp multiplied, which means a tool that does frame-rate conversion or a short script — and the multiplier is the ratio of your two measured positions, not a value you have to guess. Divide the true video time of the late line by the true video time of the early line, and do the same for the two cue stamps; the ratio of those two ratios is what has to be applied.

What a negative shift actually does here

A negative shift is the common case — subtitles that arrive late need moving earlier — and it is the one place where a subtitle tool has to make a decision that the format does not make for it. A cue at 00:00:01,000 shifted by −5 seconds would start at −4 seconds. SubRip has no way to write that. Three answers are possible: write a negative stamp anyway and let the player choke, drop the cue, or clamp it at zero. This tool picks between the last two, cue by cue, according to what is left after the origin.

The test is the cue's end stamp, which produces two different outcomes. A cue that straddles zero is truncated: at −2.5 seconds, 00:00:01,000 --> 00:00:04,000 comes back as 00:00:00,000 --> 00:00:01,500. It keeps its real end, so it now appears at the very first frame and lasts a second and a half less than it should — visible, but not fatal. A cue pushed entirely before zero is a different matter. At −5 seconds the same cue would end at −1 second: it has nothing left to show, and it is removed from the file. The cues that survive are renumbered from 1, so what comes back is a shorter file rather than a padded one.

Push the whole file back far enough and the cues inside that stretch simply go. A −20 second shift applied to a file whose first three cues sit inside the first twelve seconds returns nothing at all, and an amber line above the output says that every cue now falls before zero. Short of that extreme, the same line carries two counts: how many cues were removed, and how many started before zero and now start at the origin. What the tool will no longer do is lose subtitles without saying so — read the counts before you save over anything, and compare them with what you expected to lose.

That also makes a large negative shift a real trimming device. Cut a thirty-second intro off the front of a video, shift the subtitles by −30 seconds, and the cues that belonged to the intro are removed, the one straddling the cut starts at the first frame with its real end, and everything after keeps its spacing. The count in the banner is the check: if it says four cues removed and you meant to lose two, your offset was longer than the intro.

What comes back out, and what it quietly changes

The output is always SubRip, whatever went in. Cues are renumbered from 1 in file order, timestamps are written as HH:MM:SS,mmm with a comma before the milliseconds, and everything between the timestamp line and the blank line is passed through untouched — including any italic tags or speaker dashes you had. That last point matters: this is a retimer, not a cleaner, and it will not alter your text in any way.

It will also read a WebVTT file, and this is worth knowing because the result is not what an unwary user expects. Paste a .vtt in and the tool finds the cues, throws away the WEBVTT header line, throws away the cue identifiers and any cue settings sitting after the arrow, converts the decimal point to a comma, and hands you SubRip. The times shift correctly. But the file that comes back is no longer valid WebVTT — the header is a hard requirement of the specification, and the positioning settings you may have relied on are gone. If you wanted a shifted .vtt, this is not the way to get one.

Two smaller facts about the edges, both found by feeding the tool its own output. The timestamp reader accepts up to three digits for the hours field, so a stamp like 111:06:41,000 is read back without trouble; the ceiling is 999:59:59,999, beyond which the tool would write hours it can no longer read — a wall no film will ever reach. And the offset is rounded to whole milliseconds at output, so a value of 0.0005 seconds becomes a one-millisecond move rather than nothing. Neither will trouble a film, but both are worth knowing if you are chaining operations.

Drift per minute
The same 90-minute subtitle timeline under five rate mismatches — multiplier, drift per minute, total drift
MismatchMultiplier to applyDrift per minuteDrift over 90 minutesHow it looks while watching
Constant offset (any cause)1.000000 — shift instead0 s0 sEqually wrong at minute 1 and minute 89 — one shift fixes it
24 fps subtitles on 23.976 fps video (or 30 on 29.97)1.0010000.060 s5.4 sInvisible for twenty minutes, a sentence out of place by the end — the one most often misdiagnosed
25 fps subtitles on 24 fps video1.0416672.500 s3 min 45.0 sSubtitles run ahead and the gap widens visibly within the first reel
25 fps subtitles on 23.976 fps video1.0427082.563 s3 min 50.6 sThe classic PAL-to-film mismatch: one second lost every 23.4 seconds
23.976 fps subtitles on 25 fps video0.959041−2.458 s−3 min 41.2 sThe same mismatch the other way round: subtitles fall further and further behind
SRT subtitle time shiftFix out-of-sync subtitles by shifting every timestamp in an SRT file by the same offset. Paste the subtitles, enter a positive offset to delay them or a negative one to move them earlier, in seconds or milliseconds, and copy or download the corrected file. Times are clamped so they never go negative.Try the tool

Frequently asked questions

How do I measure the offset accurately without frame-stepping the whole film?
Two measurements are enough, and you only need tenth-of-a-second accuracy. Find a line with a hard consonant onset near the start of the film, pause on the frame the sound begins, and read the player's position; subtract the cue's start stamp from it. Then do the same for a line near the end. If the two offsets agree, apply the average of the two and you are finished. Consistency of method matters more than precision here: always measure the same instant — the beginning of the sound, not the moment you recognise it — because a reaction-time error of half a second in one of the two measurements is enough to invent a drift that does not exist. If your player shows only whole seconds, use one that shows tenths; the difference between a 3-second and a 3.5-second offset is visible on screen.
My subtitles are perfect at the start and about four minutes early at the end. What is that?
That is a frame-rate mismatch, and the size of it identifies which one. Roughly four minutes of drift over a feature-length film is the signature of 25 fps subtitles on a 23.976 fps video: the multiplier is 1.042708, the drift is 2.5625 seconds per minute, and across a 90-minute subtitle timeline it totals 230.6 seconds — 3 minutes 50.6 seconds, or 3 minutes 41.2 seconds if you measure it against the video's own clock instead. A shift cannot repair it, because a shift adds the same number to every timestamp while your error is proportional to the timestamp. What you need is a multiplication of every stamp by 1.042708, which is frame-rate conversion, not time shifting. This tool does not do that, and applying a shift will simply move the point at which the subtitles happen to be correct from one end of the film to the other.
What happens to cues that a negative shift pushes before 00:00:00,000?
They are removed, and the tool says how many. The decision is made on the end stamp, so there are two outcomes. A cue straddling zero keeps its real end: shifting 00:00:01,000 --> 00:00:04,000 by −2.5 seconds returns 00:00:00,000 --> 00:00:01,500, which shows from the first frame and is a second and a half short. A cue whose end has also gone past zero has nothing left to show and is dropped; the survivors are renumbered from 1, so the output is a shorter valid file rather than one padded with empty entries. An amber line above the output carries the counts — how many cues were removed, how many now start at the origin — and if the shift wipes out everything it says so instead of handing you a file. Negative times are never written. In practice this makes a large negative shift a usable way to trim an intro: compare the removed count with the number of cues you meant to lose before you save over anything.
Can I paste a WebVTT file in, or does it only take SubRip?
It reads WebVTT, but it gives you SubRip back, and that conversion is not free. WebVTT is a W3C specification: the file must open with a WEBVTT line, timestamps use a full stop before the three-digit fraction rather than a comma, the hours field is optional, and a cue timings line may carry a settings list after the arrow — alignment, position, region — as well as an optional identifier on the line above. This tool finds the cue timings, shifts them, and writes SubRip: the header is gone, the identifiers are gone, the cue settings are gone, and the full stop becomes a comma. If your source was styled or positioned WebVTT, all of that is discarded silently. If you actually want plain text out of a caption file rather than a retimed one, the dedicated VTT to TXT converter is the honest route.
Is there an official SubRip specification I can check my file against?
No, and it is worth knowing that before you argue with a tool about what is valid. The format is whatever the original SubRip program produced, plus whatever players later chose to tolerate. The Library of Congress records it as only partly documented and not well standardised, and lists no specification document at all; its format description gives the timecode shape as hours:minutes:seconds,milliseconds, with the comma, and the arrow as two hyphens and a right angle bracket. There is no registered media type for it either, where WebVTT has text/vtt registered with IANA. In practice this means encoding is a guess — the original program defaulted to a Windows code page, so any parser has to attempt character-set detection — and it means that when two tools disagree about your file, neither of them is wrong by reference to a standard. Test in the player you will actually use.

Articles you may find interesting

All guides
How-toSRT to Text: Getting a Clean Transcript Out of SubtitlesRemoving the numbers and the timestamps is the easy half. The half that decides whether the transcript is readable is the italic tags, the dialogue dashes, the sound descriptions and the sentences broken across two cues — and this converter leaves every one of them for you.How-toSubtitles to a Spreadsheet, and Back: What Survives the Round TripA comma is quoted, a quotation mark is doubled, and a two-line cue keeps both lines — verified byte-identical over three consecutive round trips. What can still change your file is the spreadsheet in the middle.How-toMerging Two Subtitle Tracks Into a Bilingual Version: What Actually Happens to the CuesCue 12 of the English track is not cue 12 of the French one, because translators split and join sentences differently. Two strategies exist for pairing them; this merger uses neither — it interleaves. Here is what that gives you and when it is good enough.ExplainerWhy Your Video Cut Lands Two Seconds EarlyYou asked for 1:23 and got 1:21. Nothing is broken: a cut that does not re-encode can only land on a keyframe, and how far away the nearest one is depends entirely on what recorded the video. Here is how to know which you have and when to accept the drift.GuidePulling Still Frames Out of a Video — and Why They Look Softer Than the Video DidThree commands hide behind three buttons: one frame at a timestamp, a fixed number spread across the clip, or one every N seconds. Here are the exact arguments, the 60-frame ceiling and the reason a frame from the middle of a compressed clip can never be as sharp as a keyframe.How-toGetting the Audio Out of a Video Without a Second Generation of LossThe soundtrack inside your video has already been through a lossy encoder once. Whether extracting it costs you a second pass depends entirely on which of the three buttons you press — and "extract to MP3", the one everybody reaches for, is the one that costs.

Related tools

SubRip has no specification. The Library of Congress records it as only partly documented and not well standardised, so what counts as a valid .srt file is decided by the player, the encoder or the platform that reads it, and two of them will disagree sooner or later. Everything described here was checked against the tool's actual output, not against a standard, because for this format there is none. WebVTT is different — it has a published W3C specification — but it is still a Candidate Recommendation Draft rather than a finished Recommendation. Keep the original file, run the converted one in the player or uploader you actually intend to use before you throw anything away, and treat any claim about what "all players" do, including the ones on this page, as something to verify on yours.

Sources

Spotted a mistake in this article?