1 · Load a file
2 · Pick a transform
One click runs four safe passes at broadcast-typical defaults — trim overlaps, open a minimum gap, hold a readable min/max duration, then re-wrap long lines. Every change is listed below, and anything that can’t be fully fixed (a cue too short to reach the minimum, a word longer than the line) is shown honestly as a residual — never forced into an overlap or dropped. The fixed file is downloadable.
Collapses consecutive cues whose text is identical — the stutter auto-generated and rolling captions leave behind — into one cue that spans from the first duplicate’s start to the last duplicate’s end. Only back-to-back repeats are merged; a line that genuinely recurs later in the file is kept. Text is left exactly as authored (only leading/trailing whitespace is ignored for the match) and cues are renumbered. The result tells you how many cues were removed.
Loads the file above as a second language and folds it onto the primary track (the file in box 1) — each secondary line is stacked under the primary cue it overlaps most, giving one dual-language caption file. Timings and cue count come from the primary track; a secondary line that overlaps no primary cue is dropped (reported in the count). Both files stay SRT/VTT and never leave your device. Leave this empty to use any other transform normally.
e.g. 2.5 pushes every cue 2.5 s later; -1.5 pulls them 1.5 s earlier. Times below zero clamp to 00:00:00.
Use when a track is in sync up to a point (an ad-break re-insert, a trimmed scene) then drifts. Cues starting before the boundary are left exactly as authored; a cue whose start is exactly the boundary is shifted. Time as ss, mm:ss.mmm, or hh:mm:ss.mmm.
Give two moments you can eyeball in the video. Each: where the line is now → where it should be. Times as ss, mm:ss.mmm, or hh:mm:ss.mmm.
Fixes linear drift from a frame-rate mismatch (e.g. a 23.976 fps track played at 25 fps runs progressively fast). Every timestamp is scaled by from ÷ to. Same source & target is an exact no-op.
Format is auto-detected from the file’s header/extension. Force LRC here if you dropped a start-only lyrics file without a .lrc extension — LRC carries no end times, so each cue’s end is synthesized as the next line’s start (capped at 8 s; the last line gets exactly 8 s).
MicroDVD (.sub) stores each cue as frame numbers, not clock time, so the fps it was authored at is needed to place cues on the timeline — it is never guessed. Common rates: 23.976, 24, 25, 29.97, 30. A wrong value stretches or squeezes every timestamp proportionally.
SRT↔VTT is lossless; SBV and TTML/DFXP are both read and written. ASS/SSA, MicroDVD and LRC are read-only inputs: they convert to SRT/VTT/SBV/TTML, but their styling (ASS positions/colours/fonts) can't survive a plain-text caption and is honestly dropped — words, timing and line breaks are kept. Writing TTML emits a minimal, valid <tt> document (clock timing, one <p> per cue, <br/> line breaks); it carries no regions/colours because a plain cue has none. Writing LRC is lossy: LRC lyric files hold only a start stamp per line, so every cue’s end time is dropped — you’ll see an honest warning above the result when LRC is the target. MicroDVD isn't offered as an output because there is no writer for it here.
Pulls each cue’s end earlier so at least this many milliseconds of blank screen precede the next cue — killing the flicker when one caption hides and the next appears on the same frame. ~2 frames (80–125 ms) is a common broadcast floor. Cue starts are never moved, and no cue is shrunk below a 1-second on-screen minimum: any pair that can’t reach the full gap at that floor is listed honestly in the result rather than mangled.
Holds every cue on-screen for a readable window. A cue shorter than the minimum has its end pushed later (its start never moves); a cue longer than the maximum has its end pulled in. 1000–7000 ms is a common range (min ≥ ~1 s to be legible, max so a caption doesn’t linger). A short cue is never extended onto the next cue’s start: any cue that can’t reach the minimum without colliding is stretched only as far as legal and listed honestly in the result rather than forced.
Re-wraps every cue’s text at word boundaries so each line fits the character limit, and when two lines are needed it splits them to keep the lines even. Existing breaks are normalized, then rebuilt from scratch. Timings are untouched and no text is ever dropped: a single word longer than the limit is kept whole on its own line, and text that genuinely needs more than the max lines is packed onto the last line — both cases are reported in the result.
One-click SDH / hearing-impaired cleanup that edits inside each cue — a line mixing a tag with real dialogue (“[door slams] Who’s there?”) keeps the dialogue; only the annotation is stripped. Speaker-label removal is deliberately conservative: it only touches an ALL-CAPS word (or words) followed by a colon at the very start of a line, so a mixed-case name like Dr. Smith: is never eaten. Timings are never touched; a cue left completely empty (e.g. a bare ♪ line) is dropped and the rest renumbered.
Timings are never touched — only cue text. SDH removal is opt-in and conservative: a cue that mixes dialogue with a bracketed tag keeps all its words; only cues that are purely a sound description or a bare all-caps label are dropped. Cues left empty after cleaning are removed and the rest renumbered.
Divides any cue whose text is longer than the character limit or whose duration exceeds the maximum into two or more shorter cues, splitting the text at word boundaries and sharing the original time span in proportion (a 100 ms gap is opened between the parts). This is different from “Split into two files” — that cuts the whole track at a clock time; this reshapes over-long cues. A cue that can’t be split cleanly (a single unbreakable word, or no split that keeps the gap without a zero-duration part) is left exactly as authored and listed below — never mangled or dropped.
Rewrites SRT cue numbers to 1…N in document order, fixing gaps or out-of-order indexes. For VTT this is an honest no-op — WebVTT identifiers are optional and left untouched.
Produces two files. A cue is kept whole in the part its start falls in — a cue is never cut mid-line; a straddling cue stays in part 1 with its full duration. A cue starting exactly at the split point goes to part 2. Time as ss, mm:ss.mmm, or hh:mm:ss.mmm.
Strips every timecode, index and formatting tag, leaving just the spoken words as plain text you can paste into notes or a search index. Deduping removes the echo rolling/auto-generated captions leave behind; a line that genuinely recurs later is kept.
Flags cues that show too briefly for their text. 17 CPS is a common Latin-script ceiling; use a lower value (~9) for CJK, which reads slower per character. Line breaks are not counted; spaces and punctuation are. This is a read-only report — nothing to download.
One read-only pass that lints every cue for the timing and readability defects professional QC flags: reading speed over the CPS ceiling, a gap below the minimum, a true overlap with the next cue, a duration under the minimum or over the maximum, a line past the character limit, and a cue needing more than the max lines. Each finding is shown per cue with its measured value vs the threshold below — nothing is changed and there is nothing to download. Defaults are broadcast-typical; tune any threshold above.