You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
4.8 KiB

#!/bin/bash
###
# Wanted languages to keep
##
WANTED_LANGS=(
"und"
"eng"
"swe"
"jap"
"jpn"
)
###
# Paths to used programs
##
MKVMERGE=$(which mkvmerge)
PRINTF=$(which printf)
FIND=$(which find)
GREP=$(which grep)
SED=$(which sed)
CUT=$(which cut)
WC=$(which wc)
###
# Regexes
##
GREP_MATCH_AUDIO='Track ID (\d*): audio .* \[.*language:([^\s]+).*'
GREP_MATCH_SUBS='Track ID (\d*): subtitles .* \[.*language:([^\s]+).*'
SED_EXTRACT_INFO='s/Track ID ([0-9]*): .*language:(...).*/\1\t\2/'
###
# Read config file
##
CONFIG_FILE=$(echo ${XDG_CONFIG_DIR:-$HOME/.config/}mkvtrackcleaner.conf)
if test -f $CONFIG_FILE; then
source $CONFIG_FILE
fi
###
# Wrapper to do cleaning of files
##
cleanFile() {
if ! test -f "$1"; then
echo 'FILE is not a regular file' >&2
exit 2
fi
FILE=$1
# Run mkvmerge identify to check contents of file
OUTPUT=$($MKVMERGE --identify-verbose "$FILE")
# If failure, skip out and continue loop
if test $? -ne 0; then
echo 'Failed to identify '$FILE >&2
continue
fi
# Variables to collect all audio and subtitle tracks in the file
AUDIO=()
SUBTITLE=()
# Variables to collect all audio and subtitle tracks we want to keep
WANTED_AUDIO=()
WANTED_SUBTITLE=()
# Loop through lines in output
IFS=$'\n'
for LINE in $OUTPUT; do
# Match if current track is a audio track
if test $(echo $LINE | $GREP -P $GREP_MATCH_AUDIO | $WC -l) -ne 0; then
ROW=$(echo $LINE | $SED -E $SED_EXTRACT_INFO)
AUDIO+=($ROW)
# Filter through languages we want
for LANG in "${WANTED_LANGS[@]}"; do
if test $(echo $ROW | grep $LANG | wc -l) -ne 0; then
WANTED_AUDIO+=($ROW)
fi
done
fi
# Match if current track is a subtitle track
if test $(echo $LINE | $GREP -P $GREP_MATCH_SUBS | $WC -l) -ne 0; then
ROW=$(echo $LINE | $SED -E $SED_EXTRACT_INFO)
SUBTITLE+=($ROW)
# Filter through languages we want
for LANG in "${WANTED_LANGS[@]}"; do
if test $(echo $ROW | grep $LANG | wc -l) -ne 0; then
WANTED_SUBTITLE+=($ROW)
fi
done
fi
done
unset IFS
# If there's no wanted audio tracks, just save all the tracks
if test ${#WANTED_AUDIO[@]} -eq 0; then
WANTED_AUDIO=$AUDIO
fi
# Check for change and bail out if we don't need to mux the file
if test ${#WANTED_AUDIO[@]} -eq ${#AUDIO[@]} \
-a ${#WANTED_SUBTITLE[@]} -eq ${#SUBTITLE[@]}; then
echo "No change after filtering detected, skipping: "$FILE >&2
return
fi
# Start building command to run
CMD=$(echo $MKVMERGE ' -o ' $FILE'.tmp')
# Specify audiotracks to keep
if ! test ${#WANTED_AUDIO[@]} -eq 0; then
# Build a comma-separated list of all audio track ID's
TRACKS=$(echo $($PRINTF "%s\n" "${WANTED_AUDIO[@]}" | $CUT -f 1) | $SED 's/ /,/g')
# Append to CMD
CMD=$(echo $CMD '--audio-tracks' $TRACKS)
# Loop through all audio tracks and set --default-track to zero for all
# tracks
for ROW in "${WANTED_AUDIO[@]}"; do
CMD=$(echo $CMD '--default-track' $(echo $ROW | $CUT -d ' ' -f 1):0)
done
fi
# Specify subtitle tracks to keep
if test ${#WANTED_SUBTITLE[@]} -eq 0; then
CMD=$(echo $CMD '--no-subtitles')
else
# Build a comma-separated list of all audio track ID's
TRACKS=$(echo $($PRINTF "%s\n" "${WANTED_SUBTITLE[@]}" | $CUT -f 1) | $SED 's/ /,/g')
# Append to CMD
CMD=$(echo $CMD '--subtitle-tracks' $TRACKS)
# Loop through all audio tracks and set --default-track to zero for all
# tracks
for ROW in "${WANTED_SUBTITLE[@]}"; do
CMD=$(echo $CMD '--default-track' $(echo $ROW | $CUT -d ' ' -f 1):0)
done
fi
# Append path to original file
CMD=$(echo $CMD $FILE)
# Run mkvmerge to remux the file
echo -n "Remuxing "$FILE" ... "
OUTPUT=$($CMD)
# Print message success or failure message
if test $? -ne 0; then
echo "Failed :("
echo $OUTPUT
# Remove temp file after failure
rm $FILE'.tmp'
else
echo "Success :)"
# Replace original file after success
mv $FILE'.tmp' $FILE
fi
}
###
# Wrapper to loop through all mkv files recurively in a directory to
# run cleanFile on each mkv-file
##
cleanDirectory() {
$FIND $1 -type f -iname '*.mkv' -print0 | while read -d $'\0' FILE; do
cleanFile "$FILE"
done
}
###
# If parameter is a file, run this file
##
if test -f "$1"; then
cleanFile "$1"
fi
###
# If parameter is a directory, run for directories
##
if test -d "$1"; then
cleanDirectory "$1"
fi