28

I have installed MKVToolNix and Subtitle edit. I was able to extract subtitle using Subtitle edit through OCR. While it usable, it comes with a lot of errors.

Now I thought of using MKVToolNix to extract the subtitle. I can see it listed among audio and video tracks. But I am not sure how to get it out of the program.

After referring to a few guides on Google and here, I tried a few FFMPEG commands as well. None of them worked. For example

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

It will be great if anyone can help me find a solution. Thanks.

PS : I use Ubuntu 18.04.

6
  • 2
    Is askubuntu.com/questions/452268/extract-subtitle-from-mkv-files of any use?
    – Mokubai
    Feb 24, 2020 at 9:58
  • 1
    Yes, it works. mkvinfo was not good enough though.
    – user227495
    Feb 24, 2020 at 10:19
  • 1
    Yes, the comments on the top answer there suggest that mkvmerge -i <filename> is the better way to get the subtitle track numbers to then feed into mkvextract
    – Mokubai
    Feb 24, 2020 at 10:35
  • I found a workaround. Used ffmpeg -i filename.mkv.
    – user227495
    Feb 24, 2020 at 10:45
  • 3
    Need the full output of ffmpeg -i filename.mkv to be able to provide an accurate answer.
    – llogan
    Feb 24, 2020 at 21:21

6 Answers 6

17

I use MKVCleaver for this as it provides a simple GUI interface for mkvtoolnix on Windows.

You can simply drag and drop an MKV file (or files) on to it, click the check boxes for the tracks you want to extract, and then click "Extract Tracks".

By default your subtitle tracks will then be exported with the name FileName_TrackNo.ext. For DVD subtitles it will export two files, the index of subtitle time and position locations and the actual graphical subtitles.

You can then import these files into SubtitleEdit. I found it more reliable and accurate than SubtitleEdit alone, for some reason its DVD/MKV extractor is not entirely reliable.


For command line and alternative operating systems (you mention Ubuntu) you can use mkvextract which is a part of mkvtoolnix that you have already installed.

From an answer by Cornelius in Extract subtitles from mkv on AskUbuntu:

Run from terminal: mkvextract tracks <your_mkv_video> <track_numer>:<subtitle_file.srt>

Use mkvinfo to get information about tracks.

Though the comments suggest using mkvmerge -i <filename> to get a more directly usable track number for mkvextract. As you mention ffmpeg -i filename.mkv is also usable.

11
  • I forgot to mention. Will it work on Ubuntu 18.04 ? Thanks.
    – user227495
    Feb 24, 2020 at 9:54
  • I have an update. The files I get no matter .sup or .srt are around 15 MB and unusable. I am not sure what is wrong.
    – user227495
    Feb 24, 2020 at 12:16
  • 1
    What are your source files? Where did they come from? Can you list the actual output of your ffmpeg -i command?
    – Mokubai
    Feb 24, 2020 at 12:23
  • 2
    It sounds from your original question that they are graphical subtitles, you might need to extract them as idx or sub rather than sup?
    – Mokubai
    Feb 24, 2020 at 12:37
  • 2
    @backspace the problem is entirely that some programs count from 0 (mkvextract) and some count from 1 (ffmpeg/mkvmerge) as the first element when enumerating the list of tracks in a file. That means when you go from one to the other you need to take that into account and either increment or decrement by 1 when bringing in information used by the other program. It is a form of off by one error, longer description at en.wikipedia.org/wiki/Off-by-one_error
    – Mokubai
    Aug 22, 2021 at 21:17
42

MKVCleaver is a good option with a clear GUI. But since no one has corrected the ffmpeg command, you can also do it with that. You just had one extra colon at the end of the -map.

Here is a working ffmpeg command:

ffmpeg -i Movie.mkv -map 0:s:0 subs.srt
3
  • 3
    what does 0:s:0 in map do? what are those two 0s and what's that s for? Jan 15, 2022 at 8:05
  • 10
    The first number is which input you select (0 is the first and only input in my command), second character is what type of stream you select (s is subtitles, a is audio, v is video), third is which stream you select out of those. So like this: -map input_file_index:stream_type_specifier:stream_index So the code above takes the Movie.mkv, then its subtitle streams, then the first subtitle stream. (counting starts with 0, because it's an index.)
    – Tankki3
    Jan 15, 2022 at 17:31
  • 2
    Here is more information about the map command: trac.ffmpeg.org/wiki/Map
    – Tankki3
    Jan 15, 2022 at 17:33
4

I use Subtitle Edit https://www.videohelp.com/software/Subtitle-Edit

simply drag in the mkv file and then press save after you selected what subtitle from the mkv file you want and you can edit it easy too

1
  • This is the only solution that worked for me. I guess my subs were graphic ones so the built-in OCR worked great!
    – Bonnev
    May 21, 2022 at 18:22
2

I have used Inviska MKV Extract, which required MKVToolNix(52.0.0), on MacOS 10.14.6 and worked perfect. Just drag and drop a number of .mkv files, select what you need of each file, audio or subtitles, and click begin.

2

My ten cents..... Maybe just one aspect but me myself just wrote a simple script as a Windows batch file to extract all SRT subtitles fråm a MKV video. She script loops all mkv files in current directory and generates one srt file for each sub. Each resulting subtitle file is named with weather or not it´s forced as well as the language.

I´m not a smooth script guru. It's not very beautyful but it works for med :-)

@ECHO OFF
REM A Windows Batch-script that extracts SRT subtitles from MKV video files.
REM Filename format is [VIDEOFILENAME].[FLAG-FORCED][LANGUAGECODE].srt
REM e.g. TestFile.1eng.srt for forced Engling track or TestFile.0eng.srt for unforced 
setlocal enabledelayedexpansion
for %%f in (*.mkv) do (
  ffprobe "%%f" -v panic -show_entries stream=index -select_streams v -of compact=p=0:nk=1 > probetmpfile
  set /p videoID= < probetmpfile
  ffprobe "%%f" -v panic -show_entries stream=index -select_streams a -of compact=p=0:nk=1 > probetmpfile
  set /p audioID= < probetmpfile
  ffprobe "%%f" -v panic -show_entries stream=index:disposition=forced:stream_tags=language -select_streams s -of compact=p=0:nk=1 > probetmpfile
  for /L %%n in (0,1,99) do (
    findstr %%n probetmpfile > tmpfile
    set fileIsBlank=1
    for /F %%a in (tmpfile) do set fileIsBlank=0
    if %%n EQU !videoID! set fileIsBlank=1
    if %%n EQU !audioID! set fileIsBlank=1
    if !fileIsBlank! EQU 0 (
      set /p subIdLang= < tmpFile
      if %%n LSS 10 (mkvextract tracks "%%f" %%n:"%%~nf.!subIdLang:~2,1!!subIdLang:~4!.srt") else (mkvextract tracks "%%f" %%n:"%%~nf.!subIdLang:~3,1!!subIdLang:~5!.srt")
    )
  )
)
del tmpfile
del probetmpfile
pause
1
  • This is a very promising start. Unfortunately, the script will also extract PGS subs to .SRT format. Would be nice if the script could detect hdmv_pgs_subtitle and extract it as PGS files.
    – Arete
    Jun 21, 2022 at 12:33
2

I know there already are several answers in here, but neither completely answers the question if you need to use command line on macOS, so I am adding mine too.

This was actually spotted by mokubai in his comment under this question: there's a similar question on AskUbuntu forums, and one of the answers supplies a complete script, however it is not working.

I have rewritten the script from scratch, and also properly commented it in case someone needs to tweak it later. You only need to have MKVToolNix installed, no other dependencies.

EDIT [2023-08-03]: I created a separate Gist for this script, where I will update it in the future when/if needed.

#!/bin/sh
# Extract subtitles from each MKV/MP4 file in the given directory
    
# MKVToolNix path - Leave empty if you have the tools added to $PATH.
#   This is needed e.g. on macOS, if you downloaded MKVToolNix app
#   and just dragged it to the Applications folder.
toolPath='/Applications/MKVToolNix.app/Contents/MacOS/'
    
# If no directory is given, work in local dir
if [ "$1" = "" ]; then
  DIR="."
else
  DIR="$1"
fi
    
# Get all MKV/MP4 files in this dir and its subdirs
find "$DIR" -type f \( -iname '*.mkv' -o -iname '*.mp4' \) | while read filename
do
  echo "Processing file $filename:"
  
  # Get base file name (without extension)
  fileBasename=${filename%.*}
  
  # Parse info about all subtitles tracks from file. This will output lines in the
  # following format, one line per subtitle track, fields delimited by tabulator:
  #   trackID <tab> trackLanguage <tab> trackCodecID <tab> trackCodec
  "${toolPath}mkvmerge" -J "$filename" | python -c "exec(\"import sys, json;\nfor track in json.load(sys.stdin)['tracks']:\n\tif track['type'] == 'subtitles':\n\t\tprint(str(track['id']) + '\t' + track['properties']['language'] + '\t' + track['properties']['codec_id'] + '\t' + track['codec'])\")" | while IFS=$'\t' read -r trackNumber trackLanguage trackCodecID trackCodec;
  do
    # optional: process only some types of subtitle tracks (according to $trackCodecID)
    #   See codec types here: https://tools.ietf.org/id/draft-lhomme-cellar-codec-00.html#rfc.section.6.5
    if [[ $trackCodecID == 'S_VOBSUB' || $trackCodecID == 'unwantedID_#2' ]] ; then
      echo "  skipping track #${trackNumber}: $trackLanguage ($trackCodec, $trackCodecID)"
      continue;
    fi
        
    echo "  extracting track #${trackNumber}: $trackLanguage ($trackCodec, $trackCodecID)"
        
    # extract track with language and track id
    `"${toolPath}mkvextract" tracks "$filename" $trackNumber:"$fileBasename $trackNumber($trackLanguage).srt" > /dev/null 2>&1`
  done
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .