Subtitle formats overview
Subtitle formats fall into three families: plain or lightly styled text (SRT, WebVTT), fully styled script text (ASS/SSA), and images (PGS from Blu-ray, VobSub from DVD). Which one you want depends on where the video will be played, and converting between them usually loses something.
Choosing a format
Section titled “Choosing a format”| Format | What it is | Use it for | Carried in |
|---|---|---|---|
| SRT | Timed text with <i>, <b>, <u>, <font> tags | Anything that just needs dialogue; the lowest common denominator | .srt, MKV (S_TEXT/UTF8), MP4 as mov_text |
| ASS/SSA | Styled script: fonts, colours, positioning, animation | Anime fansubs, typeset signs and songs, karaoke | .ass, MKV (S_TEXT/ASS) |
| WebVTT | SRT-like text with cue positioning and CSS styling | Web video (<track>), HLS | .vtt, WebM, MKV |
PGS (.sup) | Blu-ray bitmaps | Keeping Blu-ray subtitles exactly as authored | MKV (S_HDMV/PGS), M2TS |
VobSub (.idx + .sub) | DVD bitmaps | Keeping DVD subtitles | MKV (S_VOBSUB), VOB |
| TTML / IMSC | XML timed text | Broadcast and streaming-service deliverables | Separate files, DASH/CMAF segments |
| CEA-608/708, DVB | Broadcast caption systems | TV broadcast and recordings | Embedded in video or MPEG-TS |
Text formats stay small, searchable, and resizable by the player. Image formats look exactly like the original but cannot be edited, restyled, or searched without OCR.
Where each container can put them
Section titled “Where each container can put them”| Container | Text subtitles | Image subtitles |
|---|---|---|
| Matroska | SRT, ASS/SSA, WebVTT | PGS, VobSub |
| MP4 | mov_text only (SRT-level styling) | Not portable |
| WebM | WebVTT | None |
If a player or device cannot show your subtitle format, the fallback is burning it in (see below).
Converting between formats
Section titled “Converting between formats”ffmpeg -i subs.srt subs.assffmpeg -i subs.srt subs.vttffmpeg -i subs.vtt subs.srtffmpeg -i subs.ass subs.srtffmpeg -i input.mkv -map 0:s:0 subs.srtGoing from a richer format to a poorer one loses information, and FFmpeg does not clean up after itself. ASS to SRT turns each style into <font size="…" color="…"> wrappers (with the ASS script’s sizes, meaningless to an SRT player), drops \pos and leaves tags like {\an8} in the text; ASS to WebVTT keeps italics and bold but drops styles and positioning. Always check the result, and keep the original. Converting image subtitles to text needs OCR (Subtitle Edit, for example); FFmpeg cannot do it.
Muxing subtitles
Section titled “Muxing subtitles”ffmpeg -i video.mkv -i subs.srt -map 0 -map 1 -c copy -metadata:s:s:0 language=eng output.mkvmkvmerge -o output.mkv video.mkv --language 0:eng --track-name 0:"English" subs.srtffmpeg -i video.mkv -i subs.srt -map 0 -map 1 -c copy -c:s mov_text output.mp4The --language 0:eng option applies to the file that follows it (here subs.srt, track 0). To keep fonts for ASS subtitles, attach them to the MKV; see SubStation Alpha.
Burning subtitles into the video
Section titled “Burning subtitles into the video”Hard-coding the subtitles re-encodes the video, so it is a last resort for devices that cannot render soft subtitles:
ffmpeg -i input.mkv -vf subtitles=input.mkv -c:v libx264 -crf 18 -c:a copy output.mp4ffmpeg -i input.mkv -vf "subtitles=subs.srt:force_style='FontSize=24,Outline=2'" -c:v libx264 -crf 18 -c:a copy output.mp4ffmpeg -i input.mkv -vf ass=subs.ass -c:v libx264 -crf 18 -c:a copy output.mp4subtitles takes any text format FFmpeg can read and picks the first subtitle stream of the file (:si=1 for the second); when the file is an MKV it also loads the attached fonts. ass only reads .ass files. Both need an FFmpeg built with libass.
Image subtitles (PGS, VobSub) are burned in with the overlay filter instead:
ffmpeg -i input.mkv -filter_complex "[0:v][0:s:0]overlay=shortest=1" -c:v libx264 -crf 18 -c:a copy output.mp4shortest=1 ends the output with the video. Without it, the last subtitle event (which has no end time) can stretch the output far past the end of the video, and an MP4 mux fails. If you are also downscaling, put the scale after overlay so the subtitles shrink with the picture.
SRT has no style of its own, so FFmpeg converts it with a default ASS style. Override it with force_style using ASS style names (FontName, FontSize, Outline, MarginV). FontSize is measured against a 288-line script that libass scales to the video, so it is not a pixel size: 24 is a font size of 1/12 of the picture height at any resolution.
Encoding problems
Section titled “Encoding problems”Old SRT files are often in a legacy codepage rather than UTF-8, which shows up as garbled accents. Tell FFmpeg what the file is with -sub_charenc CP1252 -i subs.srt (or charenc= on the filter), or convert with iconv -f CP1252 -t UTF-8.