I have multiple audio tracks and subtitles to extract in a single .mkv file. I'm new to ffmpeg
commands, this is what I've tried (audio):
ffmpeg -i VIDEO.mkv -vn -acodec copy AUDIO.aac
It just extract 1 audio. What I want is tell ffmpeg
to extract every single audio files and subtitle files to a destination, and keep the original name of each files and extensions. (Because I don't know which extension does the audio files are, sometimes maybe .flac or .aac).
I'm not sure about the solutions I'd found online, because it's quite complicated, and I need explanations to know how it's works, so that I can manipulate the command in the future. By the way, I planned to run the code from Windows CMD.
Thanks.
First, the -i flag specifies the input video file name. Second, using -map 0:a selects all audio streams we found before. Next, -acodec copy copies the stream without re-encoding. Finally, audio.
You can of course select any ffmpeg parameters for audio encoding that you like, to set things like bitrate and so on. Use -acodec libmp3lame and change the extension from . ogg to . mp3 for mp3 encoding.
There is no option yet in ffmpeg
to automatically extract all streams into an appropriate container, but it is certainly possible to do manually.
You only need to know the appropriate containers for the formats you want to extract.
Default stream selection only chooses one stream per stream type, so you have to manually map each stream with the -map
option.
Using ffmpeg
or ffprobe
you can get the info in each individual stream, and there is a wide variety of formats (xml, json, cvs, etc) available to fit your needs.
ffmpeg
exampleffmpeg -i input.mkv
The resulting output (I cut out some extra stuff, the stream numbers and format info are what is important):
Input #0, matroska,webm, from 'input.mkv': Metadata: Duration: 00:00:05.00, start: 0.000000, bitrate: 106 kb/s Stream #0:0: Video: h264 (High 4:4:4 Predictive), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 1k tbn, 50 tbc (default) Stream #0:1: Audio: vorbis, 44100 Hz, mono, fltp (default) Stream #0:2: Audio: aac, 44100 Hz, mono, fltp (default) Stream #0:3: Audio: flac, 44100 Hz, mono, fltp (default) Stream #0:4: Subtitle: ass (default)
ffprobe
exampleffprobe -v error -show_entries stream=index,codec_name,codec_type input.mkv
The resulting output:
[STREAM] index=0 codec_name=h264 codec_type=video [/STREAM] [STREAM] index=1 codec_name=vorbis codec_type=audio [/STREAM] [STREAM] index=2 codec_name=aac codec_type=audio [/STREAM] [STREAM] index=3 codec_name=flac codec_type=audio [/STREAM] [STREAM] index=4 codec_name=ass codec_type=subtitle [/STREAM]
Using the info from one of the commands above:
ffmpeg -i input.mkv \ -map 0:v -c copy video_h264.mkv \ -map 0:a:0 -c copy audio0_vorbis.oga \ -map 0:a:1 -c copy audio1_aac.m4a \ -map 0:a:2 -c copy audio2.flac \ -map 0:s -c copy subtitles.ass
In this case, the example above is the same as:
ffmpeg -i input.mkv \ -map 0:0 -c copy video_h264.mkv \ -map 0:1 -c copy audio0_vorbis.oga \ -map 0:2 -c copy audio1_aac.m4a \ -map 0:3 -c copy audio2.flac \ -map 0:4 -c copy subtitles.ass
I prefer the first example because the input file index:stream specifier:stream index
is more flexible and efficient; it is also less prone to incorrect mapping.
See documentation on stream specifiers and the -map
option to fully understand the syntax. Additional info is in the answer to FFmpeg mux video and audio (from another video) - mapping issue.
These examples will stream copy (re-mux) so no re-encoding will occur.
A partial list to match the stream with the output extension for some common formats:
Video Format | Extensions |
---|---|
H.264 | .mp4, .m4v, .mov, .h264, .264 |
H.265/HEVC | .mp4, .h265, .265 |
VP8/VP9 | .webm |
AV1 | .mp4 |
MPEG-4 | .mp4, .avi |
MPEG-2 | .mpg, .vob, .ts |
DV | .dv, .avi, .mov |
Theora | .ogv/.ogg |
FFV1 | .mkv |
Almost anything | .mkv, .nut |
Audio Format | Extensions |
---|---|
AAC | .m4a, .aac |
MP3 | .mp3 |
PCM | .wav |
Vorbis | .oga/.ogg |
Opus | .opus, .oga/.ogg, .mp4 |
FLAC | .flac, .oga/.ogg |
Almost anything | .mka, .nut |
Subtitle Format | Extensions |
---|---|
Subrip/SRT | .srt |
SubStation Alpha/ASS | .ass |
You would first list all the audio streams:
ffmpeg -i VIDEO.mkv
and then based on the output you can compile the command to extract the audio tracks individually.
Using some shell script you can then potentially automate this in a script file so that you can do it generically for any mkv file.
Subtitles are pretty much the same. The subtitles will be printed in the info and then you can extract them, similar to:
ffmpeg -threads 4 -i VIDEO.mkv -vn -an -codec:s:0.2 srt myLangSubtitle.srt
0.2 is the identifier that you have to read from the info.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With