1

I made this script to remove ALL subs from all mkv files in a given path. It works ok. But now I want to only remove PGS subtitles and keep all SRT files, no matter the language.

for file in "$@"*mkv; do
    mkvmerge -o "${file%.mkv}".nosubs.mkv --no-subtitles "$file"
done

Bonus : How to keep all SRT files of a arbitrary language.

  • The --subtitle-tracks only supports specific track IDs or language codes, so you'll probably have to get the list of track IDs, process them and then remove those matching the specific format. – muru Dec 18 '17 at 6:20
  • Aren't language codes enough? – Freedo Dec 18 '17 at 6:30
  • What if you have both pgs and srt subtitles for a given language? – muru Dec 18 '17 at 7:59
1

The -I option in mkvmerge has been removed and replaced with -J which outputs JSON. Here's lumato's script adapted to be used with (requires jq to be installed see this link for installation instructions by OS)

#!/bin/bash
# If no directory is given, work in local dir
if [ -d "$1" ] || [ -f "$1" ]; then
  DIR="$1"
else
  echo "No target path given, using working directory '$(pwd)'"
  DIR="." 
fi

# Get all the MKV files in this dir and its subdirs
find "$DIR" -type f -name '*.mkv' | while read filename
do
    subs=$(mkvmerge -J "$filename" | jq -r '.tracks[] | select(.type=="subtitles") | select(.properties.language=="eng").id' | sed 'N;s/\n/,/') 
    if [[ -n $subs ]]
    then
         subs="-s $subs"
    else
        subs=-S
    fi
    echo -e "Extracting tracks \e[1m\e[34m${subs#* }\e[0m from \e[1m\e[34m${filename}\e[0m..."
    mkvmerge $subs -o "${filename%.mkv}".eng-srt-only.mkv "$filename" > /dev/null 2>&1
done
  • 1
    you should use -d to check that $1 is a directory at all – Freedo Jul 24 at 23:33
3

Parse the output of mkvmerge -I to get the desired track IDs, and pass the result as a comma-separated list with the --subtitle-tracks (-s) option.

To select only SRT subtitles using sed:

for file in "$@"*.mkv; do
    subs=$(mkvmerge -I "$file" | sed -ne '/^Track ID [0-9]*: subtitles (SubRip\/SRT).*/ { s/^[^0-9]*\([0-9]*\):.*/\1/;H }; $ { g;s/[^0-9]/,/g;s/^,//;p }')
    if [[ -n $subs ]]; then subs="-s $subs"; else subs=-S; fi
    mkvmerge $subs -o "${file%.mkv}".srt-only.mkv "$file"
done

Similarly, to select only English SRT:

for file in "$@"*.mkv; do
    subs=$(mkvmerge -I "$file" | sed -ne '/^Track ID [0-9]*: subtitles (SubRip\/SRT).* language:eng.*/ { s/^[^0-9]*\([0-9]*\):.*/\1/;H }; $ { g;s/[^0-9]/,/g;s/^,//;p }')
    if [[ -n $subs ]]; then subs="-s $subs"; else subs=-S; fi
    mkvmerge $subs -o "${file%.mkv}".eng-srt-only.mkv "$file"
done

Change language:eng to select another language.

  • Dude, you are a hero! Look at those sed and regex... you'll help thousands of people. Thanks so much – Freedo Dec 18 '17 at 20:16
  • 1
    To make it a single-file script, replace the for line with file=$1 and drop the done line. For the type parameter, you could replace SubRip\/SRT with, say, '"$(sed -e 's/[[*.\/\\]/\\&/g' <<< "$2")"' (this is like '"$2"' but escapes characters special to sed). For the language parameter, do the same with eng and $3 (and possibly just using '"$3"' since the language code is just three lowercase letters and those aren't special to sed). – lumato - Reinstate Monica Dec 19 '17 at 4:42
  • 1
    mkvmerge doesn't seem to support in-place editing. You could delete the input after processing (e.g. && rm -- "$file" after the mkvmerge command) or write a temporary file and rename it over the original (e.g. mkvmerge $subs -o "$file.$$.mkv" && mv -- "$file.$$.mkv" "$file"), which would reduce the free disk space requirement to roughly the size of the largest file. – lumato - Reinstate Monica Dec 20 '17 at 7:37
  • mkvmerge -I has been removed and replaced with -J which outputs a JSON . See my other comment to see an adapted script. – clapsus Jul 24 at 22:38

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.