Motion and video

Subtitles and captions

Subtitles write the dialogue for someone who hears the sound but does not understand the language; captions also write the sound effects and the music for someone who has no sound at all. That is a difference of definition, written into the HTML standard, and every later decision you make about format and file shape starts there.

  • Lesson 10 of 10
  • Beginner
  • Free, no signup

Five steps from audio to a subtitle file

  1. Transcribe

    Strip and compress the audio so it stays under the model size ceiling. If you cut it, write down the offset of each piece.

    1
  2. Correct

    Names, numbers and Latin words. Add nothing to the text that is not in the audio.

    2
  3. Time it

    A cue appears slightly before the sentence and leaves slightly after it. Break lines on a grammatical boundary.

    3
  4. Shape it

    Position and styling are possible only in VTT, through cue settings and the ::cue pseudo-element.

    4
  5. Export

    VTT for your own site, SRT for everyone else. And if burned-in is needed, burn again from the subtitle file for each size.

    5

The machine does step one and part of step three. Steps two and five are always a person work, and step four depends on the format you chose.

Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.

Subtitles and captions are not the same thing

Everyday speech treats them as one thing, and in practice most people build one file. But the HTML standard carries two separate definitions, and those two definitions produce two different outputs.

The WHATWG specification for the kind attribute on the track element says this: subtitles means transcription or translation of the dialogue, suitable for when the sound is available but not understood, for example because the viewer does not understand the language of the audio track. And captions means transcription or translation of the dialogue plus sound effects, relevant musical cues and other relevant audio information, suitable for when sound is unavailable.

So the difference is not language, it is whether the viewer has the sound at all. For a Persian video playing muted in a social feed, what you actually need is captions rather than subtitles, because a viewer who has turned the sound off has to know that a door slammed or the music changed. For the same video put on YouTube for an English audience, you need subtitles.

And a practical consequence most people skip: these are not one file and should not be. Build one file and ask it to do both jobs and the output is cluttered with sound-effect notes for the English viewer and thin for the deaf viewer. Build two, and separate them in the track element itself with kind and srclang. The same specification says srclang must be a valid language tag and that it is required whenever kind is in the subtitles state.

A cinema screen with a white bar at the bottom, a green bar of sound wave shapes and red timing marks

SRT or VTT: which one where

Both are plain text files and both do one job: a time span and a piece of text. Their difference is not one character, but it starts with one.

1
00:00:11,000 --> 00:00:13,000
The first line

WEBVTT

00:00:11.000 --> 00:00:13.000
The first line

The top is SRT and the bottom is VTT. Two differences are visible in those few lines and both are written into the W3C specification: a VTT file must begin with the WEBVTT signature, and the parser aborts if the stream lacks it; and a VTT timestamp puts a full stop before the three digits of thousandths where SRT puts a comma. That one character is why an SRT file renamed to vtt does not work in a browser.

The more important difference is in the table below, and its last row decides.

PropertySRTVTT
Published specificationwe found none we could citea W3C specification
Thousandths separatorcommafull stop
First line of the filethe number of the first blockthe WEBVTT signature, required
Media typenone declaredtext/vtt
Positioning text on the picturenocue settings and regions
Styling with CSSnothe ::cue pseudo-element
Speaker name in the textnoa voice span
In the web track elementnot acceptedwhat the standard asks for

So the rule is simple: VTT for playback on your own site, SRT for everywhere else. The HTML specification says plainly that if the track URL identifies a WebVTT resource and kind is not in the chapters or metadata state, the file must be a WebVTT file using caption or subtitle cue text. Which means that for a web player, VTT is not a preference; it is what the standard asks for.

Conversely, when you hand the file to a platform uploader or to an editor who will open it in their own software, SRT is the one that opens everywhere. We deliver both on our own video projects and it costs nothing: converting between them is a separator change and one signature line.

Burned or soft? Both are right, for two different places

Burned-in subtitles means the text has become part of the picture pixels and is no longer text. Soft subtitles means the text is a separate file that the player lays over the picture and the viewer can switch off.

Burned has one advantage that cancels every advantage of soft in certain places: it works everywhere. No player can fail to support it, because there is nothing to support. For social platforms that accept no sidecar file, and for a video meant to be passed around, it is the only option.

And it has three costs, all of which show up later. First, it cannot be switched off; if it sits badly, it sits badly forever. Second, it cannot be translated; for an English version you have to export the whole video again. Third, it cannot be read; neither a search engine nor a language model can read text inside pixels, so everything said in that video does not exist for any machine.

That third cost is the one subtitle tutorials almost never mention and the one that matters most to anybody who runs a site. If your video sits on a page that is supposed to rank, a soft subtitle file plus the transcript on the page itself is what makes the content of the video readable. Burning throws that away.

There is also a technical constraint experienced editors learn: never re-export burned-in subtitles at another size. Text burned for a 1080 wide frame and then scaled down to 720 breaks at the edges of the letters and degrades further under compression, because a compressor charges a lot for sharp edges. For each size, burn again from the subtitle file rather than from the previous export. The same principle applies to the whole picture in the lesson on video for the web.

Burned or soft? It depends where the video plays

Neither is better than the other. One works everywhere; everything about the other can still be changed.

Burned: inside the pixels, for anywhere

  • No player can fail to support it
  • The only option where no sidecar file is accepted
  • It cannot be switched off and cannot be translated
  • No machine reads its text

Soft: a separate file, on your own site

  • The viewer can switch it off or change its language
  • Its text is readable, by a search engine and by a machine
  • A new language means one new file, not a new export
  • The player has to support it, and not every player does

If the video both sits on your own site and goes out on social platforms, build both. The subtitle file is one file, and the burned export is made from it.

Where automatic transcription breaks

Speech to text models are good today, and the button everybody presses works right up until it does not. Here are four places it breaks, each with a source.

First, the model you choose may not produce a subtitle file at all. The OpenAI reference says the response_format key accepts json, text, srt, verbose_json, vtt and diarized_json, and immediately adds that for gpt-4o-transcribe and gpt-4o-mini-transcribe the only supported format is json. The same company guide says to start with the recommended model and to reach for a specialised model only when you need speaker labels, word timestamps, subtitle formats or translation into English. Which means the model being recommended to you is the one that does not give you a subtitle file. Worth knowing before you spend an hour hunting for an export button.

Second, word timestamps and a subtitle file do not come in one request. The same reference says word level timestamps are only available when response_format is verbose_json, and adds that generating word timestamps incurs additional latency. So you get either an srt file or data you can work with precisely, and if you want both that is two requests.

Third, the file size ceiling. The OpenAI guide says files up to 25 MB, in mp3, mp4, mpeg, mpga, m4a, wav and webm. A half hour video goes past that, so you have to strip and compress the audio and then cut it. And the cut is where the timing slips: every piece starts at zero, and you have to add each piece offset to its timestamps by hand. Somebody who does not know that builds a subtitle file that runs ahead of the picture from the middle onwards.

Fourth, names. This is where Persian takes the heaviest hit and where no number exists. A model that transcribes fluent Persian will still substitute the nearest familiar word for city names, family names and brand names. There is a capability here that almost nobody uses: the ElevenLabs guide for Scribe v2 says the model accepts keyterm prompting of up to 1000 terms, alongside precise word level timestamps, entity detection across 65 entity types and speaker diarization for up to 32 speakers, in more than ninety languages. Which means you can hand the model the list of names in your video in advance. That is one line of work and it has the largest single effect on Persian transcription quality.

And one thing worth stating plainly because many people expect otherwise: the OpenAI translation endpoint translates into English only, not into any language. If you want Persian subtitles from an English video, that is a separate translation job and the subtitle translation lesson is where it belongs.

Read this before you deliver a subtitle file

The Persian subtitle review sheetbefore delivery

Check these

  • Every proper noun and every number, one at a time
  • Line breaks on a grammatical boundary, not inside a phrase
  • The offset of each piece, if you cut the audio file
  • The file name and the language tag, matching the content

What spoils the file

  • Renaming srt to vtt without changing the separator and adding the signature
  • Improving a sentence the speaker said differently
  • Re-exporting a video with burned subtitles at a smaller size
  • One file doing both the subtitle and the caption job

This sheet does not replace viewing the file in the real player. The display direction of Latin text inside a right to left line is not identical across players, and only looking will tell you.

What a person has to do after the transcript

Automatic transcription gives you text, not subtitles. The distance between those two is four jobs, and no machine does any of them for you.

Check the names and the numbers. This is the one place where a machine error stops being nonsense and becomes meaningful and wrong: a wrong name in a subtitle is worse than a broken sentence, because the reader does not notice it and believes it.

Break the lines, and break them on a grammatical boundary. A cue that splits in the middle of a phrase makes the reader read it twice. The right boundary is where you would pause if you were saying it.

Time the cues against the speech rather than against the text. A cue should appear slightly before the sentence starts and stay slightly past its end. If you are working from a cut audio file, this is where the offset of each piece has to have been added.

And look at Latin text inside a right to left sentence. Display direction is not identical across players, and a Latin name or a number at the end of a right to left line lands in the wrong place in some of them. The practical fix is to view the file in the player it will actually be used in, not in a text editor. This is the one part of this lesson that reading cannot solve.

One simple rule we hold to on our own projects: add nothing to the text that is not in the audio. If the model has improved a sentence, that sentence is no longer what the speaker said, and a subtitle that is not what the speaker said is a far worse error than a spelling mistake.

The fast path, with AI

The fast path here is not a better model. It is two moves almost nobody makes: hand the model the list of names in your video before transcribing, and do not ask the model for a subtitle file. Take the text and the timestamps instead, and do the line breaking with a text model under an explicit rule, on the condition that it may not add or remove a single word. The first move rescues the names; the second is what separates a readable subtitle from chopped up text. Take the transcription model from <a class="text-link" href="/en/ai/audio/">the voice section</a> and the text model from <a class="text-link" href="/en/ai/">the AI section</a>.

  1. Before anything else, write the list of names: people, cities, brands, technical terms and every Latin word spoken in the video. That list is what you hand the model, and it is what you check against during review.
  2. Strip and compress the audio so it stays under the model size ceiling. If you have to cut it, write down the offset of each piece at that moment rather than later.
  3. Transcribe, and hand the model your list of names as key terms if your model accepts them. Take the output as text with timestamps rather than as an srt.
  4. Give the recipe below to a text model with your own transcript. Part three of the output, reconstructing the original text from the cues, is what proves to you that no word was lost or added.
  5. Build the file and view it in the player it will actually be used in, not in a text editor. Check the names one at a time against the list from step one.

Copy-ready recipe

Role: subtitle editor. Your job is to cut text into cues, not to rewrite it.

Language: {your language}
Character ceiling per line on my platform: {the number your platform states}
Maximum lines per cue: 2

The list of correct names:
{people, cities, brands and Latin words}

The transcript with timestamps:
{paste it here}

Return exactly these four parts:

1. The cues, each with a number, a time span, and one or two lines of text.
   A line break may only fall on a grammatical boundary, never inside a
   phrase or between an adjective and its noun. No line may exceed the
   character ceiling.

2. A list of places in the text where a word resembles one of the names above
   but is not exactly it. Report only; do not change anything yourself.

3. Join the text of every cue back together and set it beside the original
   transcript. If even one word has been lost or added, say where. This part
   is mandatory.

4. A list of cues in which a Latin word or a number sits at the start or the
   end of a line, because right to left players may display those out of
   place.

Correct no sentence, add no word, and remove no word. Even if a sentence is
grammatically wrong, leave it exactly as it is.

Before you trust the output: This path does not solve three things, and all three are a person job. First, names: part two of the output only reports and the decision is yours, because the model does not know which spelling is right. Second, display direction: part four tells you where to look and does not replace viewing the file in the real player. Third, the reconstruction in part three is a claim by the model, not a proof; put the original text and the rejoined text side by side once yourself. Fast does not mean unsupervised.

AI in this kind of work

AI does one of the five steps in this job, and it does that one well. Our position in one sentence: <strong>ask a transcription model for text and timestamps, not for a subtitle file, because a subtitle file carries editorial decisions and the model makes none of them knowingly.</strong>

Tools that actually help

  • Scribe v2 The ElevenLabs speech to text model, and the one in this list that publishes the most useful things: more than ninety languages, precise word level timestamps, speaker diarization for up to 32 speakers, entity detection across 65 types, and keyterm prompting of up to 1000 terms. That last capability is the one that works on Persian names, and almost nobody uses it.
  • whisper-1 The older OpenAI model, and the one you reach for when you want an srt or vtt file: the company own reference lists srt and vtt among the formats, then immediately says that for two of the newer models the only supported format is json. Its translation endpoint also translates into English only, not into any language.
  • Cohere Transcribe It is here because it is the only row in this list with both open weights and an Apache 2.0 licence, meaning it runs on your own hardware and commercial use is free. And here is its boundary: its 14 language list has no Persian. The Arabic model in the same family carries two languages and its model card says it gives neither timestamps nor speaker diarization, which for subtitles is half the job missing.

Where it backfires

Three specific risks here, and the first one outweighs the others.
First, a sentence the speaker never said. A transcription model sometimes cleans the text up, and that means your subtitle is no longer a quotation. For a tutorial that is annoying; for an interview or anything with legal weight it is a real problem. Reconstructing the text back from the cues is what catches it, and we have made that part mandatory in the fast path recipe.
Second, names. No vendor publishes a Persian error rate and we have not measured one, so you will see no number here. What you will see is a fix: hand the model the list of names in advance.
Third, confidentiality. An audio file of a meeting is personal content, and sending it to a cloud service means taking it out of your own hands. If the content is sensitive, an open weight model on your own hardware is the only option that solves it, with its language list as the condition.
And on access from Iran we suggest no way around anything. To see where each tool stands, read AI in Iran and the buying guide.

Sources: OpenAI: create transcription reference, response formats OpenAI: speech to text guide, file size and model choice ElevenLabs: models, Scribe v2 capabilities Cohere: Transcribe model card, languages and licence

Where this advice stops

This lesson did not run any transcription model on one identical Persian file and carries no accuracy rate, because no vendor publishes a Persian error rate and we have not measured one. Three other things are deliberately absent. Any conventional number for line length and reading speed, because those numbers differ between platforms and we have no citable source for a universal one; instead we said to take the number from your own platform. Any claim that SRT has no standard, because all we can say is that we found no specification we could cite, and the absence of something we did not find is not proof it does not exist. And any route to access from Iran. One last boundary: translating subtitles into another language is not the subject of this lesson, and the subtitle translation lesson is where it belongs.

From our own work

The line between what the machine gives you and what it does not is visible on the reference pages themselves, and we read them ourselves on the day this lesson was written. The OpenAI transcription reference lists all six response_format values and, in the same paragraph, names two models as exceptions whose only format is json; the same company guide recommends exactly those models as the place to start. So the sentence that changes your decision is on one page and the sentence that sends you to the wrong model is on another, and somebody reading only the guide never sees the contradiction. The same check works on any transcription tool and takes a minute: open its reference page, search for the word srt, and then see whether the model chosen for you is on the exception list.

Real follow-up questions

What is the difference between subtitles and captions?

The HTML standard defines them separately: subtitles are the dialogue, for someone who hears the sound but does not understand the language. Captions are the dialogue plus sound effects, musical cues and other relevant audio information, for someone with no sound available. For a video that plays muted, you need captions rather than subtitles.

Can an SRT file be converted to VTT?

Yes, and it is two changes: add the WEBVTT line at the top of the file and turn the comma in the timestamps into a full stop. Renaming the file is not enough; the W3C specification says the parser aborts without that signature, and a comma timestamp is not read either.

Are automatic subtitles good enough?

For understanding the content, usually yes; for delivering to a client, no. The problem is not overall quality but proper nouns and numbers: there a machine error stops being nonsense and becomes meaningful and wrong, and the reader does not notice. The minimum is to take the automatic file and check the names one at a time.

Do subtitles affect the page SEO?

Burned subtitles have no effect, because the text is inside the pixels and no machine reads it. A soft subtitle is a text file, and the transcript on the page itself is what makes the video content readable. If the video sits on a page that matters to you, put the transcript on the page rather than relying on the subtitle file alone.