Add & Extract subtitles from container with ffmpeg

Subtitles can be external (as .srt, .ass files) and internal (inside container .mkv, .webm). We can use ffmpeg utility to inserting or extracting them. This article is about using ffmpeg to extract and add subtitles from/into container. Before we start, i wanna note that .mp4 and .avi containers don’t always can keep subtitles inside. This may require additional specifications and standards. More information about the formats can be found on this page(Comparison of video container formats) in Wikipedia.

Extract subtitles from container

First, we need to check streams for their indexes in our video. Just run ffmpeg with -i “video file” as an argument:

ffmpeg -i video.mkv
...
Stream #0:0: Video: h264 (High), yuv420p(progressive), 960x544, SAR 4:3 DAR 40:17, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
Stream #0:1(eng): Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s (default)
Stream #0:2(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:3(ger): Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:4(eng): Subtitle: subrip (default)
Stream #0:5(ger): Subtitle: subrip

Now, we see two subtitle streams called #0:4 and #0:5. They are in .srt (subrip) format. We can use their indexes (0:4, 0:5) to extract them. Let’s extract first subtitle track. It is called Stream #0:4:

ffmpeg -i video.mkv -map 0:4 -vn -an subtitles.srt
...
Stream mapping:
  Stream #0:4 ( <- from container) -> #0:0 (subrip (srt) -> subrip (srt) ( <- convert as .srt in a separate file)

In this example we use -map option. It defines stream index we want to select.

-vn means “exclude video streams to copy” and -an option means “exclude audio streams to copy”.

In such way we extract only subtitle stream. We can even set output format to .ass so ffmpeg will convert .srt to .ass.

Stream mapping:
  Stream #0:4 ( <- from container) -> #0:0 (subrip (srt) -> ass (ssa)) ( <- convert .srt to .ass in a separate file)

The better way if we want to save subtitle format as .srt is to add -c:s copy option to our command. Then subtitle stream will be just copied to another file without re-encoding. It’s fastest way to extract subtitles.

ffmpeg -i video.mkv -map 0:4 -vn -an -c:s copy subtitles.srt
...
Stream mapping:
  Stream #0:4 ( <- from container) -> #0:0 (copy) ( <- copy to separate file)

Add subtitles to container

Let’s assume that our file has only three streams:

ffmpeg -i video.mkv
...
Stream #0:0: Video: h264 (High), yuv420p(progressive), 960x544, SAR 4:3 DAR 40:17, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
Stream #0:1(eng): Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s (default)
Stream #0:2(ger): Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s (default)

Here is one video stream (Stream #0:0) and two audio streams (Stream #0:1 and Stream #0:2).

Now, we want to add subtitle file in this container. Then we need to combine all these streams with subtitle stream. We need to tell ffmpeg what streams we want to save. As in “Extract subtitles” paragraph we need to use -map option to select these streams.

ffmpeg -i video.mkv -i subtitles.srt -map 0:0 -map 0:1 -map 0:2 -map 1:0 -c copy output.mkv
...
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #0:2 -> #0:2 (copy)
  Stream #1:0 ( <- subtitles.srt ) -> #0:3 (copy) ( <- inside container as #0:3 stream)

In the example by -map option we selected 0:0 (video stream) and 0:1, 0:2 (audio streams) in the container.

We select subtitle stream (subtitles.srt) by -map 1:0 option (1 means second file which is passed to ffmpeg with -i option and 0 means first stream).

-c copy means to save all streams which we selected with -map option.

In such way we created a new container with subtitle stream included.

Please write comments if something is not clear!

Leave a Reply

Your email address will not be published.