Customize captions API: color, position, size, and words per line
Customize burned-in captions with Sume's design object: override color, position, size, and words per phrase on every style except punch and tiktok-green.

To customize burned-in captions with the Sume API, add a design object to POST /v1/video-captions. Each key overrides one token of the chosen style: colors.active recolors the spoken word, placement.anchor_ratio moves the line up or down, typography.font_size_ratio sets the size, and phrasing.max_words caps the words per phrase.
Token names and ranges come from Sume's Video captions page and the API reference schema, read on 2026-09-26; per-style starting values are the renderer's current defaults. Picking a style in the first place is covered in How to burn captions onto a video.
How does a design override work?
A style is a set of design tokens, and design overrides them for one request. Every field is optional and merges over the style's own value, so one key changes one thing and everything else stays as the style draws it. design works on every style except punch and tiktok-green, which render on a path that reads none of these tokens.
This request keeps black-outline but recolors the spoken word, lowers the line, and shortens each phrase:
curl -X POST https://api.sume.com/v1/video-captions \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: video-caption-design-001" \
-d '{
"video_url": "https://media.sume.com/artifacts/example/clean.mp4",
"style": "black-outline",
"design": {
"colors": { "active": "#22D3EE" },
"placement": { "anchor_ratio": 0.8 },
"phrasing": { "max_words": 4 }
}
}'Which tokens can I change, and what are the ranges?
Colors take hex, rgb() / rgba(), or transparent. Numbers must sit inside these ranges:
| Token | Range | What it sets |
|---|---|---|
colors.base, colors.active | Color | Resting text, and the word being spoken. |
colors.stroke | Color | Outline color, where the style draws one. |
colors.accent, colors.accent_deep | Color | Highlight block or sweep, and the far end of its gradient (defaults to accent). |
colors.card | Color or null | Card or pill fill. null draws no card. |
typography.base_weight, active_weight | 100–1000 | Variable font weight of resting text and of the spoken word. |
typography.active_scale | 0.5–2 | Scale applied to the spoken word. |
typography.font_size_ratio | 0.01–0.4 | Type size as a fraction of a 1080-wide frame, before the fit shrinks a long line. |
typography.safe_width_ratio | 0.3–1 | Share of frame width a caption line may occupy. |
typography.stroke_width_px | 0–24 | Outline width in pixels at the 1080-wide reference. |
placement.anchor_ratio, landscape_anchor_ratio | 0.05–0.95 | Line center as a fraction of frame height, portrait and landscape. |
phrasing.max_words | 1–12 | Words per on-screen phrase. |
phrasing.max_chars | 4–60 | Characters per on-screen phrase. |
phrasing.pause_seconds | 0.05–3 | Silence that breaks one phrase into the next. |
motion.enter_seconds, exit_seconds, emphasis_in_seconds, emphasis_out_seconds | 0–2 | Phrase enter and exit, and how long the spoken word takes to take and release the emphasis. |
How do I move captions up or down?
Set placement.anchor_ratio. The renderer currently places the line's center that fraction of the way down the frame, so 0.05 sits near the top and 0.95 near the bottom. If you send only anchor_ratio, the landscape position follows it; send landscape_anchor_ratio as well to place wide frames separately.
How do I change the size and the words per line?
typography.font_size_ratio sets the type size against a 1080-wide frame, and safe_width_ratio sets how much of the width a line may take. A long line can still render smaller, because the in-browser fit shrinks it to the safe width.
phrasing.max_words and phrasing.max_chars cap each on-screen phrase, and a silence longer than pause_seconds starts a new one. slam shows one word at a time, so its phrasing caps currently have no effect.
What values do the styles start from?
An override edits the style's current defaults, so a small change stays close to its own look. Five of the styles that accept design currently start here:
| Style | Anchor (portrait) | Words / characters per phrase | Spoken-word color |
|---|---|---|---|
slam | 0.58 | One word at a time | #FFD700 |
black-outline | 0.64 | 7 / 22 | #FFD700 |
highlight | 0.7 | 7 / 22 | White on a #ff1745 to #c40f31 gradient block |
pill-karaoke | 0.74 | 7 / 22 | #FFD700 in a rgba(12,12,16,0.82) pill |
korean-ad | 0.76 | 5 / 14 | #FFE14D |
What does design not do?
design edits a look; it does not pick the face or the wording, and it rejects anything it cannot draw safely:
- It is not supported on
punchortiktok-green. - Colors in any other CSS syntax are rejected rather than drawn into the render document.
- A number outside its range is a
400, so a bad look fails at request time instead of rendering wrong and billing. - The face is
font, a separate field for Hangul styles only. The wording comes from speech-to-text,script_text,words, orcues. - An omitted
stylerenders the spoken word in the fill color. Nameblack-outlineorslamto keep its gold tint, or setdesign.colors.active. designbelongs toPOST /v1/video-captions. The avatar-videocaptionsobject has nodesignfield.
Sources
Related posts
Written by Sume