How do I add subtitles to a video?

Set subtitleSource to auto for speech-derived captions, or supply your own cue list.

Updated

Orshot allows you to automatically generate and overlay subtitles on your videos. You can configure subtitles directly in the Studio editor per page, or pass a subtitleSource via the API at render time.

Page-Level Subtitles#

You can attach subtitles to each page directly in the Studio editor:

  • Upload an SRT file — subtitles are used as-is, no transcription needed
  • Auto-generate from page audio — generated voiceovers reuse their word timings; uploaded and other audio is transcribed

Page subtitles include full styling controls (font, color, background, position) that are configured visually in the editor. These styles are automatically applied during rendering.

API Usage#

You can also provide subtitles via the videoOptions.subtitleSource field in the render API request. This is useful for dynamic subtitle sources or when you want to override page-level settings.

Single Page Templates#

For single-page templates, pass a direct URL string to your source file.

JSON
{
  "templateId": "your-template-id",
  "modifications": {
    "text": "Hello World"
  },
  "response": {
    "format": "mp4"
  },
  "videoOptions": {
    "subtitleSource": "https://example.com/audio.mp3",
    "subtitleColor": "#ffffff",
    "subtitleBackground": "rgba(0,0,0,0.5)",
    "subtitleFontSize": "32px",
    "subtitleOffset": "50px"
  }
}

Multi-Page Templates#

For multi-page templates (like carousels turned into video slideshows), you can specify different subtitle sources for each page. Each page's video segment will use its corresponding source.

Pass an array of objects, where each object specifies the page number and the url.

JSON
{
  "templateId": "your-multipage-template-id",
  "modifications": { ... },
  "response": {
    "format": "mp4",
    "includePages": [1, 2]
  },
  "videoOptions": {
    "subtitleSource": [
      {
        "page": 1,
        "url": "https://example.com/intro-audio.mp3"
      },
      {
        "page": 2,
        "url": "https://example.com/part-2-audio.mp3"
      }
    ],
    // Styling applies globally to all pages
    "subtitleColor": "#ffffff",
    "subtitleBackground": "#000000"
  }
}

Word-by-Word Subtitles (Lyric Videos)#

Set subtitleMode: "word-by-word" to reveal each word in sync with the audio instead of showing the whole phrase at once. Combined with subtitlePosition: "center", this produces the lyric-video style popular on TikTok and Reels.

JSON
{
  "templateId": "your-template-id",
  "response": {
    "format": "mp4"
  },
  "videoOptions": {
    "subtitleSource": "https://example.com/song.mp3",
    "subtitleMode": "word-by-word",
    "subtitlePosition": "center",
    "subtitleBackground": "transparent",
    "subtitleShadowBlur": 8,
    "subtitleMaxWordsPerLine": 4,
    "subtitleWordSpacing": "0.6em"
  }
}

How it works:

  • Audio sources are transcribed with word-level timestamps. Each line shows up to subtitleMaxWordsPerLine words, and every word appears at the moment it is spoken or sung. A line stays visible until the next one starts.
  • .srt and .vtt sources skip transcription; word timings are spread across each cue's duration. This is the reliable path for song lyrics: if automatic transcription mishears the vocals, upload an SRT with the correct lyrics and timing.
  • The same mode is available in the Studio editor under the page's subtitle settings (Display: Word by word), where the style is saved on the template so every render and workflow uses it.

Supported Formats#

The subtitleSource URL can point to:

  • Audio Files: .mp3, .wav, .m4a (Automated transcription via OpenAI Whisper)
  • Video Files: .mp4, .mov, .webm (Audio extracted & transcribed)
  • Subtitle Files: .srt, .vtt (Used directly without transcription)

Caption Presets#

Pass videoOptions.captionPreset to apply a complete named caption style in one option — or pick the same presets visually in the Studio subtitle popover:

PresetLook
pillWhite text in a black pill, words appearing in sync (the classic default)
minimalClean phrase captions, no background, soft shadow
karaokeFull line visible dimmed; spoken words light up, current word highlighted yellow
boldBig uppercase display type with a highlighted current word
outlineUppercase white text with a black outline stroke
neonCyan glow karaoke highlighting
JSON
{
  "templateId": "your-template-id",
  "response": { "format": "mp4" },
  "videoOptions": {
    "subtitleSource": "https://example.com/audio.mp3",
    "captionPreset": "karaoke"
  }
}

A preset layers between the page's saved subtitle styles and your explicit subtitle* options, so any individual property you pass still wins — "captionPreset": "karaoke", "subtitlePosition": "center" uses the karaoke look centered on screen.

Two things worth knowing before you reach for one:

  • A preset sets subtitleMode and subtitleFontFamily along with the look. Every preset except minimal switches the page to word-by-word, and each brings its own font (karaoke and outline use Inter, bold uses Archivo Black, neon uses Poppins, pill uses Helvetica). Pass subtitleMode or subtitleFontFamily explicitly to keep your own.
  • An unrecognised preset name is ignored rather than rejected, so a typo silently leaves your existing subtitle styling in place.

subtitleWordReveal, subtitleActiveColor and subtitleActiveBackground only take effect in word-by-word mode — there is no "current word" to style in phrase mode.

Styling Options#

When using page-level subtitles, styles are configured visually in the Studio editor. When using API-level subtitles, you can customize appearance with the following videoOptions properties:

PropertyTypeDefaultDescription
subtitleColorstring"white"Text color (hex, rgb, or name)
subtitleBackgroundstring"transparent"Background color of the subtitle box
subtitleFontSizestring"30px"CSS font size value
subtitleFontWeightstring"700"Font weight ("400" to "800")
subtitleFontFamilystring"Arial, sans-serif"Font family (Google Fonts supported)
subtitleModestring"phrase""phrase" or "word-by-word"
subtitlePositionstring"bottom""bottom", "top", or "center"
subtitleOffsetstring"50px"Distance from the positioned edge (ignored for "center")
subtitleWordSpacingstring"0.45em"Gap between words in word-by-word mode
subtitleMaxWordsPerLinenumber4Words per line in word-by-word mode (2 to 8)
subtitlePaddingXstring"16px"Horizontal padding
subtitlePaddingYstring"8px"Vertical padding
subtitleBorderRadiusstring"6px"Corner radius of the subtitle box
subtitleShadowXnumber2Text shadow X offset (px)
subtitleShadowYnumber2Text shadow Y offset (px)
subtitleShadowBlurnumber4Text shadow blur radius (px)
subtitleShadowColorstring"rgba(0,0,0,0.8)"Text shadow color
captionPresetstringNamed caption style (see Caption Presets above)
subtitleWordRevealstring"appear""appear", "highlight", or "align"
subtitleSplitstring"word"Reveal by "word" or "letter"
subtitleMaxCharsPerLinenumberCharacter limit per line; overrides subtitleMaxWordsPerLine
subtitleActiveColorstringColor of the current word in word-by-word mode
subtitleActiveBackgroundstringBackground highlight of the current word
subtitleTextTransformstringe.g. "uppercase"
subtitleStrokeWidthnumber0Text outline stroke width (px)
subtitleStrokeColorstring"#000000"Text outline stroke color

Use subtitleWordReveal: "highlight" for karaoke-style captions or "align" to reveal spoken words while keeping the growing line centered. Set subtitleSplit: "letter" for a type-on effect. Use subtitleMaxCharsPerLine when a character limit fits the design better than a word limit.

Font Support#

You can use any Google Font by specifying its name in subtitleFontFamily. The system will automatically fetch and load it.

JSON
"videoOptions": {
  "subtitleFontFamily": "Inter, sans-serif"
}
Was this page helpful?

Ready to automate?

Start rendering images, PDFs and videos from your templates in under 2 minutes. Free plan, no credit card.

Get your API key
  • Image, PDF and video generation via API
  • Visual editor with AI and smart layouts
  • Zapier, Make, MCP and 50+ integrations
  • White-label embed for your own app
  • 30 free credits — no credit card required