133 self.msg_prepare += "WARNING: cropdetect inconsistent over scan time, disabling autocrop\n" |
141 self.msg_prepare += "WARNING: cropdetect inconsistent over scan time, disabling autocrop\n" |
134 return None |
142 return None |
135 self.msg_prepare += "Crop detected: %s\n" % option |
143 self.msg_prepare += "Crop detected: %s\n" % option |
136 return option |
144 return option |
137 |
145 |
|
146 def __get_audiomap(self, info): |
|
147 """ |
|
148 Select the wanted german and english audio streams from ffmpeg info |
|
149 output: mapping list |
|
150 """ |
|
151 audiomap = [] |
|
152 audioall = filter_lines(info, "Audio:") |
|
153 audio = filter_lines(audioall, "(deu):") |
|
154 aidx = self.get_stream_index( |
|
155 filter_lines(audio, "ac3")) |
|
156 if aidx == "": |
|
157 print audioall |
|
158 print "No AC3 german audio stream found" |
|
159 # try to find the first german audio stream |
|
160 aidx = self.get_stream_index(audio.split("\n")[0]) |
|
161 if aidx == "": |
|
162 print "No other german audio streams, trying english..." |
|
163 else: |
|
164 print "Selecting first german stream." |
|
165 audiomap.append(aidx) |
|
166 else: |
|
167 audiomap.append(aidx) |
|
168 |
|
169 audio = filter_lines(audioall, "(eng):") |
|
170 aidx = self.get_stream_index( |
|
171 filter_lines(audio, "ac3")) |
|
172 if aidx != "": |
|
173 # append english audio too! |
|
174 print "Selecting english ac3 stream." |
|
175 audiomap.append(aidx) |
|
176 return audiomap |
|
177 |
138 def get_ffmpeg_command(self): |
178 def get_ffmpeg_command(self): |
139 """ |
179 """ |
140 Too complex to describe, this does all the magic |
180 Too complex to describe, this does all the magic |
141 output: produces internal ffmpeg command list (empty command list on error) |
181 output: produces internal ffmpeg command list (empty command list on error) |
142 """ |
182 """ |
143 if not self.filename: |
183 if not self.filename: |
144 return None |
184 return None |
145 |
185 |
146 |
186 |
147 commands = [] |
187 commands = [] |
148 fn = "\\'".join(p for p in self.filename.split("'")) |
188 fn = ffmpeg_filename(self.filename) |
149 fn = fn.replace(" ", "\\ ") |
|
150 outfn = self.outfilebase + ".mkv" |
189 outfn = self.outfilebase + ".mkv" |
151 # double-check: pull the kill switch and exit if outfile exists already! |
190 # double-check: pull the kill switch and exit if outfile exists already! |
152 # we do not want to overwrite files in accident (caused by automatic file naming) |
191 # we do not want to overwrite files in accident (caused by automatic file naming) |
153 if len(glob.glob(outfn)) > 0: |
192 if len(glob.glob(outfn)) > 0: |
154 print "Output file exists: %s" % outfn |
193 print "Output file exists: %s" % outfn |
155 print "NOT overwriting it!" |
194 print "NOT overwriting it!" |
156 return None |
195 return None |
157 outfn = "\\'".join(p for p in outfn.split("'")) |
196 outfn = ffmpeg_filename(outfn) |
158 outfn = outfn.replace(" ", "\\ ") |
197 |
159 |
198 cmd = [ |
160 cmd = ["ffmpeg", |
199 "ffmpeg", "-hide_banner", |
161 "-ss 00:05:00", "-t 1", # search to 5 minutes, analyze 1 second |
200 "-ss 00:05:00", "-t 1", # search to 5 minutes, analyze 1 second |
162 "-i %s" % fn, |
201 "-i %s" % fn, |
163 "-vf \"cropdetect=24:2:0\"", # detect black bar crop on top and bottom |
202 "-vf \"cropdetect=24:2:0\"", # detect black bar crop on top and bottom |
164 "-f null", "-" # no output file |
203 "-f null", "-" # no output file |
165 ] |
204 ] |
166 print " ".join(cmd) |
|
167 p = subprocess.Popen(shlex.split(" ".join(cmd)), \ |
205 p = subprocess.Popen(shlex.split(" ".join(cmd)), \ |
168 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
206 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
169 out, err = p.communicate() |
207 out, err = p.communicate() |
170 print "Command return code: ", p.poll() |
|
171 self.msg_ffmpeg = out + "\n" + err |
208 self.msg_ffmpeg = out + "\n" + err |
172 self.msg_ffmpeg = self.msg_ffmpeg[self.msg_ffmpeg.find("Input #0"):] |
209 self.msg_ffmpeg = self.msg_ffmpeg[self.msg_ffmpeg.find("Input #0"):] |
173 |
210 |
174 # find "Stream #0:" lines |
211 # find "Stream #0:" lines |
175 info = filter_lines(self.msg_ffmpeg, "Stream #0:") |
212 info = filter_lines(self.msg_ffmpeg, "Stream #0:") |
176 |
|
177 |
|
178 # CRAP! ffmpeg cannot decode dvb_teletext streams to srt :( |
|
179 # are there any subtitle streams?! |
|
180 #s = filter_lines(info, "Subtitle:") |
|
181 #s = filter_lines(s, "(deu):") |
|
182 #if s != "": |
|
183 # s = self.get_stream_index(s.split("\n")[0]) |
|
184 # commands.append([ |
|
185 # "ffmpeg", |
|
186 # "-txt_format text", |
|
187 # "-i %s" % fn, |
|
188 # "-map %s" % s, |
|
189 # "%s.srt" % os.path.splitext(fn)[0] |
|
190 # ]) |
|
191 |
213 |
192 v = self.get_stream_index( |
214 v = self.get_stream_index( |
193 filter_lines(info, "Video:")) |
215 filter_lines(info, "Video:")) |
194 if v == "": |
216 if v == "": |
195 print "No video stream found" |
217 print "No video stream found" |
196 return None |
218 return None |
197 |
219 |
198 audiomap = [] |
220 |
199 audioall = filter_lines(info, "Audio:") |
221 # TODO: copy ALL subtitle streams if present! |
200 audio = filter_lines(audioall, "(deu):") |
222 # Stream #0:0[0x20](deu): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006), 492x250 |
201 a = self.get_stream_index( |
223 submap = [] |
202 filter_lines(audio, "ac3")) |
224 for tmp in filter_lines(info, "Subtitle: dvb_teletext").split("\n"): |
203 # TODO: wenn kein ac3 stream dann dts oder mpeg fallback |
225 if self.get_stream_index(tmp): |
204 if a == "": |
226 submap.append(self.get_stream_index(tmp)) |
205 print audioall |
227 |
206 print "No AC3 german audio stream found" |
228 # select audio streams |
207 # try to find the first german audio stream |
229 audiomap = self.__get_audiomap(info) |
208 a = self.get_stream_index(audio.split("\n")[0]) |
|
209 if a == "": |
|
210 print "No other german audio streams, trying english ac3..." |
|
211 else: |
|
212 print "Selecting first german stream." |
|
213 audiomap.append(a) |
|
214 else: |
|
215 audiomap.append(a) |
|
216 |
|
217 audio = filter_lines(audioall, "(eng):") |
|
218 a = self.get_stream_index( |
|
219 filter_lines(audio, "ac3")) |
|
220 if a != "": |
|
221 # append english audio too! |
|
222 print "Selecting english ac3 stream." |
|
223 audiomap.append(a) |
|
224 |
|
225 if len(audiomap) == 0: |
230 if len(audiomap) == 0: |
226 print "No suitable audio stream found, aborting." |
231 print "No suitable audio stream found, aborting." |
227 return None |
232 return None |
228 |
233 |
229 |
234 # Old dreambox images did a file split: .ts .ts.001 .ts.002 etc. |
230 self.msg_prepare += "Video Stream selected: Stream #%s\n" % v |
|
231 |
|
232 # TODO: Old dreambox images did a file split: .ts .ts.001 .ts.002 etc. |
|
233 # Find all these files and join them! |
235 # Find all these files and join them! |
234 inputs = [fn] |
236 inputs = [fn] |
235 if os.path.splitext(fn)[1].lower() == '.ts': |
237 if os.path.splitext(fn)[1].lower() == '.ts': |
236 for fpart in glob.glob(self.filename + '.' + ('[0-9]' * 3)): |
238 for fpart in glob.glob(self.filename + '.' + ('[0-9]' * 3)): |
237 fn = "\\'".join(p for p in fpart.split("'")) |
239 fn = "\\'".join(p for p in fpart.split("'")) |
238 fn = fn.replace(" ", "\\ ") |
240 fn = fn.replace(" ", "\\ ") |
239 inputs.append(fn) |
241 inputs.append(fn) |
240 #inputs.append(shlex.split(fpart)) |
|
241 |
242 |
242 if len(inputs) > 1: |
243 if len(inputs) > 1: |
243 # use ffmpeg input concat function |
244 # use ffmpeg input concat function |
244 # attention, ffmpeg doesnt like escape sequences |
245 # attention, ffmpeg doesnt like escape sequences |
245 fn = "\"concat:" + \ |
246 fn = "\"concat:" + \ |
253 self.msg_prepare += "Input file #%i: %s\n" % ( |
254 self.msg_prepare += "Input file #%i: %s\n" % ( |
254 idx, os.path.basename(tmp)) |
255 idx, os.path.basename(tmp)) |
255 idx += 1 |
256 idx += 1 |
256 |
257 |
257 cmd = [ |
258 cmd = [ |
258 "ffmpeg", |
259 "ffmpeg", "-hide_banner", |
259 "-i %s" % fn, |
260 "-i %s" % fn, |
260 "-map %s" % v, |
|
261 ] |
261 ] |
|
262 |
|
263 for tmp in submap: |
|
264 self.msg_prepare += "Subtitle Stream selected: Stream #%s\n" % tmp |
|
265 cmd.append("-map %s" % tmp) |
|
266 |
|
267 cmd.append("-map %s" % v) |
|
268 self.msg_prepare += "Video Stream selected: Stream #%s\n" % v |
|
269 |
262 flt = [] |
270 flt = [] |
263 crop = self.get_crop_option() |
271 crop = self.get_crop_option() |
264 if crop: |
272 if crop: |
265 flt.append(crop) |
273 flt.append(crop) |
266 if self.scaleto_720p: |
274 if self.scaleto_720p: |
267 # -2 ensures division by two for codec |
275 # -2 ensures division by two for codec |
268 flt.append("scale='min(1280,iw)':-2'") |
276 flt.append("scale='min(1280,iw)':-2'") |
269 self.msg_prepare += "Scaling cropped output stream to 720p\n" |
277 self.msg_prepare += "Scaling output stream to 720p if width >1280\n" |
270 if len(flt) > 0: |
278 if len(flt) > 0: |
271 # append video filters |
279 # append video filters |
272 cmd.append('-filter:v "%s"' % ",".join(flt)) |
280 cmd.append('-filter:v "%s"' % ",".join(flt)) |
273 for a in audiomap: |
281 for tmp in audiomap: |
274 self.msg_prepare += "Audio Stream selected: Stream #%s\n" % a |
282 self.msg_prepare += "Audio Stream selected: Stream #%s\n" % tmp |
275 cmd.append("-map %s" % a) |
283 cmd.append("-map %s" % tmp) |
|
284 if len(submap) > 0: |
|
285 cmd.append("-c:s dvdsub") |
276 cmd.extend(self.video_options) |
286 cmd.extend(self.video_options) |
277 cmd.extend(self.audio_options) |
287 cmd.extend(self.audio_options) |
278 cmd.append(outfn) |
288 cmd.append(outfn) |
279 |
289 |
280 commands.append(" ".join(cmd)) |
290 commands.append(" ".join(cmd)) |