1

I am trying to extract (first, in case of many) subtitle track from mkv files (via CLI only, no GUIs) using ffmpeg or mkvextract.

But there is one downside to this: I have to write the output name manually. In a batch, you don't know if the subtitles are .srt, .ass or maybe even a different format, so writing blindly subs.srt does not sound like a good idea.

Is there a way to extract subtitles while maintaining the original format?

For example, does ffmpeg have a way to get subtitles format info then do something like the command above with the type? (ideally native method via the tool, OS agnostic)

I can do this:

ffmpeg -i video.mkv subs.srt

Or this:

ffmpeg -i video.mkv -map 0:s:0 subs.srt

But is there a way to avoid specifying the output name? For example with mkvextract I can do this:

mkvextract attachments ..\input_video.mkv 1

And I will get the warning (not error):

"No destination file name specified, will use attachment name."

Which is actually the behavior I want, but that applies for attachments.

There is no mkvextract subtitles as mkvextract considers the subtitles as part of tracks. So if track order is messed up and subtitles is not the 3rd track, using a similar command with mkvextract won't work.


tl;dr

  • ffmpeg: I am stuck with (possibly) wrong file extension
  • mkvextract: I have a risk of extracting some random track and not the subtitles.
1
  • 1
    Your addition of the existing functionality in mkvextract actually makes this question a lot clearer. So this is not an issue of “rules” being “absolute” but presenting context to allow for support. That’s it. What you request makes great sense. Hope a solution can be found. Nov 13, 2022 at 2:15

2 Answers 2

2

We may use FFprobe for getting the subtitles codec name, and apply the extracted subtitles file extension accordingly.

The sample batch file is based on the following answer.

Assume MKV file name is in1.mkv, we may use the following Windows batch file:

set fname=in1
set mkv_fname=%fname%.mkv

@echo off
SETLOCAL

::Extract subtitles codec name from file using FFprobe
for /F "tokens=1 delims='\n'" %%a in ('ffprobe.exe "-v" "error" "-select_streams" "s:0" "-show_entries" "stream=codec_name" "-of" "default=noprint_wrappers=1:nokey=1" "%mkv_fname%"') do (
    ENDLOCAL
    set tmp_subs_codec=%%a  
)

::Remove the space from subs_codec
set subs_codec=%tmp_subs_codec:~0,-1%

if %subs_codec%==ass ffmpeg -y -vn -an -dn -i %mkv_fname% -c copy -map 0:s:0 %fname%.ass
if %subs_codec%==subrip ffmpeg -y -vn -an -dn -i %mkv_fname% -c copy -map 0:s:0 %fname%.srt

For batch file with argument, replace set fname=in1 with set fname=%1


Linux Bash example:

fname=in1
mkv_fname=$fname".mkv"
subs_codec=$(ffprobe -v error -select_streams s:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 $mkv_fname 2>&1)

if [ "$subs_codec" = "ass" ]; then
    ffmpeg -y -vn -an -dn -i $mkv_fname -c copy -map 0:s:0 $fname.ass 
fi

if [ "$subs_codec" = "subrip" ]; then
    ffmpeg -y -vn -an -dn -i $mkv_fname -c copy -map 0:s:0 $fname.srt 
fi
1
  • oh my god, I really appreciate it. You did not really have to go the extra mile at all, and editing to put Linux example, too! Just mentioning ffprobe and the command to extract codec would have been enough to answer the question, leaving out the post-processing to me. Thanks for taking the time to write such a complete answer!
    – user206904
    Nov 15, 2022 at 18:04
0

The answer by Rotem inspired me and gave me the technique, so I figured out a simpler way to do this and thought I would share it.

with ffprobe using PowerShell, we use ffprobe to get the information as on organized json, then instead of grep/selection on output string, we use the structured array and its accessors :

$ff_info_array = .\ffprobe.exe -v quiet -print_format json -show_format -show_streams "video.mkv" | ConvertFrom-Json

foreach ($entry in $ff_info_array.streams){
if ($entry.codec_type -eq "subtitle") {
                $sub_type=$entry.codec_name #this will contain .srt, .ass ,etc

                if($entry.disposition.default){
                    write-host  "found default sub and its extension is $sub_type "
                    $internal_sub_found = $true
                    $idx = $entry.index
                    $concat= $idx.""
                    #we can now extract the subtitle like above but add the exertion in the name or via mkvextract:
                    .\mkvextract.exe -q tracks  "video.mp4"  "$idx"":myvideo_output.$sub_type"

                }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.