Burned captions and safe zones for 9:16 shorts
Two ways to burn captions into a vertical clip — a quick drawtext overlay with
no subtitle file, or a proper .srt/.ass burn-in — plus why caption
position matters more on 9:16 shorts than on any other aspect ratio.
Why safe zones matter on 9:16
TikTok, Reels, and Shorts all draw their own UI over the bottom third and a thin strip at the top of every vertical video: captions, like/comment/share buttons, the username and sound title, the progress bar. A caption burned in at a "normal" bottom position gets covered by that UI on at least one of the three platforms. The fix is a fixed vertical margin that clears the UI band rather than sitting flush with the frame edge.
Option A — drawtext (no subtitle file)
Good for a short hook line plus one caption, or as a fallback when the build lacks
libass. Each drawtext clause is timed with
enable='between(t,START,END)'.
ffmpeg -hide_banner -y -i shot01_5s.mp4 -vf "\
drawtext=fontfile='/System/Library/Fonts/Supplemental/Arial.ttf':text='HOOK\: watch this':fontcolor=white:fontsize=58:borderw=3:bordercolor=black@0.8:x=(w-text_w)/2:y=180:enable='between(t,0,2)',\
drawtext=fontfile='/System/Library/Fonts/Supplemental/Arial.ttf':text='caption in the safe zone':fontcolor=white:fontsize=46:box=1:boxcolor=black@0.55:boxborderw=16:x=(w-text_w)/2:y=h-text_h-260:enable='between(t,2,4)'" \
-c:a copy shot01_captioned.mp4
The hook sits at y=180, clear of the top exclusion band. The caption sits at
y=h-text_h-260 — 260px up from the bottom edge on a 1920px-tall frame, which is
the SOP's working number for staying above the bottom UI band across TikTok, Reels, and
Shorts. x=(w-text_w)/2 centers each line horizontally regardless of text
length. box=1 on the second line adds a translucent background box so the
caption stays legible over busy footage.
Option B — timed .srt/.ass subtitles
For anything longer than a hook + one caption, burn a real subtitle file with the
subtitles filter and style it with force_style.
ffmpeg -hide_banner -y -i final.mp4 \
-vf "subtitles=subs.srt:force_style='FontName=Helvetica,FontSize=18,PrimaryColour=&H00FFFFFF&,OutlineColour=&HA0000000&,BorderStyle=1,Outline=2,Shadow=0,Alignment=2,MarginV=220'" \
-c:a copy captioned.mp4
Alignment=2 is bottom-center in ASS numbering. MarginV=220 lifts
the whole subtitle block 220px off the bottom edge — the same safe-zone reasoning as the
drawtext caption above, expressed as a style property instead of an explicit
y coordinate.
The font-library gotcha
Both filters depend on ffmpeg build flags that a minimal install often skips:
drawtextrequires an ffmpeg built with libfreetype.subtitles(and ASS styling) requires an ffmpeg built with libass.
Check before relying on either:
ffmpeg -filters | grep -E 'subtitles|drawtext'
If nothing prints, install a full build — on macOS, brew install ffmpeg pulls a
full-feature build; elsewhere, use a full-feature static build rather than a minimal one.
Overlay-PNG fallback
On a build that genuinely can't get either filter (locked-down CI box, a stripped container
image), the fallback is to render the caption text as a transparent PNG with any image tool
and composite it with a plain overlay filter instead — no font-rendering filter
required inside ffmpeg at all, at the cost of pre-rendering a PNG per caption instead of
passing text straight to the filter graph.
Related
Read the free preview for the SOP Pack's table of contents and one full script-gate check.
The full pack ($19) has the worked example, prompts and QA receipts; the $9 toolkit is just the scripts.