Skip to content
Zumkor
← Back to blog 9 min read

How to convert SRT to VTT on Mac (captions for web video)

Your web player wants WebVTT and you have an .srt file. Convert SRT to VTT on a Mac with one sed or ffmpeg line, or drag a whole folder into Zumkor, fully offline.

Convert your subtitles with Zumkor on your Mac — free for 7 days, then 5 files a day free or $19.99 once. Needs macOS 14.0 or later on an Apple silicon Mac (Apple M1 or later).

Get Zumkor on the Mac App Store

You have the captions as an .srt file. Maybe a transcription service sent it, a client exported it from their editor, or it came out of an old project. The place it’s going wants .vtt: a course platform, a video player on your own site, a client’s web team. Or you already pointed an HTML5 <track> element at the .srt, reloaded the page, and got no captions and no error.

This guide covers how to convert SRT to VTT on a Mac: what actually differs between the two formats, a one-line Terminal fix, ffmpeg for cleaner output, and the drag-a-folder route for batches. All of it runs on your Mac. A subtitle file is a full transcript of your video, and none of these methods upload it anywhere.

In this guide8 sections

SRT vs. VTT: what actually differs

Both are plain text. Here’s a short SRT file:

1
00:00:01,000 --> 00:00:04,200
Welcome back, everyone.

2
00:00:04,800 --> 00:00:07,500
Today we're fixing the captions.

And the same cues as WebVTT:

WEBVTT

1
00:00:01.000 --> 00:00:04.200
Welcome back, everyone.

2
00:00:04.800 --> 00:00:07.500
Today we're fixing the captions.

The differences that matter:

  • The header. A VTT file must begin with the line WEBVTT. A browser that doesn’t find it rejects the whole file.
  • The decimal mark. SRT writes milliseconds after a comma (00:00:01,000). VTT uses a period (00:00:01.000). A cue whose timestamp has a comma doesn’t parse, so it never shows.
  • Cue numbers are optional. In VTT, the 1, 2, 3 lines become optional cue identifiers. Keeping them is valid, and so is dropping them. Hours are optional too, so 00:01.000 is a valid VTT timestamp.
  • Encoding. WebVTT must be UTF-8. SRT files in the wild are often in an older Windows encoding, which is where broken accents come from (more on that below).
  • Extras. VTT can position a cue (line:10%, align:start), tag the speaker (<v Maria>), carry NOTE comments and style cues with CSS. SRT has none of that formally, though many SRT files carry <i> tags for italics, which VTT also understands.

Why VTT matters at all: the HTML5 <track> element, which is how every browser shows captions on a <video>, only accepts WebVTT. Many web players and course platforms are built on it and ask for VTT for the same reason. Desktop players are different. IINA, VLC, Plex and Infuse read SRT happily, so for watching on your own Mac or TV, keep the SRT. Convert when the destination is a browser.

That also means renaming the file doesn’t work. A .srt renamed to .vtt still has no header and still has commas in every timestamp, so the browser throws it out.

Before you convert: check the text encoding

This is the step that saves you from captions reading “Café” instead of “Café”. In Terminal:

file -I captions.srt

If the output ends in charset=utf-8 (or us-ascii, which is a subset of it), you’re fine. If it says iso-8859-1 or unknown-8bit, the file is in a legacy encoding, most likely Windows-1252 for Western European languages. Convert it to UTF-8 first:

iconv -f WINDOWS-1252 -t UTF-8 captions.srt > captions-utf8.srt

Swap WINDOWS-1252 for the right source encoding if the captions are in another script, such as WINDOWS-1251 for Cyrillic. Do this whichever method you use below. A converter that assumes UTF-8 will either garble the accented characters or, in ffmpeg’s case, drop the cues it can’t decode and print a warning you may not notice.

Method 1: one line of sed (no installs)

Every Mac already has the tools for the two required edits. In the folder with the file:

{ printf 'WEBVTT\n\n'; sed -E 's/([0-9]{2}:[0-9]{2}:[0-9]{2}),([0-9]{3})/\1.\2/g' captions.srt; } > captions.vtt

printf writes the header and a blank line. The sed expression finds every 00:00:01,000-shaped timestamp and swaps its comma for a period, without touching commas in the dialogue. The result is the second example above. For a whole folder:

for f in *.srt; do
  { printf 'WEBVTT\n\n'; sed -E 's/([0-9]{2}:[0-9]{2}:[0-9]{2}),([0-9]{3})/\1.\2/g' "$f"; } > "${f%.srt}.vtt"
done

It’s instant, needs nothing installed and changes nothing else. That last part is also its limit. sed doesn’t understand subtitles, it just edits text, so anything SRT-specific comes through as it was. <font color="…"> tags, which browsers ignore in VTT, stay in the file. Positioning codes like {\an8}, which some SRT tools use to move a line to the top of the screen, appear on screen as literal text. For clean SRTs from a transcription service, that’s rarely an issue. For files that have been through fansub tools or old editors, use ffmpeg.

Method 2: ffmpeg (parses the subtitles, batch-friendly)

ffmpeg, installed with Homebrew, reads the SRT as subtitles rather than as text and writes a fresh VTT:

brew install ffmpeg
ffmpeg -i captions.srt captions.vtt

What changes compared with the sed route:

  • Formatting is interpreted. Italics come through as <i> tags. <font> tags and {\an8}-style codes are removed instead of showing up on screen.
  • Cue numbers and zero hours are dropped. Timestamps come out as 00:01.000 --> 00:04.200. Both are optional in WebVTT, so the file is still valid, just shorter.
  • It’s strict about encoding. A cue that isn’t valid UTF-8 is dropped with an “Invalid UTF-8 in decoded subtitles text” warning. Run the iconv step first and this never comes up.

For a folder, with a separate output folder so nothing gets overwritten:

mkdir -p vtt
for f in *.srt; do
  ffmpeg -nostdin -n -loglevel error -i "$f" "vtt/${f%.srt}.vtt"
done

-n tells ffmpeg never to overwrite an existing file, and -loglevel error keeps the output quiet unless something actually fails.

ffmpeg is the most reliable free route. The cost is Homebrew, a command per job, and remembering the encoding step.

Method 3: Zumkor (drag the files, pick VTT)

If you’d rather not keep a Terminal recipe around, Zumkor converts subtitle files the same way it converts video and photos. It needs macOS 14 or later on an Apple silicon Mac (M1 or later).

  1. Drag your .srt files, or the folder they’re in, into Zumkor.
  2. Pick VTT.
  3. Check the rows. Each shows the exact filename it will produce before you convert, so you can confirm lesson-03.srt becomes lesson-03.vtt.
  4. Click Convert and choose where the VTT files go. The SRT originals stay where they are.

A queue holds up to 2,000 files, and the conversion runs entirely on your Mac. Nothing is uploaded, and it works with Wi-Fi off, which matters when the captions are an unreleased course, a client’s internal video or an interview transcript.

The same app covers the neighboring subtitle jobs:

  • The reverse. A VTT file converts back to SRT the same way, for a desktop player or an editor that wants SRT.
  • Subtitles stuck inside a video. Zumkor pulls embedded text subtitle tracks, including ASS/SSA tracks, out of a video as SRT or VTT. That’s the usual first step with an MKV, covered in the MKV to MP4 guide.
  • No subtitles at all. On macOS 26 or later, “Create subtitles from speech” writes new SRT or VTT captions from the soundtrack, on your Mac. The first time you use it, the Mac downloads Apple’s speech files. It’s a fresh transcription, so read it through before you publish it.

What it doesn’t do: standalone subtitle conversion is SRT and VTT only. A loose .ass or .ssa file goes into the list but refuses with a message, so use ffmpeg for those. Picture-based subtitles from DVDs and Blu-rays (VOBSUB, PGS) can’t become text, because Zumkor doesn’t do OCR.

Pricing: everything is free for 7 days. After that you can keep converting 5 files a day (25 a week) for free. The small Zumkor mark only ever goes on videos, never on subtitles. The Full Version is a one-time $19.99 purchase. Buy once and keep it forever, with no subscription and no account, and it’s shared through Family Sharing.

For one file and no fuss, the sed line is hard to beat. Zumkor earns its place when captions are a regular part of the job: a course with forty lessons, a client who sends SRTs every week, or a web-publishing session where the video needs converting too. In that case the MOV to MP4 or WebM to MP4 conversion and the captions go through the same queue.

Getting captions to actually show on a web page

Converting is half the job. If the VTT still doesn’t appear, it’s usually one of these:

  • The track markup. The basic form is <track kind="captions" src="lesson-03.vtt" srclang="en" label="English" default> inside the <video> element. Use kind="captions" when the file includes sound descriptions such as [music] for deaf and hard-of-hearing viewers, and kind="subtitles" for dialogue only. Without default, viewers have to switch the captions on themselves.
  • The server’s content type. Serve .vtt files as text/vtt. Some servers send them as plain text or a download, and some browsers then ignore the track.
  • Cross-origin files. If the VTT lives on a different domain or CDN from the page, the <video> element needs a crossorigin attribute and the server must send CORS headers. Otherwise the browser quietly refuses to load the track.
  • Matching names. Keep each caption file named after its video (lesson-03.mp4, lesson-03.vtt). It makes uploads to course platforms painless and mistakes obvious.
  • Timing. Conversion never moves a cue. If captions run early or late, the SRT was made for a different cut of the video, and the fix belongs in the captioning tool, not the converter.

Test in at least Safari and one Chromium browser. If the captions show in both, they’ll show for nearly everyone.

Bottom line

  • One file, nothing installed: the printf + sed line. It adds the header and fixes the timestamps, and leaves everything else alone.
  • Messy files or batches, free: ffmpeg -i captions.srt captions.vtt after an iconv pass if the encoding isn’t UTF-8.
  • Regular caption work, no Terminal: Zumkor. Drag the SRTs in, pick VTT, and convert on your Mac into a folder you choose, alongside the videos they belong to. Free for 7 days, then 5 files a day free, or a one-time $19.99 for everything.

Whichever route you choose, check the encoding first, keep the SRT originals, and test the result in a browser before you publish. Those three steps cover nearly every “my captions don’t show” problem. For what else Zumkor reads and writes, see the full formats list.

FAQ

What’s the difference between SRT and VTT?

Both are plain-text subtitle files made of cues with a start time, an end time and the words. A VTT file starts with a WEBVTT line and uses a period instead of a comma before the milliseconds, and it allows extras such as positioning and speaker tags. Browsers only accept VTT in an HTML5 track element, which is why web players ask for it.

Can I just rename an .srt file to .vtt?

No. Renaming leaves out the WEBVTT header and keeps the comma timestamps, so a browser rejects the file and shows no captions. The fix is two small edits, adding the header and changing the timestamp commas to periods, which a one-line sed or ffmpeg command, or Zumkor, does for you.

How do I convert a folder of SRT files to VTT on a Mac?

In Terminal, loop ffmpeg over the folder with for f in *.srt. Or drag the folder into Zumkor, pick VTT and click Convert: it runs on your Mac with nothing uploaded, and the VTT files go to a folder you choose. Keep the base names so each caption file still matches its video.