[{"data":1,"prerenderedAt":45},["ShallowReactive",2],{"blog-post-subtitle-file-out-of-sync":3,"blog-index":15},{"slug":4,"title":5,"description":6,"date":7,"updated":7,"tags":8,"image":12,"html":13,"reading_minutes":14},"subtitle-file-out-of-sync","A subtitle file can look valid and still be out of sync","A subtitle file 2.5 seconds late scored the same as the in-sync one on our own check. Why a text check cannot see sync, and what the audio shows.","2026-10-15",[9,10,11],"subtitles","captions","video","https:\u002F\u002Fcontent.presentr.me\u002Fanalyze\u002Fassets\u002Fog.f3a05ee827.png","\u003Cp>A subtitle file can be perfectly formed and still be wrong for the video.\u003C\u002Fp>\n\u003Cp>We built one, broke its timing in several ways, and ran each version through our free subtitle check. The check found problems inside the file. It could not tell us whether the words appeared at the right moment.\u003C\u002Fp>\n\u003Cp>SRT and VTT files hold timed text cues; we use “captions” and “subtitles” for them interchangeably. We built every file here ourselves, from a script we wrote and had read by text-to-speech. No user files or runs were used.\u003C\u002Fp>\n\u003Ch2 id=\"how-captions-go-out-of-sync\">How captions go out of sync\u003C\u002Fh2>\n\u003Cp>A constant offset means every cue is early or late by the same amount. This can happen when someone trims an intro, adds a bumper, or uses captions made for another cut.\u003C\u002Fp>\n\u003Cp>A stretch means the error grows through the video. A common cause is a frame-rate mismatch. The difference between 25 fps and 23.976 fps is 4.27%, or about 2.56 seconds per minute. The difference between 24 fps and 23.976 fps is 0.1%, or about 3.6 seconds per hour.\u003C\u002Fp>\n\u003Cp>A jump partway through points to an edit or an inserted ad read: correct before it, wrong by a fixed amount after.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fcontent.presentr.me\u002Fanalyze\u002Fassets\u002Fsync-types.693def4981.svg\" alt=\"Diagram of three ways captions go out of sync. Offset: every caption sits the same distance after its speech. Stretch: the gap between caption and speech grows through the video. Jump: captions match until an inserted ad read, then every caption after it is early by the same amount.\" sizes=\"(max-width: 768px) 100vw, 720px\" width=\"760\" height=\"584\" loading=\"lazy\" \u002F>\u003C\u002Fp>\n\u003Cp>All three can leave a valid file: timestamps in order, no overlaps, normal reading speeds. It is internally consistent and still wrong for the video.\u003C\u002Fp>\n\u003Ch2 id=\"the-experiment\">The experiment\u003C\u002Fh2>\n\u003Cp>On October 15, 2026, we ran this test on our production service.\u003C\u002Fp>\n\u003Cp>The media was a talk we scripted about captions going wrong. It ran for 67.8 seconds and was read by text-to-speech. We also made an 88.6-second version with a 20-second ad read inserted at 0:37. The insert shifted everything after it 20.81 seconds later.\u003C\u002Fp>\n\u003Cp>We first made rough captions with 36 cues, timed by word count rather than by listening. We repaired those captions against the original audio. That repaired file became our in-sync reference.\u003C\u002Fp>\n\u003Cp>From the reference, we made an offset version shifted 2.5 seconds late, a version stretched by 25\u002F23.976, and a version placed against the media containing the ad.\u003C\u002Fp>\n\u003Cp>The free check that scored these files is ours. Its score is for each file as given. The other columns are the result of repairing that file against the audio.\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Captions\u003C\u002Fth>\n\u003Cth style=\"text-align:right\">Free check score\u003C\u002Fth>\n\u003Cth style=\"text-align:right\">Cues retimed\u003C\u002Fth>\n\u003Cth style=\"text-align:right\">Average \u002F largest correction\u003C\u002Fth>\n\u003Cth>Quality\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Rough, timed by word count\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">3\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">36 of 36\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">0.64 s \u002F 1.70 s\u003C\u002Ftd>\n\u003Ctd>excellent\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>In sync (reference)\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">8\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">(not repaired — this is the target)\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">–\u003C\u002Ftd>\n\u003Ctd>–\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Reference shifted 2.5 s late\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">8\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">36 of 36\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">2.53 s \u002F 2.74 s\u003C\u002Ftd>\n\u003Ctd>excellent\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Reference stretched 25\u002F23.976\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">6\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">36 of 36\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">1.56 s \u002F 2.89 s\u003C\u002Ftd>\n\u003Ctd>excellent\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Reference against the ad version\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">8\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">36 of 36\u003C\u002Ftd>\n\u003Ctd style=\"text-align:right\">9.17 s \u002F 20.92 s\u003C\u002Ftd>\n\u003Ctd>excellent\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp>The in-sync file and the file shifted 2.5 seconds late both scored 8. The stretched file scored 6, better than the in-sync file, because stretching made its cues read more slowly.\u003C\u002Fp>\n\u003Cp>The file that was 20.8 seconds late for everything after 0:37 also scored 8. In that case, the final cue moved from 66.68 seconds to 87.48 seconds. The true shift was 20.81 seconds.\u003C\u002Fp>\n\u003Cp>The free check measures the subtitle file, not its sync with the media.\u003C\u002Fp>\n\u003Ch2 id=\"what-a-text-only-check-can-see\">What a text-only check can see\u003C\u002Fh2>\n\u003Cp>Our free check reads only the subtitle file. Its score is the share of cues with at least one timing issue.\u003C\u002Fp>\n\u003Cp>It flags:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Reading speeds above 21 characters per second.\u003C\u002Fli>\n\u003Cli>Overlapping cues.\u003C\u002Fli>\n\u003Cli>Cues shorter than 0.5 seconds when they contain more than 5 characters.\u003C\u002Fli>\n\u003Cli>Cues longer than 7 seconds.\u003C\u002Fli>\n\u003Cli>Gaps longer than 10 seconds.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>These checks can catch bad hand edits, awkward timing, and conversion problems. They cannot see a constant offset or a clean stretch because they have no audio reference.\u003C\u002Fp>\n\u003Cp>After repair, every repaired file scored 8. In each file, 3 of 36 cues still read faster than 21 characters per second. There was no room to lengthen them before the next cue. The voice speaks about 200 words per minute, and making room would mean moving cues off their first spoken word.\u003C\u002Fp>\n\u003Ch2 id=\"measuring-sync-against-the-audio\">Measuring sync against the audio\u003C\u002Fh2>\n\u003Cp>To measure sync, the repair transcribes the media with word-level timings and finds each cue’s words in that transcript. Matching tolerates small spelling differences and looks about 20 words past the last match.\u003C\u002Fp>\n\u003Cp>When it finds a cue, it moves the cue to those spoken words. The start stays on the first word. The end is extended until the cue reads at 21 characters per second or slower, with a minimum duration of 0.5 seconds. It never extends into the next cue or beyond 7 seconds.\u003C\u002Fp>\n\u003Cp>If a nearby match fails, the repair can re-anchor up to roughly ten minutes of speech ahead. This is limited to cues containing 3 or more words and matching at least 80% of their words.\u003C\u002Fp>\n\u003Cp>The report shows how many cues were retimed, how many were unmatched, and the average and largest correction. Its quality label is based on the share retimed: 95%+ is excellent, 80%+ is good, 60%+ is marginal, and anything below that is poor.\u003C\u002Fp>\n\u003Ch2 id=\"what-broke-in-our-repair\">What broke in our repair\u003C\u002Fh2>\n\u003Cp>Testing exposed four faults in our own repair, all fixed in October 2026.\u003C\u002Fp>\n\u003Cp>Speech present in the media but absent from the captions could break alignment. An ad read longer than about 20 words left every later cue untimed. We added the longer-range re-anchoring described above. In an offline test using a 25-cue file and hand-built word timings, a 75-word insert went from 12 of 25 cues retimed to 25 of 25.\u003C\u002Fp>\n\u003Cp>The quality label also judged how far the original file was from the audio. A perfect repair of a badly mistimed file could therefore be labeled “poor.” It now grades how much of the file was retimed.\u003C\u002Fp>\n\u003Cp>Our word timings were also missing the opening 13 seconds. We had primed the speech-recognition model we use for word timings with the opening sentences as context. It treated that context as speech before the audio and skipped the same words in the recording. Among the 15 most recent service runs we checked, about half had lost the opening 10–20 seconds. We stopped sending that context. Our runs since then start at 0 seconds. Before this fix, the first test retimed only 9 of 36 cues.\u003C\u002Fp>\n\u003Cp>Finally, repaired cues ended on their last spoken word. That left 8 of 36 cues above 21 characters per second, and the repaired file scored 22 on our own check. We changed the repair to hold cues on screen using the reading-time rules above.\u003C\u002Fp>\n\u003Ch2 id=\"a-quick-manual-diagnosis\">A quick manual diagnosis\u003C\u002Fh2>\n\u003Cp>Check one line near the start of the video and another near the end.\u003C\u002Fp>\n\u003Cp>If both are wrong by the same amount, shift every timestamp by that amount. If the error grows, scale the timestamps by the frame-rate ratio, such as 25\u002F23.976 ≈ 1.0427, or its inverse. If the captions are correct and then suddenly jump, shift only the cues after the edit or realign them to the audio.\u003C\u002Fp>\n\u003Ch2 id=\"method-and-limits\">Method and limits\u003C\u002Fh2>\n\u003Cp>This was one short file, not a benchmark. The speech was clean and synthetic. Real recordings with music, crosstalk, or accents will match less cleanly.\u003C\u002Fp>\n\u003Cp>Cues the repair cannot match keep their old timing. Captions that paraphrase heavily match worse than captions close to the spoken words. A cue containing only 1 or 2 words is never re-anchored far away. The caption language must also match the spoken language.\u003C\u002Fp>\n\u003Cp>You can \u003Ca href=\"https:\u002F\u002Fanalyze.presentr.me\u002Ftools\u002Fsrt-repair-analyzer\" rel=\"noopener\">check a subtitle file free\u003C\u002Fa> without an account. It checks internal timing issues, not sync with a video. To repair captions against their audio, \u003Ca href=\"https:\u002F\u002Fanalyze.presentr.me\u002Fregister\" rel=\"noopener\">create a free account\u003C\u002Fa>. Audio repair uses credits like any run; a new account has 5 credits, about 5 minutes of audio.\u003C\u002Fp>\n",7,{"site":16,"generated_at":17,"posts":18,"redirects":44},"analyze","2026-10-23T13:34:56.758Z",[19,30,40],{"slug":20,"title":21,"description":22,"date":23,"updated":23,"tags":24,"image":27,"url":28,"published_at":29},"one-newspaper-page-four-ocr-tools","Tried OCR on an old newspaper? Compare this page","One dense 1850 newspaper page, four OCR tools: one nearly right, one fluent but wrong. See the results, then run your own page.","2026-10-20",[25,26],"ocr","text extraction","https:\u002F\u002Fcontent.presentr.me\u002Fanalyze\u002Fassets\u002Fog.088293acda.png","https:\u002F\u002Fanalyze.presentr.me\u002Fblog\u002Fone-newspaper-page-four-ocr-tools","2026-10-20T20:50:29.423Z",{"slug":31,"title":32,"description":33,"date":34,"updated":35,"tags":36,"image":37,"url":38,"published_at":39},"fix-progressive-subtitle-drift","Subtitles Offset or Slowly Drifting? Diagnose the Difference","Check subtitle sync at the beginning, middle, and end to distinguish a constant offset, progressive drift, or a re-edited video.","2026-10-19","2026-10-23",[9,10],"https:\u002F\u002Fcontent.presentr.me\u002Fanalyze\u002Fassets\u002Fog.743e8292aa.png","https:\u002F\u002Fanalyze.presentr.me\u002Fblog\u002Ffix-progressive-subtitle-drift","2026-10-19T19:30:48.590Z",{"slug":4,"title":5,"description":6,"date":7,"updated":7,"tags":41,"image":12,"url":42,"published_at":43},[9,10,11],"https:\u002F\u002Fanalyze.presentr.me\u002Fblog\u002Fsubtitle-file-out-of-sync","2026-10-15T15:51:57.159Z",{},1792762674195]