How to burn an SRT file into a video
Burning an SRT file draws its lines into the picture. Sume's captions API takes no .srt file, so turn each block into a cue and send the cues instead.

To burn an SRT file into a video, draw each subtitle block into the frames between its two timecodes, so the text becomes part of the picture and shows on every player. Sume's captions API does this, but it does not take the .srt file itself: turn each block into a cue with text, start, and end in seconds, then send the cues with the video's URL to POST /v1/video-captions. Cues skip speech-to-text, so Sume burns exactly your lines at your times.
Sume details come from the Video captions docs and the caption schema in the Sume API reference, read on 2026-09-27; details marked as current code are read from Sume's code. Whether to burn at all is covered in hard subtitles vs soft subtitles.
How do I turn SRT blocks into cues?
An SRT block is a sequence number, a timing line such as 00:00:01,000 --> 00:00:03,500, and one or more lines of text. Each block becomes one cue:
- Drop the sequence number. A cue takes only
text,start, andend. - Convert both timecodes to seconds: hours × 3600, plus minutes × 60, plus seconds, with the milliseconds after the comma as decimals.
00:00:03,500becomes3.5. - Join a block's text lines with a newline: the docs allow one in a cue's text for a two-line card. In current code the default Latin style,
slam, ignores the break and draws the words in capitals. - Strip SRT formatting tags such as
<i>; the docs define no markup for cue text.
import re
TIME = r"(\d+):(\d\d):(\d\d)[,.](\d{3})"
def seconds(h, m, s, ms):
return int(h) * 3600 + int(m) * 60 + int(s) + int(ms) / 1000
def srt_to_cues(srt_text):
cues = []
for block in re.split(r"\n\s*\n", srt_text.strip()):
lines = block.strip().splitlines()
timing = next(i for i, line in enumerate(lines) if "-->" in line)
start, end = re.findall(TIME, lines[timing])[:2]
text = re.sub(r"<[^>]+>", "", "\n".join(lines[timing + 1 :])).strip()
cues.append({"text": text, "start": seconds(*start), "end": seconds(*end)})
return cuesHow do I send the cues to Sume?
Send the video's public HTTPS URL as video_url and the list as cues (segments is an alias). cues cannot be combined with words, segments, or script_text. Add an Idempotency-Key: if the request times out, resending it with the same key and the same body returns the original job instead of a second one.
Omit style and the wording picks it: slam for Latin text, black-outline for Korean. A style you name is rendered as named, but Korean lines on slam, punch, or tiktok-green are refused with 400 caption_hangul_text_latin_style. To move the lines up or down, see customize burned-in captions.
For Korean lines, add "design": { "phrasing": { "max_words": 1 } }. In current code black-outline and the other Hangul phrase-card styles merge short cues 0.45 seconds or less apart into one card of up to 22 characters, so a line can appear before its start; a limit of one keeps each cue on its own card.
curl -X POST https://api.sume.com/v1/video-captions \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: srt-burn-001" \
-d '{
"video_url": "https://example.com/clip.mp4",
"cues": [
{ "text": "Welcome to the tour.", "start": 1.0, "end": 3.5 },
{ "text": "Setup takes one minute.", "start": 3.5, "end": 6.2 }
]
}'What are the limits?
Check the file against these before you send it. A longer subtitle file does not fit in one job.
| Rule | Limit |
|---|---|
| Cues per job | 1 to 200 |
Cue text | 1 to 400 characters |
Cue start and end | 0 to 60 seconds, with end greater than start |
video_url | A fetchable public HTTPS video. Localhost, private-network, non-HTTPS, and signed or private URLs are rejected |
| Source length | 60 seconds or less; a longer source fails with duration_out_of_range |
| Source audio | The video needs an audio stream, even with cues; one without fails with missing_audio_stream |
| SRT upload | Not supported; send the lines as cues |
What if my video is longer than 60 seconds?
Split it. Cut the video into chunks of 60 seconds or less, between SRT blocks rather than inside one. Give each chunk the cues that fall inside it, with the chunk's start time subtracted from every start and end, then rejoin the captioned chunks. Add captions to a long video walks through the cut and the rejoin. Sume's cutting and joining tools read only videos already on media.sume.com in your workspace, such as an earlier Sume job's output.
How do I get the result, and what does it cost?
Poll GET /v1/jobs/:id/status until it is terminal, then read the captioned video_url from GET /v1/video-captions/:id. Each accepted standalone caption job reserves and captures the fixed amount listed on the Video captions page, for videos up to 60 seconds; the docs say to confirm live pricing in GET /v1/catalog. The submit response quotes the job's amount as usage.billable_amount_usd.
Sources
Related posts
More in Media tools
- How to calculate speech rate in words per minute
Speech rate is words spoken divided by speaking time in minutes. Word timestamps from speech-to-text measure both, per recording or per sentence.
- How to color correct a video: fix a color cast and warmth
Color correct a video with FFmpeg filters on Sume: colorbalance removes a yellow or green cast, colortemperature sets warmth, and eq sets saturation.
- How to convert HEVC (H.265) video to H.264
Convert HEVC (H.265) to H.264 by re-encoding the video stream. On Sume, an exact trim of a whole non-HDR clip returns an H.264 MP4.
- How to crop a video without losing quality
A normal crop re-encodes the frames, so lose as little as you can: crop once, from the original, and don't scale back up. How Sume encodes each edit.
Written by Sume