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
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:
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:
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:
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
- Burn Subtitles Into a Video
- Hardcode Subtitles Into a Video
- Embed Subtitles in a Video: Track or Burned In
- Open Captions: Always-On Captions for Any Screen
- Add Subtitles to a Video Permanently
- Hide Hardcoded Subtitles and Put New Ones on Top
- Burn Subtitles Without Losing Quality
- Burn Translated Subtitles Into Your Video
- Burn Subtitles With VLC, and What to Do When It Fails
Subtitle tools
- Add Subtitles to a Video
- Video Caption Generator With Styled, Burned-In Captions
- Online Subtitle Editor
- SRT to MP4: Put Your Subtitle File Into the Video
- VTT to MP4: Burn WebVTT Captions Into a Video
- Add Captions to a TikTok Video
- Add Subtitles to Instagram Reels
- Add Subtitles to a YouTube Video
- Add Hindi Subtitles to a Video
- All subtitle tools
- AI subtitle generator (SRT and VTT files)
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.