💡 For social video, the platform determines which method to use. TikTok and Instagram Reels do not accept external subtitle files, so burned-in captions are the only way to deliver styled text on these platforms. YouTube and YouTube Shorts accept SRT uploads directly, making a soft caption track the better choice there: no re-encode, viewer-toggleable, and reusable for translation.
Key takeaways
- Burned-in:
-vf "subtitles=captions.srt:force_style='FontName=Arial,FontSize=28,Outline=2,MarginV=160'"plus a video re-encode with-c:v libx264 -crf 23. Text becomes permanent pixels. - Soft track (MP4):
-c:s mov_text -metadata:s:s:0 language=eng -disposition:s:0 default. Video and audio copy with-c:v copy -c:a copy: no re-encode, no quality loss. - TikTok and Instagram Reels: no subtitle file upload slot. Burned-in is the only way to deliver styled, precisely positioned captions before upload.
- YouTube and YouTube Shorts: upload SRT or VTT directly in YouTube Studio. No video re-export needed; viewers can toggle the track on or off.
- Burned-in captions cannot satisfy WCAG 1.2.2 for web video (they cannot be toggled). A soft track is required for accessibility compliance.
What is the difference between burned-in and soft captions?
Burned-in captions (also called hardcoded or open captions) are rendered into the video frame itself: every pixel of text becomes part of the image permanently. Once encoded, you cannot remove or reposition them. A re-encode is unavoidable because the subtitles filter runs inside ffmpeg's video filter graph, which requires the video to be decoded, filtered, and re-compressed.
Soft captions sit in a separate track inside the container. The player renders them at runtime. The video stream is never touched: -c:v copy passes it through byte-for-byte. I use soft tracks for anything that will need editing, multiple languages, or viewer control.
| Factor | Burned-in | Soft track |
|---|---|---|
| Viewer can toggle | No | Yes (player caption menu) |
| Video re-encode needed | Yes | No (-c:v copy) |
| Editable after delivery | No | Yes (replace the file) |
| Multi-language output | One re-encode per language | Multiple tracks, one file |
| WCAG 1.2.2 (web accessibility) | Fails (cannot be toggled) | Meets toggle requirement |
Which social platforms accept a subtitle file upload?
This is the decision point that determines everything else. YouTube is the exception that makes soft tracks practical for creators. TikTok and Reels are the reason burn-in exists as a creator workflow.
| Platform | SRT upload | VTT upload | Auto-captions | In-app edit |
|---|---|---|---|---|
| YouTube / Shorts | Yes | Yes | Yes | Yes (YouTube Studio) |
| TikTok | No | No | Yes | Yes (after auto-gen) |
| Instagram Reels | No | No | Yes | Yes (Edits app) |
YouTube also accepts SBV, SCC, TTML and several other formats. For a creator delivering a translated subtitle track, SRT is the simplest choice: plain text, editable in any editor, accepted everywhere YouTube accepts subtitle files.
TikTok and Instagram generate auto-captions from audio on upload and allow in-app text editing. Neither platform exposes an upload slot for an external subtitle file. If the auto-generated text is inaccurate or you need a translated track, your options are: edit in-app (limited and time-consuming), or burn a corrected version into the video pixels before upload.
How do I burn captions into a video with ffmpeg?
The subtitles filter renders SRT, WebVTT, or any libass-supported format. The force_style option overrides the default libass appearance using ASS V4+ field names. Here is the command I use for a vertical 1080x1920 short-form video destined for TikTok or Reels:
ffmpeg -i input.mp4 \
-vf "subtitles=captions.srt:force_style='FontName=Arial,FontSize=28,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=2,Shadow=0,MarginV=160'" \
-c:v libx264 -crf 23 -preset slow \
-pix_fmt yuv420p \
-c:a copy \
burned_output.mp4
Key flags:
force_style='...': overrides the libass default style. ASS colour values use ABGR byte order: white is&H00FFFFFF, solid black outline is&H00000000. Alpha byte00= fully opaque.MarginV=160: pixels from the bottom edge of the 1080x1920 frame. I keep this at 160 on vertical video to stay clear of TikTok and Reels bottom UI overlays. Adjust if the platform changes its chrome height.-c:v libx264 -crf 23 -preset slow: H.264 encode at CRF 23 with the slow preset for better compression. Use-crf 18for higher-quality deliverables.-pix_fmt yuv420p: forces 4:2:0 chroma subsampling. Some ffmpeg builds produce yuv420p10 when libass renders; platforms re-encode that with a second chroma conversion, adding blur to the text.-c:a copy: the subtitle filter does not touch audio. Copy it through unchanged.
How do I add a soft caption track without re-encoding?
For MP4 output, the only accepted text subtitle codec is mov_text (3GPP Timed Text). Using -c:s srt or -c:s copy into an MP4 container causes an error or writes a track most players silently ignore. For YouTube, I produce the MP4 first, then upload the .srt separately - no re-encode at any step.
ffmpeg -i video.mp4 -i captions.srt \
-map 0 -map 1 \
-c:v copy -c:a copy \
-c:s mov_text \
-metadata:s:s:0 language=eng \
-metadata:s:s:0 title="English" \
-disposition:s:0 default \
soft_output.mp4
What each flag does:
-map 0 -map 1: include all streams from the video input, plus the first stream from the SRT input.-c:v copy -c:a copy: pass video and audio through byte-for-byte. No quality loss, almost no processing time.-c:s mov_text: convert the SRT to 3GPP Timed Text, the only text subtitle codec MP4 supports.-metadata:s:s:0 language=eng: ISO 639-2 language tag. Useviefor Vietnamese,frafor French.-disposition:s:0 default: pre-selects this track in players that auto-load a subtitle stream.
Verify the result: ffprobe -v error -select_streams s -show_entries stream=codec_name:stream_tags=language -of default=noprint_wrappers=1 soft_output.mp4. If codec_name is not mov_text, most players will skip the track silently.
Should I combine both methods on the same file?
I do this when a client needs both platform coverage and viewer control. The workflow: start from the same source video and SRT, produce a burned-in MP4 for TikTok and Reels, and produce a separate clean MP4 with a soft track for YouTube. Both outputs share the same timing and text: no translation or re-timing divergence between them.
The scenario where combining pays off most is a translated subtitle track. Burn the Vietnamese version into the TikTok copy (since TikTok cannot accept a sidecar file). Embed a Vietnamese soft track in the YouTube copy alongside an English track. One SRT per language, two delivery variants, no re-translation needed.
What you can do yourself vs where a specialist helps
Both commands above are fully self-service. Write the SRT, burn it for TikTok and Reels, upload the SRT to YouTube Studio. For single-language content with clean speech, that covers the full technical workflow.
The calculation shifts for translated subtitles. Vietnamese translated from English regularly overflows reading-speed limits because Vietnamese lines are longer than their English source. A machine-translated .srt timed to English cues often runs too fast to read comfortably. I translate in Subtitle Edit with the CPS (characters per second) warning live on screen, adjusting line breaks until every event stays inside the reading-speed limit before the file goes to ffmpeg.
For branded video series, multi-language delivery, or web video that must meet a style guide, professional timing and native-language QC earns its cost. My vertical subtitle service covers both the burn-in and the soft-track delivery path, from translation through ffmpeg export.
FAQ
Can I burn in captions without re-encoding the video?
No. The subtitles and ass filters run inside ffmpeg's video filter graph, which requires decoding and re-encoding the video stream. Using -c:v copy while a -vf filter is active causes an error. Audio is unaffected: -c:a copy always works alongside a subtitle filter.
Why do my burned-in captions look blurry after TikTok upload?
TikTok re-encodes every upload. If captions were rendered onto a scaled-down proxy before the final H.264 encode, the re-encode compounds the blur. Always burn onto the full 1080x1920 frame. Also include -pix_fmt yuv420p: some ffmpeg builds produce yuv420p10 when libass renders, and TikTok's pipeline converts that with a second chroma pass.
Can I upload Vietnamese subtitles to YouTube as a soft track?
Yes. Upload the Vietnamese .srt in YouTube Studio and select Vietnamese as the language. The viewer can choose it from the caption menu alongside any other tracks. Save the file as UTF-8 without BOM from Subtitle Edit: Vietnamese precomposed characters with diacritics are within UTF-8 and render correctly in YouTube's player.
Does mov_text preserve Vietnamese diacritics in an MP4?
Yes, as long as the source SRT is UTF-8 encoded. The mov_text codec stores text in UTF-8 inside the MP4 container. The common failure mode is a source file saved in Windows-1252: diacritics are garbled before ffmpeg processes the text. Check File > Character encoding in Subtitle Edit and re-save as UTF-8 without BOM before running the ffmpeg command.
What is the right CRF for burning captions into a social video?
For TikTok and Reels, I use -crf 23: it produces a clean file at a manageable size and the platforms re-encode on their end anyway. For a YouTube upload where the platform preserves more of the original quality, I prefer -crf 18 to keep the burned text sharp after the platform's processing. Both use -preset slow for better compression at the same quality level.
Official Sources
- FFmpeg documentation: subtitles filter and force_style option - authoritative reference for burn-in commands and libass style fields. Verified Oct 2026.
- FFmpeg codec documentation: mov_text subtitle codec - confirms mov_text as the required codec for MP4 soft subtitle tracks. Verified Oct 2026.
- YouTube Help: Supported subtitle and closed caption files - lists SRT, VTT, SBV, SCC and all accepted formats. Verified Oct 2026.
- TikTok Newsroom: Introducing auto captions - confirms auto-caption feature with in-app editing; no external subtitle file upload mentioned. Verified Oct 2026.
- Instagram Help: Manage closed captions for your reels - confirms speech-recognition auto-captions and in-app editing only. Verified Oct 2026.

Written by Dao Huy (Lucas), Vietnamese translator and localization specialist (English, Chinese and French into Vietnamese). See translation services →
