Skip to content

Instantly share code, notes, and snippets.

@majora2007
Created May 22, 2020 18:36
Show Gist options
  • Save majora2007/114d869dbcb20e9c4bd307c5723144fc to your computer and use it in GitHub Desktop.
Save majora2007/114d869dbcb20e9c4bd307c5723144fc to your computer and use it in GitHub Desktop.
Removes non-LANG audio tracks and subtitles from mkv files in a directory.
#!/usr/bin/python
# Removes non-LANG audio tracks and subtitles from mkv files in a directory.
# Original script by greenbender at https://forum.videohelp.com/threads/343271-BULK-remove-non-English-tracks-from-MKV-container
# Modified by Joseph Milazzo for updated MkvMerge commands.
import os
import re
import sys
import StringIO
import subprocess
import json
import argparse
import commands
# change this for other languages (3 character code)
LANG = "eng"
# set this to the path for mkvmerge
MKVMERGE = "C:/Program Files/MKVToolNix/mkvmerge.exe"
AUDIO_RE = re.compile(r"Track ID (\d+): audio \([A-Z0-9_/]+\) [number:\d+ uid:\d+ codec_id:[A-Z0-9_/]+ codec_private_length:\d+ language:([a-z]{3})")
SUBTITLE_RE = re.compile(r"Track ID (\d+): subtitles \([A-Z0-9_/]+\) [number:\d+ uid:\d+ codec_id:[A-Z0-9_/]+ codec_private_length:\d+ language:([a-z]{3})(?: track_name:\w*)? default_track:[01]{1} forced_track:([01]{1})")
# if len(sys.argv) < 2:
# print "Please supply an input directory"
# sys.exit()
# in_dir = sys.argv[1]
def get_argument(argument, default="None"):
if argument:
return argument[0]
else:
return default
def init_args():
parser = argparse.ArgumentParser()
# Required Parameters
parser.add_argument('--subtitle_ids', required=False, nargs='*', default='', help="List of comma delimited ids of subitles to keep. Default empty")
return parser.parse_args()
args = init_args()
subtitle_ids = []
if str(get_argument(args.subtitle_ids, '')) is not '':
subtitle_ids = str(get_argument(args.subtitle_ids)).split(',')
in_dir = os.path.abspath('.')
for root, dirs, files in os.walk(in_dir):
for f in files:
# filter out non mkv files
if not f.endswith(".mkv"):
continue
# path to file
path = os.path.join(root, f)
# build command line
cmd = [MKVMERGE, "-J", path]
# get mkv info
mkvmerge = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = mkvmerge.communicate()
if mkvmerge.returncode != 0:
print >> sys.stderr, "mkvmerge failed to identify", path
continue
# find audio and subtitle tracks
audio = []
subtitle = []
info_json = json.loads(stdout)
tracks = info_json['tracks']
for track in tracks:
track['properties']['id'] = track['id']
if track['type'] == 'audio':
audio.append(track)
elif track['type'] == 'subtitles':
subtitle.append(track)
# filter out files that don't need processing
if len(audio) < 2 and len(subtitle) < 2:
print >> sys.stderr, "nothing to do for", path
continue
if len(subtitle_ids) > 0:
print('Supressing script subtitles with user defined subtitles')
# filter out tracks that don't match the language
audio_lang = filter(lambda a: a['properties']['language']==LANG, audio)
subtitle_lang = filter(lambda a: a['properties']['language']==LANG or str(a['properties']['id']) in subtitle_ids, subtitle) # NOTE: Subtitles are rarely tagged. Enhance by trying to detect language via google translate
# filter out files that don't need processing
if len(audio_lang) == 0 and len(subtitle_lang) == 0:
print >> sys.stderr, "no tracks with that language in", path
continue
for a in subtitle_lang:
print(a['properties']['id'])
# build command line
cmd = [MKVMERGE, "-o", path + ".temp"]
if len(audio_lang):
cmd += ["--audio-tracks", ",".join([str(a['id']) for a in audio_lang])]
for i in range(len(audio_lang)):
cmd += ["--default-track", ":".join([str(audio_lang[i]['id']), "0" if i else "1"])]
if len(subtitle_lang):
cmd += ["--subtitle-tracks", ",".join([str(s['id']) for s in subtitle_lang])]
for i in range(len(subtitle_lang)):
cmd += ["--default-track", ":".join([str(subtitle_lang[i]['id']), "0"])]
cmd += [path]
# process file
print >> sys.stderr, "Processing", path, "...",
mkvmerge = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = mkvmerge.communicate()
if mkvmerge.returncode != 0:
print >> sys.stderr, "Failed"
print(stdout)
continue
print >> sys.stderr, "Succeeded"
# overwrite file
os.remove(path) # Don't overwrite
os.rename(path + ".temp", path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment