Cookies for analytics and advertising
We use cookies for analytics and advertising, both sent to Google. Refusing changes nothing you can see.Read the privacy page
Converting SRT to VTT makes a subtitle file the browser will actually load: the output opens with the required WEBVTT header line and every timestamp is rewritten with a full stop before the milliseconds instead of a comma. Those two differences are the entire reason an otherwise correct SRT produces a video with an empty subtitle menu, and both are fixed here in your browser.
Up to 100 files at once. Mixed formats are fine.
They convert one after another and download together as a ZIP.
SRT to VTT
HTML video takes subtitles through a track element, and the only subtitle format that element accepts is WebVTT. Hand a browser an SRT and nothing happens: no console error, no entry in the subtitle menu, just a video playing without captions. That silence is what brings most people to this conversion, because the file is correct, the markup is correct, and the format is the single thing that is wrong.
The two formats being close relatives makes the failure more confusing than it deserves to be. Structurally a WebVTT file is a SubRip file with a header line and a different decimal separator. The browser is not objecting to anything substantial; it is refusing a file that is two mechanical edits away from valid, and this converter makes both of them.
The first is the timestamp. SubRip writes 00:01:32,500 with a comma before the milliseconds; WebVTT writes 00:01:32.500 with a full stop. One character per timestamp, twice per cue, and a parser that finds the comma stops reading. Most of the world writes decimals with a comma, which is why hand-edited files acquire this fault so reliably.
The second is the header. A WebVTT file must begin with the word WEBVTT on its own first line, before anything else. It is not documentation and it is not optional — a file without it is rejected outright. The output here opens with WEBVTT followed by a blank line, and writes every timestamp as hours, minutes, seconds and milliseconds with the hours zero-padded and a full stop in front of the fraction.
It is the first thing almost everyone tries, and it is understandable: the file is text, the structures look alike, and changing an extension takes a second. It also cannot work, because neither of the two differences above lives in the filename. The result is a file that claims to be WebVTT, is served as WebVTT, and is discarded by the parser at the first line.
What makes this expensive is that the failure looks like something else. Developers who have renamed the file go on to check the track element, the file path, the MIME type and the player, none of which are the problem. Converting properly removes the possibility, which is worth doing before spending an afternoon on the markup.
SubRip numbers every cue, starting at one, on the line above the timestamp. This converter reads those numbers, uses them for nothing, and does not write them into the VTT. The output is a header, then a blank line, then timestamp-and-text blocks separated by blank lines.
That is a design decision rather than a loss. WebVTT treats the line before the timestamp as an optional cue identifier, not as a counter, and nothing in a browser or a player depends on it. Anything you genuinely need to attach to an individual cue — a vertical position, an alignment, a width — is a cue setting written after the end timestamp, and a numeric identifier would only be noise in front of it.
The text of every cue is copied verbatim from the SRT into the VTT. Nothing is stripped, escaped or reinterpreted. Both formats spell italics and bold the same way, with the same angle-bracket tags, so a file that uses them for emphasis keeps that emphasis on a web page.
The consequence is worth checking before you publish. A player-specific code that some desktop software honours in an SRT — an ASS-style positioning tag in curly braces is the common one — also survives verbatim, and a browser has no idea what it means. It will render as literal characters in the middle of a caption. If your SRT came from a fansub or a media-centre workflow, read the first few cues of the output.
The track element goes inside the video element, with src pointing at the .vtt file, kind set, srclang set to the language code, and a label that becomes the entry in the subtitle menu. Add the default attribute if the captions should be on when the video starts, because otherwise the viewer has to find the menu and most will not.
The kind attribute is the one worth thinking about rather than copying. Subtitles assume a viewer who can hear and translate the dialogue; captions assume a viewer who cannot hear and therefore describe the non-speech audio as well. Where captions are an accessibility obligation rather than a nicety, a track marked as captions that contains only translated dialogue satisfies the markup and not the requirement.
If the header and the timestamps are correct and the captions still do not appear, the remaining causes are in the page rather than the file. The track element may be missing kind or srclang, or the viewer may never have switched subtitles on because there is no default attribute anywhere.
The one that costs the most time is cross-origin. A VTT served from a different origin than the page — a separate asset domain, a bucket, a CDN hostname — is refused unless the response carries the right cross-origin headers, and the refusal is silent. The video plays, the menu is empty, and nothing on the page suggests why. Serving the subtitle file from the same origin as the page removes the whole class of problem.
Work through the four in that order rather than changing several things at once, because they produce the same symptom and fixing two while a third is still wrong looks like neither fix worked. The quickest discriminator is to open the .vtt URL directly in a tab: if the file renders as text, the path and the server are fine and the fault is in the markup or the origin. If it downloads or 404s, nothing about the track element was ever going to matter, and the remaining work is a hosting question rather than a subtitle one.
Subtitle editors, transcription services and desktop tooling are better at SRT than at anything else on this site; it is the format the whole ecosystem assumes. Correcting text and timing there and converting at the point of publishing is a sound division of labour.
The failure mode to avoid is maintaining both. Two files that started identical drift apart the first time somebody fixes a typo in whichever one they happened to open, and the drift is invisible until a viewer reads a caption that the transcript does not contain. Treat the VTT as build output: regenerate it, never edit it.
The file is produced with the WebVTT media type, text/vtt, and the server that eventually hosts it needs to send the same thing. Most static hosts map the .vtt extension correctly now, but a surprising number of older configurations fall back to a generic binary type or to text/plain, and a browser handed a caption file under the wrong type is entitled to refuse it. If the header and the timestamps are right and the track still does not load, the response headers are the next place to look and the fastest to check.
Two smaller deployment details save time later. Caption files are tiny and change rarely, so they cache well, and a long cache lifetime on a file you later correct is a caption error that persists on a viewer’s machine after the fix has shipped — version the filename rather than relying on a purge. And keep the extension as .vtt even when a build pipeline wants to fingerprint it, because some players and validators still key off the extension rather than the media type when deciding whether a track is worth fetching at all.
In your browser, in JavaScript, with no upload and no queue. The file is read as text, parsed into a list of cues with millisecond timings, and written back out in WebVTT form. There is no server involved, which is why it is instant and why there is no sign-up.
The free ceiling is 100 MB and no subtitle file will ever approach it — a feature film is a few tens of kilobytes of text. The more useful guarantee is that the output is written as UTF-8. SubRip has no way to declare its own encoding, which is why accented characters go wrong so often; committing the output to UTF-8 is what a browser expects and settles the question at the point of conversion.
| SRT | VTT | |
|---|---|---|
| Full name | SubRip Subtitle | WebVTT |
| File extension | .srt | .vtt |
| Media type | application/x-subrip | text/vtt |
| First published | 2000 | 2010 |
| Published by | — | W3C |
| Specification | — | WebVTT |
| Licensing | Open standard | Open standard |
| Standing today | Current | Current |
| Opens in a browser | No browser | Every browser |
| Considered instead | ASS | ASS |
Nothing is discarded. SRT and VTT both store their content losslessly, so the conversion is a change of packaging rather than a change of quality, and it can be repeated without accumulating damage.
VTT opens in every current browser. SRT has narrower browser support than that. If the file is going onto a web page or into a form, that is usually the whole reason for the conversion.
VLC and Subtitle Edit read both SRT and VTT, so there is a way to check the result against the original without a second tool.
VTT comes from W3C and dates from 2010, specified as WebVTT. VLC and Subtitle Edit all read it.
No. This conversion runs entirely inside your browser, so the file never leaves your device. You can confirm it yourself: open the network tab of your browser's developer tools and convert something. You will see the page load, plus the analytics and advertising the site is paid for with — and nothing carrying your file.
Because the track element accepts WebVTT and nothing else. A browser handed an SRT does not report an error — the video plays and the subtitle menu stays empty, which is why this looks like a markup problem when it is a format problem.
No. Two things have to change inside it: the file must begin with WEBVTT on its own first line, and every timestamp must use a full stop before the milliseconds instead of a comma. A renamed SRT fails both tests and is rejected.
No. SubRip numbers every cue and the converter does not write those numbers into the VTT, because WebVTT treats the line before the timestamp as an optional identifier rather than a counter. Nothing downstream needs them.
They come across unchanged. The text of each cue is copied verbatim, and both formats spell italics the same way. Player-specific codes such as an ASS-style positioning tag also survive verbatim, and a browser will render those as literal characters.
No. The parser and the writer are plain JavaScript running in your browser, so the subtitle file never leaves your machine. The free ceiling is 100 MB, which is orders of magnitude more than any subtitle file needs.
UTF-8. An SRT carries no declaration of its own encoding, so the reading step interprets the bytes and the writing step commits to UTF-8, which is what browsers expect from a WebVTT file.