Skip to content

Instantly share code, notes, and snippets.

@spirillen
Last active January 14, 2024 04:50
Show Gist options
  • Save spirillen/af307651c4261383a6d651038a82565d to your computer and use it in GitHub Desktop.
Save spirillen/af307651c4261383a6d651038a82565d to your computer and use it in GitHub Desktop.
Use FFmpeg to add subtitles to video

Use FFmpeg to add subtitles to video

MP4:

ffmpeg -i input.mp4 -f srt -i input.srt -map 0:0 -map 0:1 -map 1:0 -c:v copy \
    -c:a copy -c:s mov_text output.mp4

MKV:

ffmpeg -i input.mp4 -f srt -i input.srt -map 0:0 -map 0:1 -map 1:0 -c:v copy \
    -c:a copy -c:s srt output.mkv

To understand the -map option you'll first need to examine your source file by running the video trough ffprobe or ffmpeg

ffmprobe -i video.mp4

Then you'll see some lines named "Stream", each stream represent a video, sound and/or subtitle. Streams starting with 0: are video or sound tracks (streams) and streams starting with a number higher than 0 is subtitle (overlays)

To add several subtitles to the same video requires you to add a -c:s mov_text or -c:s srt for each subtitle submitted

If you like to add a title to each soundtrack or subtitle you can use the

-metadata:s: and -metadata:s:s

Example

For English soundtracks you'll use English for language

-metadata:s:0 language=English

For subtitle you have to use the extra s

-metadata:s:s:1 language=English \
-metadata:s:s:2 language=Dansk

Source: https://www.reck.dk/use-ffmpeg-to-add-subtitles-to-video/

@wonbinbk
Copy link

Streams starting with 0: are video or sound tracks (streams) and streams starting with a number higher than 0 is subtitle (overlays)

Is this correct? If so, does the order of inputs specified by the "-i" switch matter?

@spirillen
Copy link
Author

This is all correct

and yes the order of the input sources matters, meaning it is first the video and audio streams, then the subtitle streams

@Neurognostic
Copy link

Thanks for sharing the example!

This is what I got to work with several languages:

ffmpeg -i ./"$name".mp4 \
	-f srt -i ./"$name".en.srt \
	-f srt -i ./"$name".es.srt \
	-f srt -i ./"$name".fr.srt \
	-f srt -i ./"$name".sv.srt \
	-f srt -i ./"$name".fi.srt \
	-f srt -i ./"$name".cr.srt \
	-f srt -i ./"$name".ar.srt \
	-map 0:0 -map 0:1 -map 1:0 \
	-map 2:0 -map 3:0 -map 4:0 \
	-map 5:0 -map 6:0 -map 7:0 \
	-c:v copy -c:a copy -c:s mov_text \
	-metadata:s:s:0 language=eng \
	-metadata:s:s:1 language=spa \
	-metadata:s:s:2 language=fra \
	-metadata:s:s:3 language=swe \
	-metadata:s:s:4 language=fin \
	-metadata:s:s:5 language=cre \
	-metadata:s:s:6 language=ara \
	-metadata title="$title" \
	"$title".subs.mp4

I used the ISO 639-2 three character language code for the subtitle language metadata which seems to be recognized by both mediainfo and vlc as their locale names.

I had a problem with one of my subtitle files being encoded with WINDOWS-1252 rather than the expected UTF-8. It would produce an error like this when encoding:

[srt @ 0x559e9f111dc0] Invalid UTF-8 in decoded subtitles text; maybe missing -sub_charenc option
Error while decoding stream #0:8: Invalid data found when processing input

To fix it you can detect the encoding with chardet or uchardet and then use iconv to convert to the expected UTF-8:

iconv --verbose -f WINDOWS-1252 -t UTF-8 -o ./"$name".fixed.en.srt ./"$name".en.srt

@salivity
Copy link

I created an online tool which used this method to add subtitles to a video container, https://davidclews.com/article/280.html you can see the code in the browsers console

@spirillen
Copy link
Author

I created an online tool which used this method to add subtitles to a video container, https://davidclews.com/article/280.html you can see the code in the browsers console

You should mention the rather small limitation, but good initiative.

This tool has a max filesize limit of 2.00 GiB or 2.15 GB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment