Fri, 24 Nov 2017 23:11:58 +0100
added option parser and automatic file rename feature
eit.py | file | annotate | diff | comparison | revisions | |
ts2mkv.py | file | annotate | diff | comparison | revisions |
--- a/eit.py Fri Nov 24 16:16:50 2017 +0100 +++ b/eit.py Fri Nov 24 23:11:58 2017 +0100 @@ -360,6 +360,8 @@ Read Eit File and show the information. """ eitlist = eitinfo(eitfile) + if len(eitlist.eit) == 0: + return None out = "Movie name: %s" % eitlist.get_name() out += "\nGenre: %s" % eitlist.get_genre() out += "\nComponents: %s" % eitlist.get_components()
--- a/ts2mkv.py Fri Nov 24 16:16:50 2017 +0100 +++ b/ts2mkv.py Fri Nov 24 23:11:58 2017 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/env python import subprocess -from eit import readeit +from eit import readeit, eitinfo import os, shlex def filter_lines(data, search): @@ -24,19 +24,20 @@ return rc class ts2mkv(object): - def __init__(self): + def __init__(self, crf=19, tune='film', scaleto_720p=True, rename=False): self.msg_prepare = "" self.msg_eit = "" self.msg_ffmpeg = "" self.command = None - self.scaleto_720p = True + self.scaleto_720p = scaleto_720p + self.rename = rename self.video_options = [ "-c:v libx264", "-preset faster", # slow - "-tune film", # film / animation - "-crf 19" # 21, better 19 + "-tune %s" % tune, # film / animation + "-crf %i" % crf # 21, better 19 ] self.audio_options = [ "-c:a copy", @@ -50,12 +51,40 @@ self.msg_prepare += "Selecting: %s\n" % data return data[idx:idx+3] - def get_movie_description(self, filename): + def get_movie_description(self): + if not self.filename: + return # read the EIT file # TODO: fallback to meta file if no EIT # TODO: is there a way to get the imdb for the movie automagically? # http://www.omdbapi.com/apikey.aspx - self.msg_eit = readeit(os.path.splitext(filename)[0] + ".eit") + filename = os.path.splitext(self.filename)[0] + ".eit" + self.msg_eit = readeit(filename) + if not self.rename or not self.msg_eit: + return + info = eitinfo(filename) + name = info.eit.get("name") + if name == "": + # cancel rename, no movie title found! + return + genre = info.eit.get("genre") + if genre != "": + name = "%s (%s)" % (name, genre) + # build new filename + name = name.replace(' : ', ' - ') + name = name.replace(': ', ' - ') + name = name.replace(':', '-') + name = name.replace('/', '') + name = name.replace('\\', '') + name = name.replace('?', '') + name = name.replace('*', '') + name = name.replace('\"', '\'') + + self.outfilebase = os.path.join( + os.path.dirname(filename), + name + ) + def get_crop_option(self): lines = filter_lines(self.msg_ffmpeg, "[Parsed_cropdetect").split("\n") @@ -72,9 +101,16 @@ self.msg_prepare += "Crop detected: %s\n" % option return option - def get_ffmpeg_command(self, filename): + def get_ffmpeg_command(self): + if not self.filename: + return None + commands = [] - fn = "\\'".join(p for p in filename.split("'")) + fn = "\\'".join(p for p in self.filename.split("'")) + fn = fn.replace(" ", "\\ ") + outfn = self.outfilebase + ".mkv" + outfn = "\\'".join(p for p in outfn.split("'")) + outfn = outfn.replace(" ", "\\ ") # ffmpeg -ss 00:05:00 -t 2 -i testfiles/chappie.ts -vf "cropdetect=24:16:0" -f null - @@ -94,7 +130,6 @@ # find "Stream #0:" lines info = filter_lines(self.msg_ffmpeg, "Stream #0:") - fn = fn.replace(" ", "\\ ") # CRAP! ffmpeg cannot decode dvb_teletext streams to srt :( # are there any subtitle streams?! @@ -116,23 +151,36 @@ print "No video stream found" return None + audiomap = [] audioall = filter_lines(info, "Audio:") audio = filter_lines(audioall, "(deu):") a = self.get_stream_index( filter_lines(audio, "ac3")) # TODO: wenn kein ac3 stream dann dts oder mpeg fallback - audiomap = [a] if a == "": - print "No suitable german audio stream found" - return None + print audioall + print "No AC3 german audio stream found" + # try to find the first german audio stream + a = self.get_stream_index(audio.split("\n")[0]) + if a == "": + print "No other german audio streams, trying english ac3..." + else: + print "Selecting first german stream." + audiomap.append(a) + else: + audiomap.append(a) audio = filter_lines(audioall, "(eng):") a = self.get_stream_index( filter_lines(audio, "ac3")) if a != "": # append english audio too! + print "Selecting english ac3 stream." audiomap.append(a) + if len(audiomap) == 0: + print "No suitable audio stream found, aborting." + return None self.msg_prepare += "Video Stream selected: Stream #%s\n" % v @@ -156,35 +204,65 @@ cmd.append("-map %s" % a) cmd.extend(self.video_options) cmd.extend(self.audio_options) - cmd.append(os.path.splitext(fn)[0] + ".mkv") + cmd.append(outfn) commands.append(" ".join(cmd)) return commands def load(self, filename): self.filename = filename - self.get_movie_description(filename) - self.command = self.get_ffmpeg_command(filename) - -if __name__ == "__main__": - import sys - os.system('cls' if os.name == 'nt' else 'clear') - - # TODO: get file from commandline - #filename = "testfiles/chappie.ts" - filename = "/srv/storage0/DREAMBOX/Science Fiction/THE_ISLAND.ts" + self.outfilebase = os.path.splitext(filename)[0] + self.get_movie_description() + self.command = self.get_ffmpeg_command() - mkv = ts2mkv() - mkv.load(filename) - if mkv.command: - fd = open(os.path.splitext(filename)[0] + ".txt", "wb") - fd.write(mkv.msg_eit) + def convert(self): + if not self.command: + return None + fd = open(self.outfilebase + ".txt", "wb") + fd.write(self.msg_eit) fd.write("\n\n# ---DEBUG---\n\n") - fd.write(mkv.msg_prepare) - fd.write(mkv.msg_ffmpeg) + fd.write(self.msg_prepare) + fd.write(self.msg_ffmpeg) fd.close() - print mkv.msg_ffmpeg + #print self.msg_ffmpeg for cmd in mkv.command: print "Executing ffmpeg:\n%s\n" % cmd - run_command(cmd) + return run_command(cmd) + + + +if __name__ == "__main__": + # parse command line options + import argparse, sys, glob + + parser = argparse.ArgumentParser(description = 'DVB-TS to MKV kung-fu') + parser.add_argument('--crf', type=int, default=19, + help='h264 crf (default 19)') + parser.add_argument('--tune', default='film', + help='ffmpeg tune preset [film, animation] (default is film)') + parser.add_argument('--ns', action='store_true', default=False, + help='no rescaling (default is scale to 720p)') + parser.add_argument('--rename', action='store_true', default=False, + help='rename file basename to name and genre from EIT file if present') + parser.add_argument('input', metavar='input', nargs='+', + help='one or more files, glob style syntax') + + args = parser.parse_args() + mkv = ts2mkv( + crf = args.crf, + tune = args.tune, + scaleto_720p = (not args.ns), + rename = args.rename + ) + + #os.system('cls' if os.name == 'nt' else 'clear') + + for srcstr in args.input: + src = glob.glob(srcstr) + for filename in src: + print filename + mkv.load(filename) + mkv.convert() + +