-
Notifications
You must be signed in to change notification settings - Fork 2
Tips: To keep subtitle streams when converting video
(NB, edited from https://askubuntu.com/a/214351/843820)
For all formats that support streaming text format subtitles:
Basic example using default stream selection behavior while stream copying the audio:
ffmpeg -i input.mkv -c copy -c:s copy output.mp4
Example to stream copy all of the video and audio streams, convert the all text based subtitle input streams (SRT, ASS, VTT, etc) to the streaming text format, and set the language for the first two subtitle streams.
ffmpeg -i input.mkv -map 0 -c copy -c:s copy -metadata:s:s:0 language=eng -metadata:s:s:1 language=ipk output.mp4
Same as above but re-encode the video and audio to formats compatible with the MP4 container (H.264 video:
ffmpeg -i input.mkv -map 0 -c:v libx264 -c:a aac -c:s mov_text -metadata:s:s:0 language=eng -metadata:s:s:1 language=ipk output.mp4
Same as above but use the -map
option to choose the first video stream, second audio stream, and third subtitle stream:
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:1 -map 0:s:2 -c:v libx264 -c:a aac -c:s mov_text -metadata:s:s:0 language=eng output.mp4
Ref:
Use the subtitles filter to "burn-in" text based subtitle formats (SRT, ASS, VTT, etc). Note that this requires re-encoding, so it will by much slower than using softsubs.
To disable subtitle output/recording, use -sn
.
Starting with Version 1.3.2 (builds later than 2019-01-06), ffcvt
supports subtitle streams copy by default when encoding to the default WebM(VP9) format. Here is an example:
$ ffmpeg -i Sample-with-Subtitle.mkv
Input #0, matroska,webm, from 'Sample-with-Subtitle.mkv':
Metadata:
encoder : libebml v1.3.6 + libmatroska v1.4.9
creation_time : 2018-07-17 15:23:05
Duration: 00:52:55.17, start: 0.000000, bitrate: 9105 kb/s
Stream #0:0: Video: hevc (Main), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)
Metadata:
BPS-eng : 8879131
DURATION-eng : 00:52:55.172000000
NUMBER_OF_FRAMES-eng: 76128
NUMBER_OF_BYTES-eng: 3524096033
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(eng): Audio: eac3, 48000 Hz, stereo, fltp, 224 kb/s (default)
Metadata:
BPS-eng : 224000
DURATION-eng : 00:52:55.136000000
NUMBER_OF_FRAMES-eng: 99223
NUMBER_OF_BYTES-eng: 88903808
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:2(eng): Subtitle: subrip
Metadata:
BPS-eng : 91
DURATION-eng : 00:52:00.418000000
NUMBER_OF_FRAMES-eng: 966
NUMBER_OF_BYTES-eng: 35651
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
So the Sample-with-Subtitle.mkv
has a (subrip) text subtitle stream.
Now try to transcode to the default WebM(VP9) format using ffcvt
:
$ ffcvt -f Sample-with-Subtitle.mkv -force -- -ss 00:02:50 -t 0:3:00
== Transcoding: Sample-with-Subtitle.mkv
] -i Sample-with-Subtitle.mkv -c:a libopus -b:a 64k -c:s copy -c:v libvpx-vp9 -b:v 0 -crf 37 -y -ss 00:02:50 -t 0:3:00 Sample-with-Subtitle_.mkv
. . .
$ ffmpeg -i Sample-with-Subtitle_.mkv
Input #0, matroska,webm, from 'Sample-with-Subtitle_.mkv':
Metadata:
ENCODER : Lavf56.36.100
Duration: N/A, start: 0.007000, bitrate: N/A
Stream #0:0: Video: vp9 (Profile 0), yuv420p(tv), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 1k tbc (default)
Metadata:
BPS-eng : 8879131
DURATION-eng : 00:52:55.172000000
NUMBER_OF_FRAMES-eng: 76128
NUMBER_OF_BYTES-eng: 3524096033
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
ENCODER : Lavc56.41.100 libvpx-vp9
Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
Metadata:
LANGUAGE : eng
BPS-eng : 224000
DURATION-eng : 00:52:55.136000000
NUMBER_OF_FRAMES-eng: 99223
NUMBER_OF_BYTES-eng: 88903808
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
ENCODER : Lavc56.41.100 libopus
Stream #0:2(eng): Subtitle: subrip
Metadata:
LANGUAGE : eng
BPS-eng : 91
DURATION-eng : 00:52:00.418000000
NUMBER_OF_FRAMES-eng: 966
NUMBER_OF_BYTES-eng: 35651
_STATISTICS_WRITING_APP-eng: mkvmerge v25.0.0 ('Prog Noir') 64-bit
_STATISTICS_WRITING_DATE_UTC-eng: 2018-07-17 15:23:05
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Note that
-
ffcvt
supports subtitle streams copy by blindly inserting-c:s copy
into theffmpeg
command line, to do the subtitle streams copy. It will copy the subtitle meta-data as well (see above result). If the original subtitle meta-data (e.g., language setting) was wrong somehow, you can use-metadata:s:s:0 language=eng
to override it. - In order to support subtitle streams copy, the default format of the WebM(VP9) video extension has to be changed. If keep using the
.webm
extension,ffmpeg
will complain about the following then abort:
$ ffmpeg -i Sample-with-Subtitle.mkv -c:a libopus -b:a 64k -c:v libvpx-vp9 -b:v 0 -crf 37 -c:s copy -ss 00:02:50 -t 0:3:00 Sample-with-Subtitle_.webm
[libvpx-vp9 @ 0x4066320] v1.4.0-823-g4110a27
[webm @ 0x40ae020] Codec for stream 2 does not use global headers but container format requires global headers
[webm @ 0x40ae020] Only VP8 or VP9 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.
Output #0, webm, to 'Sample-with-Subtitle_.webm':
. . .
Stream mapping:
Stream #0:0 -> #0:0 (hevc (native) -> vp9 (libvpx-vp9))
Stream #0:1 -> #0:1 (eac3 (native) -> opus (libopus))
Stream #0:2 -> #0:2 (copy)
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
- For videos that don't have subtitle streams at all,
ffcvt
(ffmpeg
) will carry on without erroring out:
$ ffcvt -f tears_of_steel_720p.mov -force -- -t 0:0:30
== Transcoding: tears_of_steel_720p.mov
] -i tears_of_steel_720p.mov -c:a libopus -b:a 64k -c:s copy -c:v libvpx-vp9 -b:v 0 -crf 37 -y -t 0:0:30 tears_of_steel_720p_.mkv
Done.
Org Size: 363455 KB
New Size: 2564 KB
Saved: 99% with 360891 KB
Time: 2m43.937355268s at 2019-01-06 21:15:26
. . .
$ ffmpeg -i tears_of_steel_720p_.mkv
Input #0, matroska,webm, from 'tears_of_steel_720p_.mkv':
Metadata:
COMPATIBLE_BRANDS: qt
MAJOR_BRAND : qt
MINOR_VERSION : 512
ENCODER : Lavf56.36.100
Duration: 00:00:30.01, start: 0.007000, bitrate: 700 kb/s
Stream #0:0(eng): Video: vp9 (Profile 0), yuv420p(tv), 1280x534, SAR 1:1 DAR 640:267, 24 fps, 24 tbr, 1k tbn, 1k tbc (default)
Metadata:
LANGUAGE : eng
HANDLER_NAME : DataHandler
ENCODER : Lavc56.41.100 libvpx-vp9
Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
Metadata:
LANGUAGE : eng
HANDLER_NAME : DataHandler
ENCODER : Lavc56.41.100 libopus