FFmpeg

Burn Subtitles With FFmpeg, or Skip the Terminal

FFmpeg burns subtitles with its subtitles filter: one command decodes the video, draws the SRT or ASS text onto each frame through the libass library, and encodes a new file. Below is a command that works, the options people usually add, and the mistakes behind most failed first attempts. If you'd rather see the subtitles before committing to a render, the browser editor on this page does the same job with a live preview.

Subtitle editor

Load a video, get subtitles from AI, an SRT/VTT file or your own typing, style them, and download an MP4 with the subtitles in the picture.

MP4, MOV, M4V, WebM or MKV · free to edit and render · no watermark · the video stays on your device

What you need before the first command

  • An FFmpeg build that includes libass. Most full builds from package managers and the common download sites do. Run ffmpeg -filters and look for a line mentioning subtitles; if it is missing, the build can't burn text.
  • A subtitle file. The subtitles filter reads SRT, ASS/SSA, VTT and any other format FFmpeg can decode, converting it to ASS internally. It can also read a subtitle stream inside an MKV.
  • Fonts. libass looks up fonts through the system (fontconfig on Linux and macOS builds). Anything not installed has to be pointed to with the fontsdir option.
  • A terminal opened in the folder that holds the video and the subtitle file. Short, plain filenames there will spare you the escaping problems described further down.

A command that works

Burn an SRT into an MP4

ffmpeg -i talk.mp4 -vf "subtitles=talk.srt" -c:v libx264 -crf 18 -preset slow -c:a copy talk-subtitled.mp4

Read left to right, the pieces do this:

-i talk.mp4
The input video.
-vf "subtitles=talk.srt"
The video filter that renders the subtitle file onto each frame.
-c:v libx264 -crf 18
Encode with x264 at constant quality. Lower numbers mean higher quality and bigger files; the default is 23, and 18 is a popular choice when the copy should look very close to the source.
-preset slow
Spend more time encoding for a smaller file at the same quality. Use medium or fast if time matters more than size.
-c:a copy
Leave the audio exactly as it is.

Adding -movflags +faststart moves the index to the front of the MP4 so it starts playing sooner when streamed from a website.

Styling SRT text

An ASS file carries its own styles, and the filter honours them. An SRT has no styling, so FFmpeg applies a default look unless you override it with force_style, which takes ASS style fields:

Bigger text with an outline, raised off the bottom

ffmpeg -i talk.mp4 -vf "subtitles=talk.srt:force_style='FontName=Arial,FontSize=20,Outline=2,MarginV=30'" -c:v libx264 -crf 18 -c:a copy talk-subtitled.mp4

The single quotes protect the commas inside force_style from the filter parser, and the double quotes protect the whole filter from the shell. A few fields behave unexpectedly:

  • FontSize is measured against a small virtual canvas (288 units tall by default for SRT input), not your video's pixel height, so a value around 18 to 24 is already large. Test on a short clip.
  • Colours use the ASS format with the channels in blue, green, red order, so PrimaryColour=&H0000FFFF is yellow, not cyan.
  • Alignment follows a numeric-keypad layout: 2 is bottom centre, 8 is top centre.
  • BorderStyle=3 replaces the outline with an opaque box behind each line.

Because you only see the style after a render, it pays to encode the first 20 seconds while experimenting; add -t 20 before the output name.

Errors that stop first attempts

  • "No such filter: 'subtitles'". The build lacks libass. Install a full build rather than a minimal one.
  • Asking for -c copy or -c:v copy. You can't filter a stream you are copying; the video has to be encoded for text to be drawn into it.
  • Paths. Inside a filter, colons, commas, square brackets and apostrophes have special meanings. A Windows path with a drive letter breaks the filter for exactly this reason. Running FFmpeg from the folder that holds the subtitle file, with a simple filename, avoids the escaping entirely.
  • Garbled accents or symbols. The SRT is probably not UTF-8. Add :charenc=CP1252 (or the right code page) after the filename, or re-save the file as UTF-8. Subtitles showing strange characters covers the cause.
  • Empty boxes instead of letters in Hindi, Arabic, Chinese and other non-Latin scripts. The chosen font lacks those glyphs. Name an installed font that covers the script in force_style, or supply one with fontsdir.
  • Audio refuses to copy into MP4. Some camera formats store audio MP4 doesn't accept; replace -c:a copy with -c:a aac.
  • Washed-out colours from HDR or 10-bit footage. Players expect 8-bit SDR from most MP4s. Tone mapping needs extra filters (zscale with tonemap), and -pix_fmt yuv420p keeps the output broadly playable.
  • Subtitles in an MKV rather than a separate file. Point the filter at the MKV itself and pick the stream: subtitles=film.mkv:si=0.

Many files at once

This is where FFmpeg is hard to beat. In a Bash or Zsh shell, a loop burns every MP4 in a folder using an SRT with the same base name:

Batch burn in Bash or Zsh

for f in *.mp4; do ffmpeg -i "$f" -vf "subtitles=$(basename "$f" .mp4).srt" -c:v libx264 -crf 18 -c:a copy "subtitled-$f"; done

Filenames with spaces or apostrophes will still trip the filter parser, so rename the files first. PowerShell and the Windows command prompt quote differently; translate the loop rather than pasting it.

If you didn't actually want them burned in

Burning is permanent. If viewers should be able to switch the subtitles off, mux them as a track instead, which copies the video without re-encoding:

Soft subtitle track in an MP4

ffmpeg -i talk.mp4 -i talk.srt -map 0 -map 1 -c copy -c:s mov_text talk-soft.mp4

Many players and most social apps ignore soft tracks, which is why burning exists at all. Embedding subtitles in a video untangles the two meanings of "embed", and MKVToolNix is a graphical option for MKV files.

FFmpeg beside the browser editor

The editor on this page reaches the same result through a different route: open the video, import an SRT or VTT (or type the lines, or have AI write them), style with presets and a live preview, then render an MP4 in the browser. Neither route is better across the board; they suit different jobs.

Setup
FFmpeg: install a build with libass and work in a terminal. Editor: open the page in a recent Chrome, Edge, Safari or Firefox on a computer.
Subtitle input
FFmpeg: SRT, ASS/SSA, VTT and tracks inside MKV files. Editor: SRT or VTT import, typing, or AI subtitles; ASS and MKV tracks are not read.
Styling
FFmpeg: ASS fields typed as text, checked by rendering. Editor: eight presets, 19 fonts, boxes and a safe-area guide, all visible before you render.
Timing fixes
FFmpeg: edit the SRT elsewhere first. Editor: drag lines, split, merge and shift every line at once.
Encoder control
FFmpeg: every codec, CRF, preset, pixel format and hardware encoder. Editor: chosen for you, with a generous bitrate and the source's resolution and frame rate.
Automation
FFmpeg: scripts, batch loops, servers. Editor: one video at a time, by hand.

The editor renders with the browser's own video encoder, not with FFmpeg. If the reason you opened a terminal was quality, burning without losing quality explains what any burn can and can't preserve. If you have no subtitle file yet, the AI subtitle generator produces an SRT you can feed to either route, and VLC's converter is a third option for people who already have it installed.

About the subtitle editor on this page

Opens
MP4, MOV, M4V, WebM, MKV videos your browser can decode
Subtitles from
AI (from the speech, optionally translated into one of 21 languages), an SRT or VTT file, or typing them in
You download
An MP4 with the subtitles drawn into the picture at the original resolution and frame rate, plus SRT and VTT files
Cost
Editing, styling, rendering and SRT/VTT export are free, with no account and no watermark. AI subtitles cost 1 credit per minute (5-credit minimum per video); signing in with Google gives 100 free credits and accounts get 10 free credits a day
Privacy
The video never leaves your device and is rendered in your browser. Only for AI subtitles is the audio sent, over HTTPS, and it is deleted within 30 minutes of delivery
Rendering needs
Chrome or Edge 94+, Safari 16.4+, or Firefox 130+ on a computer. Editing and SRT/VTT export work in any current browser

More: burn, embed and hardcode

Subtitle tools

Frequently asked questions

Why does FFmpeg say there is no such filter called subtitles?

Your FFmpeg build was compiled without libass, the library that renders subtitle text. Install a full build from your package manager or a common download site and run the command again.

Can FFmpeg burn subtitles without re-encoding the video?

No. Drawing text into frames requires decoding and encoding them. If you want to avoid a re-encode, mux the subtitles as a soft track with -c copy and -c:s mov_text instead.

How do I make FFmpeg's burned subtitles larger?

Add force_style with a FontSize value to the subtitles filter. The size is relative to a small virtual canvas rather than your video's pixels, so small numbers already look big; test on a short clip.

Can FFmpeg keep the styling of an ASS subtitle file?

Yes. The subtitles filter, or the ass filter, renders ASS styles as written. The browser editor on this page doesn't import ASS, so use FFmpeg when that styling matters.

Does the editor on this page run FFmpeg in the browser?

No. It renders with the browser's built-in video encoder (WebCodecs) on your computer, and the video is never uploaded for rendering.