This is an old revision of the document!


DVD Subtitles

WARNING: ffmpeg might or might not automatically mux the closed captioning stream into the output file, regardless of whether asked to or not, and it will not show up in the encoding map. I haven't found a way to explicitly ignore it, using -sn doesn't catch it. The output container may make a difference as well.

ffmpeg -i dvd_copy.mpg dvd_copy.mp4
Output #0, mp4, to 'dvd_copy.mp4':
  Metadata:
    encoder         : Lavf58.20.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 720x480 [SAR 8:9 DAR 4:3], q=-1--1, 29.97 fps, 30k tbn, 29.97 tbc
    Metadata:
      encoder         : Lavc58.35.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s
    Metadata:
      encoder         : Lavc58.35.100 aac

Running mediainfo dvd_copy.mp4:

Text
ID                                       : 1-CC1
Format                                   : EIA-608
Muxing mode                              : SCTE 128 / DTVCC Transport
Muxing mode, more info                   : Muxed in Video #1
Duration                                 : 30 s 30 ms
Bit rate mode                            : Constant
Stream size                              : 0.00 Byte (0%)
Encoded stream size                      : 0.00 Byte (0%)
CaptionServiceName                       : CC1

Same source, but in a Matroska container does not on this sample:

ffmpeg -i dvd_copy.mpg dvd_copy.mkv
Output #0, matroska, to 'dvd_copy.mkv':
  Metadata:
    encoder         : Lavf58.20.100
    Stream #0:0: Video: h264 (libx264) (H264 / 0x34363248), yuv420p, 720x480 [SAR 8:9 DAR 4:3], q=-1--1, 29.97 fps, 1k tbn, 29.97 tbc
    Metadata:
      encoder         : Lavc58.35.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1: Audio: vorbis (libvorbis) (oV[0][0] / 0x566F), 48000 Hz, stereo, fltp
    Metadata:
      encoder         : Lavc58.35.100 libvorbis

Running mediainfo dvd_copy.mkv does not have a cc stream in it.

Detect VobSub

The MPG will need to be probed deeper than normal to check for VobSub streams because they only are detected once they show up in the video.

An example:

ffprobe -probesize 67108864 -analyzeduration 60000000 dvd_video.mpg
Input #0, mpeg, from '1.665.2138.17690.TNTGO.mpg':
  Duration: 00:11:09.02, start: 0.045500, bitrate: 5708 kb/s
    Stream #0:0[0x1bf]: Data: dvd_nav_packet
    Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, progressive), 720x480 [SAR 32:27 DAR 16:9], 29.92 fps, 59.94 tbr, 90k tbn, 59.94 tbc
    Stream #0:2[0x82]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:3[0x81]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:4[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
    Stream #0:5[0x21]: Subtitle: dvd_subtitle
    Stream #0:6[0x20]: Subtitle: dvd_subtitle
    Stream #0:7[0x23]: Subtitle: dvd_subtitle
    Stream #0:8[0x22]: Subtitle: dvd_subtitle

For a DVD directly:

dvd_copy -o - | ffprobe -probesize 67108864 -analyzeduration 60000000 -

Detect CC

For DVDs, closed captioning streams are embedded in the video stream.

The fastest way is to see if it has closed captioning is using ffprobe and looking for Closed Captions in the output:

ffprobe dvd_copy.mpg
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, top first), 720x480 [SAR 32:27 DAR 16:9], Closed Captions, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc

Use ffprobe's INI style output to look for it as well:

ffprobe -v 0 -show_streams -show_entries stream=start_pts -select_streams s -f lavfi -i movie=dvd_copy.mpg[out+subcc]

See if a DVD has closed captioning:

dvd_copy -o - | ffprobe -v 0 -show_streams -show_entries stream=start_pts -select_streams s -f lavfi -i movie=pipe\\\\:0[out+subcc]

When splitting the streams using lavfi device, ffmpeg will “create” a subtitle stream, even if one is not present. To make sure one exists or not, a closer look at the stream itself is actually needed.

This one has a starting presentation timestamp (PTS) that's a positive value, so it's safe to say that one exists.

[STREAM]
start_pts=25257
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
[/STREAM]

Here's one without it present:

[STREAM]
start_pts=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
[/STREAM]

Extract CC

Use ffmpeg to extract the closed captioning stream from a DVD using dvd_copy:

dvd_copy -o - | ffmpeg -f lavfi -i movie=pipe\\\\:0[out+subcc] -map 0:s subtitles.srt

Extract CC subtitles from an MPG:

dvd_copy -o dvd_copy.mpg
ffmpeg -f lavfi -i movie=dvd_copy.mpg[out+subcc] -map 0:s subtitles.srt

Since the closed captioning is embedded in the video stream, you can re-encode that at the same time. It won't see any other streams though (audio, vobsub).

ffmpeg -f lavfi -i movie=dvd_copy.mpg[out+subcc] -map 0:v -map 0:s video.mkv

Encode with existing Closed Captioning

Since ffmpeg can input from two sources at once, you can input the same source twice, encode the audio and video from one, split the closed captioning data from the other, and mux them into one file all at once.

This will work on a file but not with piped input

ffmpeg -i dvd_copy.mpg -f lavfi -i movie=dvd_copy.mpg[out+subcc] -map 0:v -map 0:a -map 1:s? dvd_copy.mkv

Default Subtitles

If any subtitles are copied from the DVD, ffmpeg will mark them all as enabled by default. This means that when playing it back with mpv or mplayer, it will display the subtitles automatically.

ffmpeg has the ability to toggle some off and some on, but not the ability to mark all of them as not default.

An example …

Encode a video file using defaults for audio and video codec, and copying the first subtitle stream:

dvd_copy -o - | ffmpeg -probesize 67108864 -analyzeduration 60000000 -i - -map 0:v -map i:0x80 -map i:0x20 -scodec copy dvd_copy.mkv
mediainfo dvd_copy.mkv

Here, Default is set to yes.

...
Text
ID                                       : 3
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 26 s 660 ms
Default                                  : Yes
Forced                                   : No

If you were to copy multiple VobSub streams, it will set them all to default:

Switching to using an MPG file in the example here for simplicity.

ffmpeg -probesize 67108864 -analyzeduration 60000000 -i dvd_copy.mpg -map 0:v -map i:0x80 -map i:0x20 -map i:0x21 -scodec copy dvd_copy.mkv
mediainfo dvd_copy.mkv

Both are set to default here:

Text #1
ID                                       : 3
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 26 s 660 ms
Default                                  : Yes
Forced                                   : No

Text #2
ID                                       : 4
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 26 s 660 ms
Default                                  : Yes
Forced                                   : No

ffmpeg *does* let you set the disposition off for one or more, but not all.

Here's an example with three subtitles illustrating the point, where the first two will be disabled as default, and switching the third to enabled:

ffmpeg -probesize 67108864 -analyzeduration 60000000 -i dvd_copy.mpg -map 0:v -map i:0x80 -map i:0x20 -map i:0x21 -map i:0x22 -scodec copy -disposition:s:0 0 -disposition:s:1 0 -disposition:s:2 default dvd_copy.mkv
mediainfo dvd_copy.mkv
Text #1
ID                                       : 3
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 26 s 660 ms
Default                                  : No
Forced                                   : No

Text #2
ID                                       : 4
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 26 s 660 ms
Default                                  : No
Forced                                   : No

Text #3
ID                                       : 5
Format                                   : VobSub
Codec ID                                 : S_VOBSUB
Codec ID/Info                            : Picture based subtitle format used on DVDs
Duration                                 : 27 s 661 ms
Default                                  : Yes
Forced                                   : No

If you want to disable default for all subtitle tracks, use mkvpropedit (part of mkvtoolnix package), editing them individually:

mkvpropedit dvd_copy.mkv --edit track:s1 --set flag-default=0 --edit track:s2 --set flag-default=0 --edit track:s3 --set flag-default=0

Navigation