#!/usr/bin/env python3 """ Mapfile format: ## More than meets the eye @ -a2 -q19 1 1x09 - Fire on the Mountain ^ ^ | +- Output file name (sans .mp4) +---- Title number Argument lines starting with `@` contain extra arguments passed to HandBrakeCLI. Each one affects all the output lines until a new such line is seen. Actual comments starting with `#` and empty lines are ignored. Greetz and thankz to Con Kolivas for the HandBrake options! """ import multiprocessing import os import subprocess import sys DVDW_DEVICE = os.environ.get('DVDW_DEVICE', '/dev/sr0') DVDW_CPUCOUNT = os.environ.get('DVDW_CPUCOUNT', multiprocessing.cpu_count()) DVDW_MODE = os.environ.get('DVDW_MODE', 'pal_4_3') OPT_720P = 'nombtree:keyint=1000:scenecut=10:ref=9:ip_factor=1:pb_factor=1:' \ 'direct_pred=auto:weight_b:analyse=all:me=umh:mixed_refs:' \ 'trellis=0:nofast_pskip:level_idc=41:threads={}:' \ 'aq_mode=0:nodeterministic:psy-rd=0|0:b-adapt=2:level=4.1:' \ 'direct=auto:fast-pskip=0:ipratio=1.00:pbratio=1.00:aq-mode=0' \ ':mbtree=0:cabac=0:no-dct-decimate=1:aq-strength=0:bframes=16'.format(DVDW_CPUCOUNT) BASE_MODES = { 'pal_4_3': { 'width': 720, 'height': 576, 'fps': 25, }, 'ntsc_4_3': { 'width': 720, 'height': 480, 'fps': 30, } } BASE_ARGS = '-i {DVDW_DEVICE} -e x264 -x {OPT} ' \ '-w {width} -l {height} -r {fps} ' \ '--no-loose-crop --crop 0:0:0:0 ' \ '--comb-detect ' \ '-t {tracknum} ' \ '{extra_args}' def find_handbrake(): """Do a simple search in $PATH for HandBrakeCLI """ for path in os.environ['PATH'].split(':'): candidate = os.path.join(path, 'HandBrakeCLI') if os.path.exists(candidate): return candidate def get_arguments(mapfile, mode): """Parse `mapfile` and combine its arguments with the ones in `mode`. """ fmt = mode.copy() fmt['DVDW_DEVICE'] = DVDW_DEVICE fmt['extra_args'] = '' args = [] for line in open(mapfile, 'r'): split_line = line.strip().split() if not split_line: continue if line.startswith('#'): continue elif split_line[0] == '@': fmt['extra_args'] = ' '.join(split_line[1:]) continue fmt['tracknum'] = split_line[0] trackname = ' '.join(split_line[1:]) args_list = BASE_ARGS.format(**fmt) args.append((args_list, trackname)) return args def main(mapfile): """Parse and rip """ hb = find_handbrake() if not hb: print('HandBrakeCLI not found') return 1 mode = BASE_MODES.get(DVDW_MODE) if mode['width'] <= 720: mode['OPT'] = OPT_720P else: raise NotImplementedError('Not here yet') args = get_arguments(mapfile, mode) for arg, trackname in args: cmd = '{} {}'.format(hb, arg) cmd = cmd.split() cmd.extend(('-o', '{}.mp4'.format(trackname))) ret = subprocess.run(cmd) return ret.returncode if __name__ == '__main__': if len(sys.argv) == 1: print('USAGE: {} MAPFILE'.format(sys.argv[0])) sys.exit(1) sys.exit(main(sys.argv[1]))