|
1 #!/usr/bin/env python |
|
2 |
|
3 import subprocess |
|
4 from eit import readeit |
|
5 import os, shlex |
|
6 |
|
7 def filter_lines(data, search): |
|
8 ret = [] |
|
9 for line in data.split("\n"): |
|
10 if line.find(search) == -1: |
|
11 continue |
|
12 ret.append(line) |
|
13 return "\n".join(ret) |
|
14 |
|
15 def run_command(command): |
|
16 process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) |
|
17 while True: |
|
18 output = process.stdout.readline() |
|
19 if output == '' and process.poll() is not None: |
|
20 break |
|
21 if output: |
|
22 print output.strip() |
|
23 rc = process.poll() |
|
24 return rc |
|
25 |
|
26 class ts2mkv(object): |
|
27 def __init__(self): |
|
28 self.msg_prepare = "" |
|
29 self.msg_eit = "" |
|
30 self.msg_ffmpeg = "" |
|
31 self.command = None |
|
32 |
|
33 self.video_options = [ |
|
34 "-c:v libx264", |
|
35 "-preset slow", |
|
36 "-crf 21" |
|
37 ] |
|
38 self.audio_options = [ |
|
39 "-c:a copy", |
|
40 ] |
|
41 |
|
42 |
|
43 def get_stream_index(self, data): |
|
44 idx = data.find("Stream #") |
|
45 if idx == -1: |
|
46 return "" |
|
47 idx += 8 |
|
48 self.msg_prepare += "Selecting: %s\n" % data |
|
49 return data[idx:idx+3] |
|
50 |
|
51 def get_movie_description(self, filename): |
|
52 # read the EIT file |
|
53 # TODO: fallback to meta file if no EIT |
|
54 # TODO: is there a way to get the imdb for the movie automagically? |
|
55 # http://www.omdbapi.com/apikey.aspx |
|
56 self.msg_eit = readeit(os.path.splitext(filename)[0] + ".eit") |
|
57 |
|
58 def get_ffmpeg_command(self, filename): |
|
59 commands = [] |
|
60 fn = "\\'".join(p for p in filename.split("'")) |
|
61 |
|
62 p = subprocess.Popen(["ffmpeg", "-i", fn], |
|
63 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
64 out, err = p.communicate() |
|
65 self.msg_ffmpeg = out + "\n" + err |
|
66 self.msg_ffmpeg = self.msg_ffmpeg[self.msg_ffmpeg.find("Input #0"):] |
|
67 # find "Stream #0:" lines |
|
68 info = filter_lines(self.msg_ffmpeg, "Stream #0:") |
|
69 |
|
70 fn = fn.replace(" ", "\\ ") |
|
71 |
|
72 # CRAP! ffmpeg cannot decode dvb_teletext streams to srt :( |
|
73 # are there any subtitle streams?! |
|
74 #s = filter_lines(info, "Subtitle:") |
|
75 #s = filter_lines(s, "(deu):") |
|
76 #if s != "": |
|
77 # s = self.get_stream_index(s.split("\n")[0]) |
|
78 # commands.append([ |
|
79 # "ffmpeg", |
|
80 # "-txt_format text", |
|
81 # "-i %s" % fn, |
|
82 # "-map %s" % s, |
|
83 # "%s.srt" % os.path.splitext(fn)[0] |
|
84 # ]) |
|
85 |
|
86 v = self.get_stream_index( |
|
87 filter_lines(info, "Video:")) |
|
88 if v == "": |
|
89 print "No video stream found" |
|
90 return None |
|
91 |
|
92 audioall = filter_lines(info, "Audio:") |
|
93 audio = filter_lines(audioall, "(deu):") |
|
94 a = self.get_stream_index( |
|
95 filter_lines(audio, "ac3")) |
|
96 # TODO: wenn kein ac3 stream dann dts oder mpeg fallback |
|
97 audiomap = [a] |
|
98 if a == "": |
|
99 print "No suitable german audio stream found" |
|
100 return None |
|
101 |
|
102 audio = filter_lines(audioall, "(eng):") |
|
103 a = self.get_stream_index( |
|
104 filter_lines(audio, "ac3")) |
|
105 if a != "": |
|
106 # append english audio too! |
|
107 audiomap.append(a) |
|
108 |
|
109 |
|
110 self.msg_prepare += "Video Stream selected: Stream #%s\n" % v |
|
111 cmd = [ |
|
112 "ffmpeg", |
|
113 "-i %s" % fn, |
|
114 "-map %s" % v, |
|
115 ] |
|
116 for a in audiomap: |
|
117 self.msg_prepare += "Audio Stream selected: Stream #%s\n" % a |
|
118 cmd.append("-map %s" % a) |
|
119 cmd.extend(self.video_options) |
|
120 cmd.extend(self.audio_options) |
|
121 cmd.append(os.path.splitext(fn)[0] + ".mkv") |
|
122 |
|
123 commands.append(" ".join(cmd)) |
|
124 return commands |
|
125 |
|
126 def load(self, filename): |
|
127 self.filename = filename |
|
128 self.get_movie_description(filename) |
|
129 self.command = self.get_ffmpeg_command(filename) |
|
130 |
|
131 if __name__ == "__main__": |
|
132 import sys |
|
133 os.system('cls' if os.name == 'nt' else 'clear') |
|
134 |
|
135 # TODO: get file from commandline |
|
136 filename = "testfiles/chappie.ts" |
|
137 |
|
138 mkv = ts2mkv() |
|
139 mkv.load(filename) |
|
140 if mkv.command: |
|
141 fd = open(os.path.splitext(filename)[0] + ".txt", "wb") |
|
142 fd.write(mkv.msg_eit) |
|
143 fd.write("\n\n# ---DEBUG---\n\n") |
|
144 fd.write(mkv.msg_prepare) |
|
145 fd.write(mkv.msg_ffmpeg) |
|
146 fd.close() |
|
147 print mkv.msg_ffmpeg |
|
148 |
|
149 for cmd in mkv.command: |
|
150 print "Executing ffmpeg:\n%s\n" % " ".join(cmd) |
|
151 run_command(cmd) |