# HG changeset patch # User mdd # Date 1511485945 -3600 # Node ID 0d021d47eca5023c806c6953a1c146f638364028 # Parent 1420abafd049f4fadfb79756fe2205d97a08061e added ts2mkv converter diff -r 1420abafd049 -r 0d021d47eca5 ts2mkv.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts2mkv.py Fri Nov 24 02:12:25 2017 +0100 @@ -0,0 +1,151 @@ +#!/usr/bin/env python + +import subprocess +from eit import readeit +import os, shlex + +def filter_lines(data, search): + ret = [] + for line in data.split("\n"): + if line.find(search) == -1: + continue + ret.append(line) + return "\n".join(ret) + +def run_command(command): + process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if output: + print output.strip() + rc = process.poll() + return rc + +class ts2mkv(object): + def __init__(self): + self.msg_prepare = "" + self.msg_eit = "" + self.msg_ffmpeg = "" + self.command = None + + self.video_options = [ + "-c:v libx264", + "-preset slow", + "-crf 21" + ] + self.audio_options = [ + "-c:a copy", + ] + + + def get_stream_index(self, data): + idx = data.find("Stream #") + if idx == -1: + return "" + idx += 8 + self.msg_prepare += "Selecting: %s\n" % data + return data[idx:idx+3] + + def get_movie_description(self, filename): + # 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") + + def get_ffmpeg_command(self, filename): + commands = [] + fn = "\\'".join(p for p in filename.split("'")) + + p = subprocess.Popen(["ffmpeg", "-i", fn], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + self.msg_ffmpeg = out + "\n" + err + self.msg_ffmpeg = self.msg_ffmpeg[self.msg_ffmpeg.find("Input #0"):] + # 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?! + #s = filter_lines(info, "Subtitle:") + #s = filter_lines(s, "(deu):") + #if s != "": + # s = self.get_stream_index(s.split("\n")[0]) + # commands.append([ + # "ffmpeg", + # "-txt_format text", + # "-i %s" % fn, + # "-map %s" % s, + # "%s.srt" % os.path.splitext(fn)[0] + # ]) + + v = self.get_stream_index( + filter_lines(info, "Video:")) + if v == "": + print "No video stream found" + return None + + 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 + + audio = filter_lines(audioall, "(eng):") + a = self.get_stream_index( + filter_lines(audio, "ac3")) + if a != "": + # append english audio too! + audiomap.append(a) + + + self.msg_prepare += "Video Stream selected: Stream #%s\n" % v + cmd = [ + "ffmpeg", + "-i %s" % fn, + "-map %s" % v, + ] + for a in audiomap: + self.msg_prepare += "Audio Stream selected: Stream #%s\n" % a + cmd.append("-map %s" % a) + cmd.extend(self.video_options) + cmd.extend(self.audio_options) + cmd.append(os.path.splitext(fn)[0] + ".mkv") + + 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" + + mkv = ts2mkv() + mkv.load(filename) + if mkv.command: + fd = open(os.path.splitext(filename)[0] + ".txt", "wb") + fd.write(mkv.msg_eit) + fd.write("\n\n# ---DEBUG---\n\n") + fd.write(mkv.msg_prepare) + fd.write(mkv.msg_ffmpeg) + fd.close() + print mkv.msg_ffmpeg + + for cmd in mkv.command: + print "Executing ffmpeg:\n%s\n" % " ".join(cmd) + run_command(cmd)