You cannot autodetect extension, but FFMPEG is able to autodetect which muxer to use for given output container and some muxer (mostly for audio and subtitles) can process only streams of specific type (codec).
Also FFMPEG tries to select the "best" (usualy most suitable) stream, if you don't specify it enough. And if you don't allow reencoding, the only suitable streams are those supported by the muxer.
It means if you tell FFMPEG e.g. to save file as *.AC3
without reencoding it (-c copy
), but don't specify which stream to process using -map
, it will try to use first suitable stream; or throw error if no such stream exists. And if you use -map
parameter to specify an unsuitable stream, it will also throw error.
So you can use these features, for example, to extract only DTS stream regardless of on which position in the file is it:
ffmpeg -i in.mkv -c copy out.dts
Or if you know your file contains DTS, AC3 and AAC streams but don't know in which order:
ffmpeg -i in.mkv -c copy -map 0:a:0 out-1.dts
ffmpeg -i in.mkv -c copy -map 0:a:0 out-1.ac3
ffmpeg -i in.mkv -c copy -map 0:a:0 out-1.aac
ffmpeg -i in.mkv -c copy -map 0:a:1 out-2.dts
ffmpeg -i in.mkv -c copy -map 0:a:1 out-2.ac3
ffmpeg -i in.mkv -c copy -map 0:a:1 out-2.aac
ffmpeg -i in.mkv -c copy -map 0:a:2 out-3.dts
ffmpeg -i in.mkv -c copy -map 0:a:2 out-3.ac3
ffmpeg -i in.mkv -c copy -map 0:a:2 out-3.aac
This will create all the mentioned files, but only those that match a suitable stream in the input file will contain the stream. So after this you just need to delete the empty files a use what remains.
In Windows command (batch), you can instead check the ERRORLEVEL
(which is either 0
for success or 1
for failure) and keep only the files that were successfuly extracted:
ffmpeg -i in.mkv -c copy -map 0:a:0 out-1.dts
if [1] == [%ERRORLEVEL%] del out-1.dts
ffmpeg -i in.mkv -c copy -map 0:a:0 out-1.ac3
if [1] == [%ERRORLEVEL%] del out-1.ac3
...
However note that for specific muxers there may be some limitations:
- MP3 muxer works without
-map
parameter only for files containing exactly one mp3 stream. So to extract mp3 from multi-audio file, you must use multiple calls with -map 0:a:X
and try each audio stream until you find the correct one.
- AC3 muxer is used on AC3 but can also process MP3 and MP2 streams so if the file contains both AC3 and MP3/MP2 streams, it will extract both (or first one) ignoring the extension.
- other limits may also exist but I haven't found them yet.
Update: here are few ideas how to solve the problem with AC3 and MP2/MP3 streams.
Inside Windows Batch you can use %~zX
to read size of an input file and if A LSS B
to compare two numbers. For Linux check this.
Idea A) you can extract all (audio) streams from the file as out-1.ac3, out-2.ac3, etc. and then find the largest one (presuming AC3 is larger than MP2 or MP3 of same length).
ffmpeg -i in.mkv -c copy -map 0:a:0 out-0.ac3
ffmpeg -i in.mkv -c copy -map 0:a:1 out-1.ac3
call keep_larger.cmd out-0.ac3 out-1.ac3 out.ac3
And the keep_larger
batch will be:
if %~z1 LSS %~z2 goto del
del %2
ren %1 %3
goto end
:del
del %1
ren %2 %3
:end
Now the largest file is saved as out.ac3
Idea 2) Program LAME can accept WAVE and MPEG audio as input (and convert them to MP3), but will fail on AC3. So you can extract ~5 minutes of the stream and let LAME to process it (use param -f
for fastest processing). If it's WAVE or MPEG, the result will be large (1MB+) but if it was AC3, the result will be very small ~5kB).
ffmpeg -i in.mkv -c copy -map 0:a:0 -t "5:00" out.mp2
lame -f out.mp2 out.mp3
call keep_if_larger.cmd 500000 out.mp3
if not exist out.mp3 ren out.mp2 out.ac3
if not exist out.ac3 del out.mp2
if not exist out.ac3 del out.mp3
The keep_if_larger
batch will be:
if %~z2 LSS %1 del %2
Now if the selected stream was AC3, LAME was not able to convert it to acceptably big MP3 and we could rename MP2 to AC3. Otherwise we delete MP2 and MP3 file and try another stream.
-ac
is the audio channels option. If you try to use that to set stream copy mode you'll get an error:Expected number for ac but found: copy
. Instead use-c:a
\-codec:a
\-acodec
.c:a
.mkv
for the output container, as it supports aac, opus (seems to work nowadays), etc. Wouldn't really recommend this, though.