Skip to content

Instantly share code, notes, and snippets.

@trustin
Created August 5, 2023 03:44
Show Gist options
  • Save trustin/f6f3bdf819e2341d36ae1b7e1b8f7ccb to your computer and use it in GitHub Desktop.
Save trustin/f6f3bdf819e2341d36ae1b7e1b8f7ccb to your computer and use it in GitHub Desktop.
Remove the tracks that match certain criteria from MKV files (using jq)
#!/usr/bin/env bash
set -Eeuo pipefail
if [[ $# -lt 2 ]]; then
echo "Usage: $(basename "$0") <preset or jq condition> <files or directories...>"
echo 'Presets: subrip_only, anime'
exit 1
fi
JQ_COND="$1"
shift
case "$JQ_COND" in
subrip_only)
JQ_COND='.type == "subtitles" and .properties.codec_id != "S_TEXT/UTF8"'
;;
anime)
JQ_COND='(.type == "audio" and .properties.language == "eng") or (.type == "subtitles" and .properties.codec_id != "S_TEXT/UTF8")'
;;
esac
find "$@" -type f -iname '*.mkv' -print | while read -r F; do
echo "$F"
JSON="$(mkvmerge -J "$F")"
NUM_TRACKS="$(echo "$JSON" | jq ".tracks | length")"
if [[ $NUM_TRACKS -le 2 ]]; then
echo '> Too few tracks in the file'
continue
fi
TRACKS_TO_KEEP=()
TRACKS_TO_REMOVE=()
for T in $(echo "$JSON" | jq ".tracks[] | select($JQ_COND) | .id"); do
TRACKS_TO_REMOVE+=($T)
done
if [[ "${#TRACKS_TO_REMOVE[@]}" -le 0 ]]; then
echo '> No tracks to remove'
continue
fi
for ((I=0; I<$NUM_TRACKS; I++)); do
KEEP=1
for TTR in "${TRACKS_TO_REMOVE[@]}"; do
if [[ $I -eq $TTR ]]; then
KEEP=0
fi
done
if [[ $KEEP -ne 0 ]]; then
TRACKS_TO_KEEP+=($I)
fi
done
if [[ "${#TRACKS_TO_KEEP[@]}" -le 1 ]]; then
echo '> Refusing to remove too many tracks'
continue
fi
echo "> Keeping ${TRACKS_TO_KEEP[@]} out of $NUM_TRACKS tracks"
TTK="$(IFS=,; echo "${TRACKS_TO_KEEP[*]}")"
NEW_F="$F.clean.tmp"
mkvmerge -o "$NEW_F" --video-tracks "$TTK" --audio-tracks "$TTK" --subtitle-tracks "$TTK" "$F"
mv "$NEW_F" "$F"
chmod 644 "$F"
echo
done
@trustin
Copy link
Author

trustin commented Aug 5, 2023

A few examples:

  • Remove subtitles that are not SubRip:
    remove-mkv-tracks.sh \
      '.type == "subtitles" and .properties.codec_id != "S_TEXT/UTF8"' \
      *.mkv
    
  • Remove all English audio:
    remove-mkv-tracks.sh \
      '.type == "audio" and .properties.language == "eng"' \
      *.mkv
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment