How to add bilingual subtitles to a video
Burn two languages onto one video with Sume: put both lines in each cue of one caption job, or run two jobs, each language at its own height.

To add bilingual subtitles to a video, show each line in two languages at once, such as the original with its translation just below or above it. To burn both into the video with Sume, send timed cues to POST /v1/video-captions in one of two ways: one job whose cues each hold both lines, separated by a newline, or two jobs, where the second captions the first job's output with the other language at a different design.placement.anchor_ratio.
Sume facts come from the Video captions docs and the caption schema in the Sume API reference, read on 2026-09-27. This post is for creators burning both languages in; viewers who want two subtitle tracks at once need a player that can show them.
Where do the two sets of lines come from?
The captions API has no translation step: language only tells speech-to-text what to expect, so the second language's lines are yours. One pipeline is to get timed sentences from Sume's speech-to-text, translate each one, and keep each sentence's start and end for both languages. Translate video subtitles by API walks through it.
Already have two SRT files? Pair their blocks by time; each pair becomes one bilingual line.
How do I burn both languages in one job?
Join the two lines of each pair with a newline in one cue: a cue's text may include one for a two-line card, up to 400 characters in all. Both lines share the cue's times, style, and height, so they always appear and leave together.
The style has to draw both scripts, so name it. For Korean with English, name black-outline or another Hangul phrase-card style, which burns text exactly as written. Don't leave style out or count on a 400: in current code both the default style and the caption_hangul_text_latin_style refusal go by whether at least half the letters across all your cues are Hangul, so English-heavy pairs can land on slam, whose Latin face has no Hangul glyphs.
The style also decides the line break. In current code the Hangul phrase-card styles keep it, while korean-ad and the default Latin style, slam, ignore it, so for two Latin-script languages, use two jobs. The phrase-card styles also merge short cues 0.45 seconds or less apart into one card of up to 22 characters; design.phrasing.max_words: 1 keeps one cue per card.
A named black-outline keeps its gold spoken-word tint, and in current code each cue counts as the spoken word from its start to its end, so the sample sets design.colors.active to white to keep both lines white.
curl -X POST https://api.sume.com/v1/video-captions \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: bilingual-one-pass-001" \
-d '{
"video_url": "https://example.com/interview.mp4",
"style": "black-outline",
"design": { "colors": { "active": "#FFFFFF" } },
"cues": [
{ "text": "Thanks for joining us.\n함께해 주셔서 감사합니다.", "start": 0, "end": 2.4 },
{ "text": "Setup takes a minute.\n설정은 1분이면 됩니다.", "start": 2.4, "end": 5.1 }
]
}'How do I put each language at its own height?
Run two jobs. The first burns language one: the speech itself (no wording field), your transcript as script_text, or timed cues. The second sends the first job's captioned video_url as its source, with the other language as cues and a different design.placement.anchor_ratio, the line's center as a fraction of the frame's height from 0.05 to 0.95. In current code that fraction is measured from the top, so 0.9 sits lower than 0.75.
Leave room between the two heights for the text itself, and check the first result before a batch. design works on every style except punch and tiktok-green.
| One job, two-line cues | Two jobs, one language each | |
|---|---|---|
| Caption jobs billed | One | Two |
| Height | Both lines share one anchor_ratio | Each job sets its own anchor_ratio |
| Style | One style has to draw both scripts | Each job names its own style |
| Timing | Both lines share each cue's start and end | Each language keeps its own times |
| Line break | Kept by the Hangul phrase-card styles; slam and korean-ad ignore it | Not needed |
What are the limits?
- Each job takes 1 to 200 cues, each 1 to 400 characters, with
startandendbetween 0 and 60 seconds. - Today the caption worker refuses a source longer than 60 seconds or one without an audio stream. The first job's captioned MP4 keeps the clip's sound in current code, so it can go into the second job.
- The docs describe Latin display styles and Hangul styles only; they name no style for other scripts, such as Chinese or Japanese.
- Each accepted caption job reserves and captures the fixed amount listed on the Video captions page, for videos up to 60 seconds, so the two-job route costs two of them.
Sources
Related posts
More in Media tools
- Add captions to a long video by API: split, caption, rejoin
One Sume caption job takes up to 60 seconds of video. Cut a longer video into chunks, caption each one, then rejoin them over the original audio.
- How to add an image to a video at a specific time
Show a picture only between two timestamps: compose it over that stretch of the clip, or cut to it as a still, then rebuild the video in one render.
- How to add a logo or watermark to a video
Add a logo or watermark to a video by laying the image over every frame. Sume's Timeline compose does it for Sume-hosted files in one MP4.
- How to add subtitles to a video from a transcript
Have the words but no timings? Send the transcript as script_text with the video to Sume's captions API, which times it to the speech and burns it.
Written by Sume