What this does
TTML is the format streaming platforms actually deliver. Netflix, Amazon, Disney+ and the BBC all ship captions as TTML or one of its profiles — DFXP and IMSC — which is why a caption file pulled from a broadcaster will not open in VLC and will not hand off cleanly to a video editor. The cues are XML <p> elements with begin and end attributes, and the times inside them can be written four different ways. This converter reads all four and writes SubRip.
How to use it
- Paste the
.ttml,.dfxpor.xmlfile into the box, or drop it onto the page. - Every
<p>element is read, itsbegintime and itsendordurtime are converted to milliseconds, and inline markup is stripped from the text. - Copy the result or download it as a
.srtfile.
Good to know
- Profiles accepted: TTML 1.0, DFXP and IMSC. All three share the same
<tt>/<body>/<div>/<p>structure, so one parser covers them. - If a cue declares
beginbut noend, thedurattribute is used instead. A cue with neither is skipped rather than given a guessed duration. <br/>becomes a real line break. Nested<span>elements are unwrapped and their text kept — thetts:fontStyle,tts:colorandtts:textDecorationstyling on them is dropped, because SubRip has nowhere to put it.- Regions, positioning and background images (
smpte:backgroundImage) do not survive. TTML can place a caption anywhere on the frame; SubRip cannot. - The frame rate is read from the header only, not from per-cue overrides. Files that switch frame rate mid-stream are vanishingly rare, but they would need splitting by hand.
Four ways TTML writes a timestamp
Clock time with milliseconds — 00:01:02.350. This is the common case and the one closest to SubRip. A comma separator (00:01:02,350) is accepted as well, because some exporters emit it by mistake.
Clock time with frames — 00:01:02:11. The fourth field is frames, not milliseconds, so it only means something once it has been divided by the frame rate. That rate comes from ttp:frameRate on the root <tt> element; when the file does not declare one, 30 fps is assumed. A file authored at 25 fps and read as if it were 30 fps drifts by roughly 17 percent, which is the single most common reason TTML-to-SRT timing is right at the start of a file and wrong at the end.
Offset times — 10s, 100ms, 1.5m, 3h. These are durations rather than points on a clock, and TTML permits them in begin as well as in dur. The converter understands h, m, s and ms.
Frame and tick offsets — 30f and 100t. Frames are divided by the frame rate, ticks by the rate declared as ttp:tickRate. Both turn up in broadcast files where timing is authored on a frame grid rather than in wall-clock seconds.
Entities are decoded. Because the source is XML, an ampersand arrives as & and a quote as ". Named and numeric entities are both decoded before the text reaches SubRip, so what you see in the output is what the caption was meant to say.
Worked example
Input — .ttml
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttp="http://www.w3.org/ns/ttml#parameter" xmlns:tts="http://www.w3.org/ns/ttml#styling" ttp:frameRate="25">
<body><div>
<p begin="00:00:01.000" end="00:00:04.000">Hello there.</p>
<p begin="00:00:04.200" dur="2.8s"><span tts:fontStyle="italic">Music playing</span><br/>Sign on wall: EXIT</p>
</div></body>
</tt>
Output — .srt
1 00:00:01,000 --> 00:00:04,000 Hello there. 2 00:00:04,200 --> 00:00:07,000 Music playing Sign on wall: EXIT
The second cue had no end attribute — its dur of 2.8s was added to the begin time. The span was unwrapped and the br became a real line break.
FAQ
Why does the timing drift towards the end of the file?
hh:mm:ss:ff timestamps and declares no ttp:frameRate, the converter assumes 30 fps. A file authored at 25 fps then accumulates error in proportion to the timecode — small at the start, obvious by the end. Open the file, read the rate from the root element, and if it is not 30 you will want to re-time the result with the resync tool.Can I convert the other way, from SRT to TTML?
The output is empty even though the file opens in a player
<p> elements carrying a begin attribute. Files that put the timing on <span> children, or that store cues in a non-standard element, have nothing to read. Check the first few lines of the body section.Does this upload my caption file anywhere?
Why did my italics disappear?
<i>, <b> and <u>, and TTML expresses italics as a tts:fontStyle attribute on a <span> or through a named style in a <style> block. Inline spans are unwrapped rather than translated, so the words survive and the emphasis does not.Troubleshooting
- No cues found at allThe file needs
<p>elements that carry abeginattribute. A TTML file whose cues were emptied out, or a file that is really a plain XML config with a .ttml extension, will produce nothing. Open it in a text editor and look for the wordbegin. - Every cue is a few seconds off, and the error growsA frame-rate mismatch. Times written as
hh:mm:ss:ffwere divided by the wrong rate. Note thettp:frameRatevalue in the file header and re-time the output — the ratio presets on the resync tool cover the common 23.976 / 24 / 25 / 30 combinations. - The text contains stray ampersands or question marksThe source used an entity the decoder does not know, or the file is not UTF-8. Re-save it as UTF-8 from the editor that produced it. Unrecognised named entities are left as written rather than guessed at.
- Two languages came out in one cueThat is how the file was authored — one
<p>containing both languages, usually separated by a<br/>. Split them into separate files if you need one language per track; the converter preserves the text exactly as written. - The player shows the subtitles but they look plainExpected. SubRip has no font, colour or positioning fields, so all of that is discarded on the way through. Keep the original TTML as the master if appearance matters, and treat the SRT as a delivery or review copy.
Related tools
SRT to VTT Converter
Convert .srt subtitle files to WebVTT (.vtt) for HTML5 video, right in your browser.
ASS / SSA to SRT Converter
Turn SubStation Alpha (.ass, .ssa) subtitles into clean SubRip (.srt) — in your browser, with nothing uploaded.
Clean Up AI-Generated Subtitles
Remove sound cues, HTML tags, speaker labels and duplicate cues from auto-generated captions.