ts2mkv.py

changeset 14
b398ae388328
parent 13
cf5c5cec1b2b
child 15
82361ad7b3fe
--- a/ts2mkv.py	Sat Nov 25 15:37:54 2017 +0100
+++ b/ts2mkv.py	Sat Nov 25 16:51:08 2017 +0100
@@ -39,6 +39,14 @@
     rc = process.poll()
     return rc
 
+def ffmpeg_filename(filename):
+    """
+    Escape filename path contents for ffmpeg shell command
+    """
+    fn = "\\'".join(p for p in filename.split("'"))
+    fn = fn.replace(" ", "\\ ")
+    return fn
+
 class ts2mkv(object):
     """
     Main worker class, contains all the magic & ffmpeg voodoo
@@ -135,6 +143,38 @@
         self.msg_prepare += "Crop detected: %s\n" % option
         return option
 
+    def __get_audiomap(self, info):
+        """
+        Select the wanted german and english audio streams from ffmpeg info
+        output: mapping list
+        """
+        audiomap = []
+        audioall = filter_lines(info, "Audio:")
+        audio = filter_lines(audioall, "(deu):")
+        aidx = self.get_stream_index(
+            filter_lines(audio, "ac3"))
+        if aidx == "":
+            print audioall
+            print "No AC3 german audio stream found"
+            # try to find the first german audio stream
+            aidx = self.get_stream_index(audio.split("\n")[0])
+            if aidx == "":
+                print "No other german audio streams, trying english..."
+            else:
+                print "Selecting first german stream."
+                audiomap.append(aidx)
+        else:
+            audiomap.append(aidx)
+
+        audio = filter_lines(audioall, "(eng):")
+        aidx = self.get_stream_index(
+            filter_lines(audio, "ac3"))
+        if aidx != "":
+            # append english audio too!
+            print "Selecting english ac3 stream."
+            audiomap.append(aidx)
+        return audiomap
+
     def get_ffmpeg_command(self):
         """
         Too complex to describe, this does all the magic
@@ -145,8 +185,7 @@
 
 
         commands = []
-        fn = "\\'".join(p for p in self.filename.split("'"))
-        fn = fn.replace(" ", "\\ ")
+        fn = ffmpeg_filename(self.filename)
         outfn = self.outfilebase + ".mkv"
         # double-check: pull the kill switch and exit if outfile exists already!
         # we do not want to overwrite files in accident (caused by automatic file naming)
@@ -154,82 +193,45 @@
             print "Output file exists: %s" % outfn
             print "NOT overwriting it!"
             return None
-        outfn = "\\'".join(p for p in outfn.split("'"))
-        outfn = outfn.replace(" ", "\\ ")
+        outfn = ffmpeg_filename(outfn)
 
-        cmd = ["ffmpeg",
-                "-ss 00:05:00", "-t 1", # search to 5 minutes, analyze 1 second
-                "-i %s" % fn,
-                "-vf \"cropdetect=24:2:0\"", # detect black bar crop on top and bottom
-                "-f null", "-" # no output file
-                ]
-        print " ".join(cmd)
+        cmd = [
+            "ffmpeg", "-hide_banner",
+            "-ss 00:05:00", "-t 1", # search to 5 minutes, analyze 1 second
+            "-i %s" % fn,
+            "-vf \"cropdetect=24:2:0\"", # detect black bar crop on top and bottom
+            "-f null", "-" # no output file
+            ]
         p = subprocess.Popen(shlex.split(" ".join(cmd)), \
             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         out, err = p.communicate()
-        print "Command return code: ", p.poll()
         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:")
 
-
-        # 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
 
-        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
-        if a == "":
-            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)
+        # TODO: copy ALL subtitle streams if present!
+        # Stream #0:0[0x20](deu): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006), 492x250
+        submap = []
+        for tmp in filter_lines(info, "Subtitle: dvb_teletext").split("\n"):
+            if self.get_stream_index(tmp):
+                submap.append(self.get_stream_index(tmp))
 
+        # select audio streams
+        audiomap = self.__get_audiomap(info)
         if len(audiomap) == 0:
             print "No suitable audio stream found, aborting."
             return None
 
-
-        self.msg_prepare += "Video Stream selected: Stream #%s\n" % v
-
-        # TODO: Old dreambox images did a file split: .ts .ts.001 .ts.002 etc.
+        # Old dreambox images did a file split: .ts .ts.001 .ts.002 etc.
         # Find all these files and join them!
         inputs = [fn]
         if os.path.splitext(fn)[1].lower() == '.ts':
@@ -237,7 +239,6 @@
                 fn = "\\'".join(p for p in fpart.split("'"))
                 fn = fn.replace(" ", "\\ ")
                 inputs.append(fn)
-                #inputs.append(shlex.split(fpart))
 
         if len(inputs) > 1:
             # use ffmpeg input concat function
@@ -255,10 +256,17 @@
             idx += 1
 
         cmd = [
-            "ffmpeg",
+            "ffmpeg", "-hide_banner",
             "-i %s" % fn,
-            "-map %s" % v,
             ]
+
+        for tmp in submap:
+            self.msg_prepare += "Subtitle Stream selected: Stream #%s\n" % tmp
+            cmd.append("-map %s" % tmp)
+
+        cmd.append("-map %s" % v)
+        self.msg_prepare += "Video Stream selected: Stream #%s\n" % v
+
         flt = []
         crop = self.get_crop_option()
         if crop:
@@ -266,13 +274,15 @@
         if self.scaleto_720p:
             # -2 ensures division by two for codec
             flt.append("scale='min(1280,iw)':-2'")
-            self.msg_prepare += "Scaling cropped output stream to 720p\n"
+            self.msg_prepare += "Scaling output stream to 720p if width >1280\n"
         if len(flt) > 0:
             # append video filters
             cmd.append('-filter:v "%s"' % ",".join(flt))
-        for a in audiomap:
-            self.msg_prepare += "Audio Stream selected: Stream #%s\n" % a
-            cmd.append("-map %s" % a)
+        for tmp in audiomap:
+            self.msg_prepare += "Audio Stream selected: Stream #%s\n" % tmp
+            cmd.append("-map %s" % tmp)
+        if len(submap) > 0:
+            cmd.append("-c:s dvdsub")
         cmd.extend(self.video_options)
         cmd.extend(self.audio_options)
         cmd.append(outfn)

mercurial