Ejemplo n.º 1
0
    def on_cut_play_clicked(self, widget, data=None):
        filename = self.gui.main_window.get_selected_filenames()[0]

        error, cutlists = cutlists_management.download_cutlists(
            filename, self.app.config.get('general', 'server'),
            self.app.config.get('general', 'choose_cutlists_by'),
            self.app.config.get('general', 'cutlist_mp4_as_hq'))
        if error:
            return

        cutlist = cutlists_management.get_best_cutlist(cutlists)
        cutlist.download(self.app.config.get('general', 'server'), filename)
        cutlist.read_cuts()

        # delete cutlist?
        if self.app.config.get('general', 'delete_cutlists'):
            fileoperations.remove_file(cutlist.local_filename)

        # make edl
        # https://github.com/mpv-player/mpv-player.github.io/blob/master/guides/edl-playlists.rst
        edlurl = "edl://"

        for count, (start, duration) in enumerate(cutlist.cuts_seconds):
            edlurl = edlurl + filename + "," + str(start) + "," + str(
                duration) + ";"

        p = subprocess.Popen([self.app.config.get_program('mpv'), edlurl])

        while p.poll() == None:
            time.sleep(1)
            while Gtk.events_pending():
                Gtk.main_iteration()
Ejemplo n.º 2
0
    def get_keyframes_from_file(self, filename):
        """ returns keyframe list - in frame numbers"""
        
        if not os.path.isfile(filename + '.ffindex_track00.kf.txt'):
            try:
                command = [self.config.get_program('ffmsindex'),  '-p', '-f', '-k',  filename ]
                ffmsindex = subprocess.call(command)
            except OSError:
                return None, "ffmsindex konnte nicht aufgerufen werden."
    
        if os.path.isfile(filename + '.ffindex_track00.kf.txt'):
            filename_keyframes = filename + '.ffindex_track00.kf.txt'
        elif os.path.isfile(filename + '.ffindex_track01.kf.txt'):
            filename_keyframes = filename + '.ffindex_track01.kf.txt'
        elif os.path.isfile(filename + '.ffindex_track02.kf.txt'):
            filename_keyframes = filename + '.ffindex_track02.kf.txt'
        else:
            filename_keyframes = None

        try:
            index = open(filename_keyframes, 'r')
        except IOError:
            return None,  "Keyframe File von ffmsindex konnte nicht geöffnet werden."
        index.readline()
        index.readline()
        try:
            list =[int(i) for i in index.read().splitlines()]
        except ValueError:
            return None,  "Keyframes konnten nicht ermittelt werden."
        index.close()
        if os.path.isfile(filename + '.ffindex'):
            fileoperations.remove_file(filename +'.ffindex')
            
        return list,  None
Ejemplo n.º 3
0
    def __create_cutlist_virtualdub(self, filename, format):
        """ returns: cuts, error_message """

        try:
            f = open(filename, 'r')
        except IOError:
            return None, "Die VirtualDub-Projektdatei konnte nicht gelesen werden.\nWurde das Projekt in VirtualDub nicht gespeichert?\n(Datei: %s)." % filename

        cuts_frames = []  # (start, duration)
        count = 0

        for line in f.readlines():
            if "VirtualDub.subset.AddRange" in line:
                try:
                    start, duration = line[line.index('(') + 1: line.index(')')].split(',')
                except (IndexError, ValueError) as message:
                    return None, "Konnte Schnitte nicht lesen, um Cutlist zu erstellen. (%s)" % message

                if format == Format.HQ or format == Format.HD:
                    cuts_frames.append((int(start) - 2, int(duration)))
                else:
                    cuts_frames.append((int(start), int(duration)))

        if len(cuts_frames) == 0:
            return None, "Konnte keine Schnitte finden!"

        fileoperations.remove_file(filename)

        return cuts_frames, None
Ejemplo n.º 4
0
    def _on_button_show_cuts_clicked(self, widget, data=None):
        cutlist = cutlists_management.Cutlist()

        if self.builder.get_object('radio_local_cutlist').get_active():
            cutlist.local_filename = self.builder.get_object(
                'label_cutlist').get_text()

        else:
            cutlist = self.treeview_cutlists.get_selected()

            if not cutlist:
                self.gui.message_error_box(
                    "Es wurde keine Cutlist ausgewählt!")
                return

            error = cutlist.download(self.app.config.get('general', 'server'),
                                     self.filename)

            if error:
                self.gui.message_error_box(error)
                return

        self.app.show_cuts(self.filename, cutlist)

        # delete cutlist
        fileoperations.remove_file(cutlist.local_filename)
Ejemplo n.º 5
0
        def upload():
            error_messages = []

            count = len(cutlists)
            # ~ counter = 0
            for cutlist in cutlists:
                # ~ counter += 1
                error_message = cutlist.upload(
                    self.app.config.get('general', 'server'),
                    self.app.config.get('general', 'cutlist_hash'))
                if error_message:
                    error_messages.append(error_message)
                else:
                    if self.app.config.get('general', 'delete_cutlists'):
                        fileoperations.remove_file(cutlist.local_filename)
                # ~ self.log.debug("Counter: {}, Count: {}".format(counter, count))
                # ~ if counter < count:
                # ~ self.log.debug("Multiple cutlists: Next upload delayed.")
                # ~ time.sleep(1.1)

            message = "Es wurden %s/%s Cutlisten hochgeladen!" % (
                str(count - len(error_messages)), str(count))
            if len(error_messages) > 0:
                message += " (" + ", ".join(error_messages) + ")"

            yield message
Ejemplo n.º 6
0
    def mux_ac3(self, filename, cut_video, ac3_file, cutlist):	# cuts the ac3 and muxes it with the avi into an mkv
        mkvmerge = self.config.get_program('mkvmerge')
        root, extension = os.path.splitext(filename)
        mkv_file = os.path.splitext(cut_video)[0] + ".mkv"
        # env
        my_env = os.environ.copy()
        my_env["LANG"] = "C"

        # creates the timecodes string for splitting the .ac3 with mkvmerge
        timecodes = (','.join([self.get_timecode(start) + ',' + self.get_timecode(start+duration) for start, duration in cutlist.cuts_seconds]))
        # splitting .ac3. Every second fragment will be used.
#        return_value = subprocess.call([mkvmerge, "--split", "timecodes:" + timecodes, "-o", root + "-%03d.mka", ac3_file])
        try:
            blocking_process = subprocess.Popen([mkvmerge, '--ui-language',  'en_US',  "--split", "timecodes:" + timecodes, "-o", root + "-%03d.mka", ac3_file ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True,  env=my_env)
        except OSError as e:
            return None,  e.strerror + ": " + mkvmerge
        return_value = blocking_process.wait()
        # return_value=0 is OK, return_value=1 means a warning. Most probably non-ac3-data that has been omitted.
        # TODO: Is there some way to pass this warning to the conclusion dialog?
        if return_value != 0 and return_value != 1:
            return None, None, str(return_value)

        if len(cutlist.cuts_seconds) == 1:              # Only the second fragment is needed. Delete the rest.
            fileoperations.rename_file(root + "-002.mka", root + ".mka")
            fileoperations.remove_file(root + "-001.mka")
            if os.path.isfile(root + "-003.mka"):
                fileoperations.remove_file(root + "-003.mka")

        else:                                           # Concatenating every second fragment.
            command = [mkvmerge, "-o", root + ".mka", root + "-002.mka"]
            command[len(command):] = ["+" + root + "-%03d.mka" % (2*n) for n in range(2,len(cutlist.cuts_seconds)+1)]
#            return_value = subprocess.call(command)
            try:
                blocking_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True,  env=my_env)
            except OSError as e:
                return None,  e.strerror + ": " + mkvmerge
            return_value = blocking_process.wait()
            if return_value != 0:               # There should be no warnings here
                return None, None, str(return_value)

            for n in range(1,2*len(cutlist.cuts_seconds)+2):    # Delete all temporary audio fragments
                if os.path.isfile(root + "-%03d.mka" % n):
                    fileoperations.remove_file(root + "-%03d.mka" % n)

        # Mux the cut .avi with the resulting audio-file into mkv_file
        # TODO: Is there some way to pass possible warnings to the conclusion dialog?
#        return_value = subprocess.call([mkvmerge, "-o", mkv_file, cut_video, root + ".mka"])
        try:
            blocking_process = subprocess.Popen([mkvmerge, "-o", mkv_file, cut_video, root + ".mka"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True,  env=my_env)
        except OSError as e:
            return None,  e.strerror + ": " + mkvmerge
        return_value = blocking_process.wait()
        if return_value != 0 and return_value != 1:
            return None, None, str(return_value)

        fileoperations.remove_file(root + ".mka")       # Delete remaining temporary files
        fileoperations.remove_file(cut_video)
        return mkv_file, ac3_file, None
Ejemplo n.º 7
0
 def do(self, filenames):
     if len(filenames) == 1:
         message = "Es ist eine Datei ausgewählt. Soll diese Datei "
     else:
         message = "Es sind %s Dateien ausgewählt. Sollen diese Dateien " % len(filenames)
     
     if self.__gui.question_box(message + "endgültig gelöscht werden?"):
         for f in filenames:           
             fileoperations.remove_file(f)
Ejemplo n.º 8
0
    def do(self, downloads):
        downloads_count = len(downloads)
        if downloads_count == 1:
            question = "Soll der Download wirklich entfernt werden?"
        else:
            question = "Sollen %i Downloads wirklich entfernt werden?" % downloads_count

        dialog = gtk.MessageDialog(self.__gui.main_window, 0, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, question)
        checkbutton = gtk.CheckButton('Die heruntergeladene Datei in den Müll verschieben\n(Fertige Downloads werden nicht verschoben)')
        checkbutton.set_active(True)
        checkbutton.show()
        dialog.vbox.pack_end(checkbutton)
        response = dialog.run()

        if response == gtk.RESPONSE_YES:
            model = self.__gui.main_window.treeview_download.get_model()

            refs = []
            for row in model:
                if row[0] in downloads:
                    refs.append(gtk.TreeRowReference(model, row.path))

                    files = [
                        os.path.join(row[0].information['output'], row[0].filename + '.torrent'),
                        os.path.join(row[0].information['output'], row[0].filename + '.aria2'),
                        os.path.join(row[0].information['output'], row[0].filename + '.cutlist'),
                        os.path.join(self.__app.config.get('general', 'folder_trash_otrkeys'), row[0].filename + '.segments'),
                    ]

                    for file in files:
                        if os.path.exists(file):
                            fileoperations.remove_file(file, None)

                    if checkbutton.get_active() and not row[0].information['status'] in [DownloadStatus.FINISHED, DownloadStatus.SEEDING]:
                        otrkey = os.path.join(row[0].information['output'], row[0].filename)
                        # move otrkey to trash
                        if os.path.exists(otrkey):
                            fileoperations.move_file(otrkey, self.__app.config.get('general', 'folder_trash_otrkeys'), None)
                        # move avi file of otrdecoder to trash
                        avi_file = os.path.splitext(otrkey)[0]
                        if os.path.exists(avi_file):
                            fileoperations.move_file(avi_file, self.__app.config.get('general', 'folder_trash_avis'), None)

                    row[0].stop()

            for ref in refs:
                iter = model.get_iter(ref.get_path())
                model.remove(iter)

        dialog.destroy()
Ejemplo n.º 9
0
    def get_timecodes_from_file(self, filename):  # TESTING
        """ returns frame->timecode and timecode->frame dict"""

        if not os.path.isfile(filename + '.ffindex_track00.tc.txt'):
            try:
                command = [
                    self.config.get_program('ffmsindex'), '-f', '-c', '-k',
                    filename
                ]
                process = subprocess.Popen(command,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
                self.show_indexing_progress(process)
            except OSError:
                return None, "ffmsindex konnte nicht aufgerufen werden."

        if os.path.isfile(filename + '.ffindex_track00.tc.txt'):
            filename_timecodes = filename + '.ffindex_track00.tc.txt'
        elif os.path.isfile(filename + '.ffindex_track01.tc.txt'):
            filename_timecodes = filename + '.ffindex_track01.tc.txt'
        elif os.path.isfile(filename + '.ffindex_track02.tc.txt'):
            filename_timecodes = filename + '.ffindex_track02.tc.txt'
        else:
            filename_timecodes = None

        try:
            index = open(filename_timecodes, 'r')
        except (IOError, TypeError) as e:
            return None, "Timecode Datei von ffmsindex konnte nicht geöffnet werden."
        index.readline()
        try:
            frame_timecode = {}
            for line_num, line in enumerate(index, start=0):
                frame_timecode[line_num] = int(
                    round(float(line.replace('\n', '').strip()), 2) / 1000 *
                    Gst.SECOND)
        except ValueError:
            index.close()
            return None, "Timecodes konnten nicht ermittelt werden."

        index.close()
        # Generate reverse dict
        timecode_frame = {v: k for k, v in frame_timecode.items()}
        if os.path.isfile(filename + '.ffindex'):
            fileoperations.remove_file(filename + '.ffindex')

        self.log.debug("Number of frames (frame_timecode dict): {}".format(
            list(frame_timecode.keys())[-1] + 1))
        return frame_timecode, timecode_frame, None
Ejemplo n.º 10
0
    def on_cut_play_clicked(self, widget, data=None):
        filename = self.gui.main_window.get_selected_filenames()[0]

        error, cutlists = cutlists_management.download_cutlists(
            filename, self.app.config.get('general', 'server'),
            self.app.config.get('general', 'choose_cutlists_by'),
            self.app.config.get('general', 'cutlist_mp4_as_hq'))
        if error:
            return

        cutlist = cutlists_management.get_best_cutlist(cutlists)
        cutlist.download(self.app.config.get('general', 'server'), filename)
        cutlist.read_cuts()

        # delete cutlist?
        if self.app.config.get('general', 'delete_cutlists'):
            fileoperations.remove_file(cutlist.local_filename)

        # make edl
        # http://www.mplayerhq.hu/DOCS/HTML/en/edl.html
        # [Begin Second] [End Second] [0=Skip/1=Mute]
        edl_filename = os.path.join(
            self.app.config.get('general', 'folder_uncut_avis'), ".tmp.edl")
        f = open(edl_filename, "w")

        f.write("0 %s 0\n" % (cutlist.cuts_seconds[0][0] - 1))

        for count, (start, duration) in enumerate(cutlist.cuts_seconds):
            end = start + duration
            if count + 1 == len(cutlist.cuts_seconds):
                f.write("%s 50000 0\n" % (end))
            else:
                f.write("%s %s 0\n" %
                        (end, (cutlist.cuts_seconds[count + 1][0] - 1)))
        f.close()

        p = subprocess.Popen([
            self.app.config.get('general', 'mplayer'), "-edl", edl_filename,
            filename
        ])

        while p.poll() == None:
            time.sleep(1)
            while gtk.events_pending():
                gtk.main_iteration(False)

        fileoperations.remove_file(edl_filename)
Ejemplo n.º 11
0
        def upload():
            error_messages = []

            for cutlist in cutlists:
                error_message = cutlist.upload(self.app.config.get('general', 'server'), self.app.config.get('general', 'cutlist_hash'))
                if error_message: 
                    error_messages.append(error_message)
                else:
                    if self.app.config.get('general', 'delete_cutlists'):
                        fileoperations.remove_file(cutlist.local_filename)
                 
            count = len(cutlists)
                
            message = "Es wurden %s/%s Cutlisten hochgeladen!" % (str(count - len(error_messages)), str(count))
            if len(error_messages) > 0:
                message += " (" + ", ".join(error_messages) + ")"

            yield message
Ejemplo n.º 12
0
        def upload():
            error_messages = []

            for cutlist in cutlists:
                error_message = cutlist.upload(
                    self.app.config.get('general', 'server'),
                    self.app.config.get('general', 'cutlist_hash'))
                if error_message:
                    error_messages.append(error_message)
                else:
                    if self.app.config.get('general', 'delete_cutlists'):
                        fileoperations.remove_file(cutlist.local_filename)

            count = len(cutlists)

            message = "Es wurden %s/%s Cutlisten hochgeladen!" % (
                str(count - len(error_messages)), str(count))
            if len(error_messages) > 0:
                message += " (" + ", ".join(error_messages) + ")"

            yield message
Ejemplo n.º 13
0
    def get_keyframes_from_file(self, filename):
        """ returns keyframe list - in frame numbers"""

        if not os.path.isfile(filename + '.ffindex_track00.kf.txt'):
            try:
                command = [
                    self.config.get_program('ffmsindex'), '-f', '-k', filename
                ]
                process = subprocess.Popen(command,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
                self.show_indexing_progress(process)
            except OSError:
                return None, "ffmsindex konnte nicht aufgerufen werden."

        if os.path.isfile(filename + '.ffindex_track00.kf.txt'):
            filename_keyframes = filename + '.ffindex_track00.kf.txt'
        elif os.path.isfile(filename + '.ffindex_track01.kf.txt'):
            filename_keyframes = filename + '.ffindex_track01.kf.txt'
        elif os.path.isfile(filename + '.ffindex_track02.kf.txt'):
            filename_keyframes = filename + '.ffindex_track02.kf.txt'
        else:
            filename_keyframes = None

        try:
            index = open(filename_keyframes, 'r')
        except (IOError, TypeError) as e:
            return None, "Keyframe File von ffmsindex konnte nicht geöffnet werden."
        index.readline()
        index.readline()
        try:
            list = [int(i) for i in index.read().splitlines()]
        except ValueError:
            index.close()
            return None, "Keyframes konnten nicht ermittelt werden."
        index.close()
        if os.path.isfile(filename + '.ffindex'):
            fileoperations.remove_file(filename + '.ffindex')

        return list, None
Ejemplo n.º 14
0
    def on_cut_play_clicked(self, widget, data=None):   
        filename = self.gui.main_window.get_selected_filenames()[0]
        
        error, cutlists = cutlists_management.download_cutlists(filename, self.app.config.get('general', 'server'), self.app.config.get('general', 'choose_cutlists_by'), self.app.config.get('general', 'cutlist_mp4_as_hq')) 
        if error:
            return
            
        cutlist = cutlists_management.get_best_cutlist(cutlists)
        cutlist.download(self.app.config.get('general', 'server'), filename)
        cutlist.read_cuts()       
       
        # delete cutlist?        
        if self.app.config.get('general', 'delete_cutlists'):
            fileoperations.remove_file(cutlist.local_filename)  
       
        # make edl
        # http://www.mplayerhq.hu/DOCS/HTML/en/edl.html
        # [Begin Second] [End Second] [0=Skip/1=Mute]
        edl_filename = os.path.join(self.app.config.get('general', 'folder_uncut_avis'), ".tmp.edl")
        f = open(edl_filename, "w")
       
        f.write("0 %s 0\n" % (cutlist.cuts_seconds[0][0] - 1))        
       
        for count, (start, duration) in enumerate(cutlist.cuts_seconds):
            end = start + duration
            if count + 1 == len(cutlist.cuts_seconds):
                f.write("%s 50000 0\n" % (end))
            else:
                f.write("%s %s 0\n" % (end, (cutlist.cuts_seconds[count+1][0] - 1)))
        f.close()
        
        p = subprocess.Popen([self.app.config.get('general', 'mplayer'), "-edl", edl_filename, filename])                
        
        while p.poll() == None:
            time.sleep(1)
            while gtk.events_pending():
                gtk.main_iteration(False)

        fileoperations.remove_file(edl_filename)
Ejemplo n.º 15
0
    def _on_button_show_cuts_clicked(self, widget, data=None):
        cutlist = cutlists_management.Cutlist()

        if self.builder.get_object('radio_local_cutlist').get_active():            
            cutlist.local_filename = self.builder.get_object('label_cutlist').get_text()
            
        else:
            cutlist = self.treeview_cutlists.get_selected()
            
            if not cutlist:
                self.gui.message_error_box("Es wurde keine Cutlist ausgewählt!")
                return
                                    
            error = cutlist.download(self.app.config.get('general', 'server'), self.filename)

            if error:
                self.gui.message_error_box(error)
                return
            
        self.app.show_cuts(self.filename, cutlist)
        
        # delete cutlist
        fileoperations.remove_file(cutlist.local_filename)
Ejemplo n.º 16
0
    def __cut_file_virtualdub(self, filename, config_value, cuts=None, manually=False):
        format = self.__get_format(filename)

        if format == Format.HQ:
            aspect, error_message = self.__get_aspect_ratio(filename)
            if not aspect:
                return None, error_message

            if aspect == "16:9":
                comp_data = codec.get_comp_data_h264_169()
            else:
                comp_data = codec.get_comp_data_h264_43()
        elif format == Format.HD:
            aspect, error_message = self.__get_aspect_ratio(filename)
            if not aspect:
                return None, error_message

            if aspect == "16:9":
                comp_data = codec.get_comp_data_hd_169()
            else:
                comp_data = codec.get_comp_data_hd_43()

        elif format == Format.AVI:
            comp_data = codec.get_comp_data_dx50()

        else:
            return None, "Format nicht unterstützt (Nur Avi DX50, HQ H264 und HD sind möglich)."

        # make file for virtualdub scripting engine
        if manually:
            # TODO: kind of a hack
            curr_dir = os.getcwd()
            try:
                os.chdir(dirname(config_value))
            except OSError:
                return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        self.__gui.main_window.set_tasks_progress(50)

        f = open("tmp.vcf", "w")

        if not manually:
            f.write('VirtualDub.Open("%s");\n' % filename)

        if self.config.get('general', 'smart'):
            f.writelines([
                'VirtualDub.video.SetMode(1);\n',
                'VirtualDub.video.SetSmartRendering(1);\n',
                'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
                'VirtualDub.video.SetCompData(%s);\n' % comp_data
                ])
        else:
            f.write('VirtualDub.video.SetMode(0);\n')

        f.write('VirtualDub.subset.Clear();\n')

        if not manually:
            for frame_start, frames_duration in cuts:
                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration))

            cut_video = self.__generate_filename(filename)

            f.writelines([
                'VirtualDub.SaveAVI("%s");\n' % cut_video,
                'VirtualDub.Close();'
                ])

        f.close()

        # start vdub
        if not exists(config_value):
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        if manually:
            win_filename = "Z:" + filename.replace(r"/", r"\\")
            command = 'VirtualDub.exe /s tmp.vcf "%s"' % win_filename
        else:
            command = "%s /s tmp.vcf /x" % config_value

        command = "wineconsole " + command

        print command

        try:
            vdub = subprocess.Popen(command, shell=True)
        except OSError:
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        while vdub.poll() == None:
            time.sleep(1)

            while events_pending():
                main_iteration(False)

        fileoperations.remove_file('tmp.vcf')

        if manually:
            os.chdir(curr_dir)
            return None, None

        return cut_video, None
Ejemplo n.º 17
0
    def do(self, downloads, cut_action=None):
        downloads_count = len(downloads)
        if downloads_count == 1:
            question = "Soll der Download wirklich entfernt werden?"
        else:
            question = "Sollen %i Downloads wirklich entfernt werden?" % downloads_count

        dialog = Gtk.MessageDialog(self.__gui.main_window, 0,
                                   Gtk.MessageType.QUESTION,
                                   Gtk.ButtonsType.YES_NO, question)
        checkbutton = Gtk.CheckButton(
            'Die heruntergeladene Datei in den Müll verschieben\n(Fertige Downloads werden nicht verschoben)'
        )
        checkbutton.set_active(True)
        checkbutton.show()
        dialog.vbox.pack_end(checkbutton, False, False, 0)
        response = dialog.run()

        if response == Gtk.ResponseType.OK:
            model = self.__gui.main_window.treeview_download.get_model()

            refs = []
            for row in model:
                if row[0] in downloads:
                    refs.append(Gtk.TreeRowReference.new(model, row.path))

                    files = [
                        os.path.join(row[0].information['output'],
                                     row[0].filename + '.torrent'),
                        os.path.join(row[0].information['output'],
                                     row[0].filename + '.aria2'),
                        os.path.join(row[0].information['output'],
                                     row[0].filename + '.cutlist'),
                        os.path.join(
                            self.__app.config.get('general',
                                                  'folder_trash_otrkeys'),
                            row[0].filename + '.segments'),
                    ]

                    for file in files:
                        if os.path.exists(file):
                            fileoperations.remove_file(file, None)

                    if checkbutton.get_active(
                    ) and not row[0].information['status'] in [
                            DownloadStatus.FINISHED, DownloadStatus.SEEDING
                    ]:
                        otrkey = os.path.join(row[0].information['output'],
                                              row[0].filename)
                        # move otrkey to trash
                        if os.path.exists(otrkey):
                            fileoperations.move_file(
                                otrkey,
                                self.__app.config.get('general',
                                                      'folder_trash_otrkeys'),
                                None)
                        # move avi file of otrdecoder to trash
                        avi_file = os.path.splitext(otrkey)[0]
                        if os.path.exists(avi_file):
                            fileoperations.move_file(
                                avi_file,
                                self.__app.config.get('general',
                                                      'folder_trash_avis'),
                                None)

                    row[0].stop()

            for ref in refs:
                iter = model.get_iter(ref.get_path())
                model.remove(iter)

        dialog.destroy()
Ejemplo n.º 18
0
    def cut_file_manually(self, filename):
        """ Cuts a file manually with Avidemux or VirtualDub or the CutInterface and gets cuts from
            possibly created project files (VD) or from output (AD). 
            returns: error_message, cutlist """
        
        program, config_value, ac3file = self.get_program(filename, manually=True)
        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)

        if error:
            if exists(filename+'.mkv'):
                fileoperations.remove_file(filename+'.mkv')
            return "Konnte FPS nicht bestimmen: " + error,  None


        if program < 0:
            return config_value, None
            
        cutlist = cutlists_management.Cutlist()

        if program == Program.AVIDEMUX:

            cutter = CutAvidemux(self.app, self.gui)
            cuts_frames,  cutlist_error = cutter.create_cutlist(filename, config_value)
                        
        elif program == Program.VIRTUALDUB: # VIRTUALDUB
            
            cutter = CutVirtualdub(self.app, self.gui)
            cuts_frames,  cutlist_error = cutter.create_cutlist(filename, config_value)
                
        if program == Program.CUT_INTERFACE:
            # looking for latest cutlist, if any
            p, video_file = os.path.split(filename)
            cutregex = re.compile("^" + video_file + "\.?(.*).cutlist$")
            files = os.listdir(p)
            number = -1
            local_cutlist = None		# use fallback name in conclusions if there are no local cutlists
            for f in files:
                match = cutregex.match(f)
                if match:
                    # print "Found local cutlist %s" % match.group()
                    if match.group(1) == '':
                        res_num = 0
                    else:
                        res_num = int(match.group(1))
                    
                    if res_num > number:
                        res_num = number
                        local_cutlist = p + "/" + match.group()
                    
            ci = CutinterfaceDialog.NewCutinterfaceDialog()
            cutlist = ci._run(filename , local_cutlist, self.app)
            ci.destroy()
            
            if cutlist.cuts_frames == None or len(cutlist.cuts_frames) == 0:
                cutlist_error = "Keine Schnitte angegeben"
            else:
                cutlist_error = None
            
        else: # complete cutlist for Avidemux & VirtualDub
        
            # create cutlist data
            if cutlist_error == None:
                cutlist.cuts_frames = cuts_frames
                cutlist.intended_app = basename(config_value)                    
                cutlist.usercomment = 'Mit %s geschnitten' %self.app.app_name
                cutlist.fps = fps
                
                # calculate seconds
                for start_frame, duration_frames in cuts_frames:
                    cutlist.cuts_seconds.append((start_frame / fps, duration_frames / fps))
        
        if cutlist_error:            
            return cutlist_error, None
        else:
            return None, cutlist
Ejemplo n.º 19
0
    def on_cut_play_clicked(self, widget, data=None):
        filename = self.gui.main_window.get_selected_filenames()[0]

        error, cutlists = cutlists_management.download_cutlists(
            filename, self.app.config.get('general', 'server'),
            self.app.config.get('general', 'choose_cutlists_by'),
            self.app.config.get('general', 'cutlist_mp4_as_hq'))
        if error:
            return

        cutlist = cutlists_management.get_best_cutlist(cutlists)
        cutlist.download(self.app.config.get('general', 'server'), filename)
        cutlist.read_cuts()

        # delete cutlist?
        if self.app.config.get('general', 'delete_cutlists'):
            fileoperations.remove_file(cutlist.local_filename)

        # make mplayer edl
        # http://www.mplayerhq.hu/DOCS/HTML/en/edl.html
        # [Begin Second] [End Second] [0=Skip/1=Mute]
        edl_filename = os.path.join(
            self.app.config.get('general', 'folder_uncut_avis'), ".tmp.edl")
        f = open(edl_filename, "w")

        f.write("0 %s 0\n" % (cutlist.cuts_seconds[0][0] - 1))

        for count, (start, duration) in enumerate(cutlist.cuts_seconds):
            end = start + duration
            if count + 1 == len(cutlist.cuts_seconds):
                f.write("%s 50000 0\n" % (end))
            else:
                f.write("%s %s 0\n" %
                        (end, (cutlist.cuts_seconds[count + 1][0] - 1)))
        f.close()

        # make mpv edl
        # https://github.com/mpv-player/mpv-player.github.io/blob/master/guides/edl-playlists.rst
        edlurl = "edl://"

        for count, (start, duration) in enumerate(cutlist.cuts_seconds):
            edlurl = edlurl + filename + "," + str(start) + "," + str(
                duration) + ";"

        def check_prog(prog):
            cmdfound = False
            plays = False

            if shutil.which(prog):
                cmdfound = True
                if not subprocess.call(prog,
                                       stdin=subprocess.PIPE,
                                       stdout=subprocess.DEVNULL,
                                       stderr=subprocess.STDOUT):
                    plays = True
                else:
                    self.log.error("{} failed to start.".format(prog))
            else:
                exist = False
                self.log.error("{} is not installed.".format(prog))
            return cmdfound and plays

        def play_with(prog):
            if prog == 'mplayer':
                p = subprocess.Popen([
                    self.app.config.get_program('mplayer'), "-edl",
                    edl_filename, filename
                ])
            elif prog == 'mpv':
                p = subprocess.Popen(
                    [self.app.config.get_program('mpv'), edlurl])

        if self.app.config.get('general', 'prefer_mpv'):
            self.playprog = ['mpv', 'mplayer']
        else:
            self.playprog = ['mplayer', 'mpv']

        if check_prog(self.playprog[0]):
            play_with(self.playprog[0])
        elif check_prog(self.playprog[1]):
            play_with(self.playprog[1])
        else:
            self.gui.message_error_box("Zum Anzeigen der Schnitte sind weder mpv noch mplayer " + \
                                       "installiert bzw. funktionieren nicht.")
            return

        while p.poll() == None:
            time.sleep(1)
            while Gtk.events_pending():
                Gtk.main_iteration()

        fileoperations.remove_file(edl_filename)
Ejemplo n.º 20
0
class DecodeOrCut(BaseAction):

    def __init__(self, app, gui):
        self.update_list = True
        self.__app = app
        self.config = app.config
        self.__gui = gui

    def do(self, action, filenames, cut_action=None):
        self.rename_by_schema = self.__app.rename_by_schema

        decode, cut = False, False

        # prepare tasks
        if action == Action.DECODE:
            self.__gui.main_window.set_tasks_text('Dekodieren')
            decode = True
        elif action == Action.CUT:
            self.__gui.main_window.set_tasks_text('Schneiden')
            cut = True
        else: # decode and cut
            self.__gui.main_window.set_tasks_text('Dekodieren/Schneiden')
            decode, cut = True, True

        file_conclusions = []

        if decode:
            for otrkey in filenames:
                file_conclusions.append(FileConclusion(action, otrkey=otrkey))

        if cut and not decode: # dont add twice
            for uncut_video in filenames:
                file_conclusions.append(FileConclusion(action, uncut_video=uncut_video))

        # decode files
        if decode:
            if self.decode(file_conclusions) == False:
                return

        # cut files
        if cut:
            if self.cut(file_conclusions, action, cut_action) == False:
                return

        self.__gui.main_window.block_gui(False)

        # no more need for tasks view
        self.__gui.main_window.set_tasks_visible(False)

        show_conclusions = False
        # Only cut - don't show conclusions if all were cancelled
        if action == Action.CUT:
            for conclusion in file_conclusions:
                if conclusion.cut.status != Status.NOT_DONE:
                    show_conclusions = True
                    break

        # Only decode - don't show if everything is OK
        elif action == Action.DECODE:
            for conclusion in file_conclusions:
                if conclusion.decode.status != Status.OK:
                    show_conclusions = True

            if not show_conclusions:
                self.__app.gui.main_window.change_status(0, "%i Datei(en) erfolgreich dekodiert" % len(file_conclusions), permanent=True)

        # Decode and cut - always show
        else:
            show_conclusions = True

        if show_conclusions:
            self.__app.conclusions_manager.add_conclusions(*file_conclusions)

    def decode(self, file_conclusions):

        # no decoder
        if not "decode" in self.config.get('general', 'decoder'): # no decoder specified
            # dialog box: no decoder
            self.__gui.message_error_box("Es ist kein korrekter Dekoder angegeben!")
            return False

        # retrieve email and password
        email = self.config.get('general', 'email')
        password = base64.b64decode(self.config.get('general', 'password'))

        if not email or not password:
            self.__gui.dialog_email_password.set_email_password(email, password)

            # let the user type in his data through a dialog
            response = self.__gui.dialog_email_password.run()
            self.__gui.dialog_email_password.hide()

            if response == RESPONSE_OK:
                email, password = self.__gui.dialog_email_password.get_email_password()
            else: # user pressed cancel
                return False

        # now this method may not return "False"
        self.__gui.main_window.set_tasks_visible(True)
        self.__gui.main_window.block_gui(True)

        # decode each file
        for count, file_conclusion in enumerate(file_conclusions):
            # update progress
            self.__gui.main_window.set_tasks_text("Datei %s/%s dekodieren" % (count + 1, len(file_conclusions)))

            verify = True

            command = [self.config.get('general', 'decoder'), "-i", file_conclusion.otrkey, "-e", email, "-p", password, "-o", self.config.get('general', 'folder_uncut_avis')]

            if not self.config.get('general', 'verify_decoded'):
                verify = False
                command += ["-q"]

            try:
                process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            except OSError:
                file_conclusion.decode.status = Status.ERROR
                file_conclusion.decode.message = "Dekoder wurde nicht gefunden."
                continue

            while True:
                l = ""
                while True:
                    c = process.stdout.read(1)
                    if c == "\r" or c == "\n":
                        break
                    l += c

                if not l:
                    break

                try:
                    if verify:
                        file_count = count + 1, len(file_conclusions)

                        if "input" in l:
                            self.__gui.main_window.set_tasks_text("Eingabedatei %s/%s kontrollieren" % file_count)
                        elif "output" in l:
                            self.__gui.main_window.set_tasks_text("Ausgabedatei %s/%s kontrollieren" % file_count)
                        elif "Decoding" in l:
                            self.__gui.main_window.set_tasks_text("Datei %s/%s dekodieren" % file_count)

                    progress = int(l[10:13])
                    # update progress
                    self.__gui.main_window.set_tasks_progress(progress)

                    while events_pending():
                        main_iteration(False)
                except ValueError:
                    pass

            # errors?
            errors = process.stderr.readlines()
            error_message = ""
            for error in errors:
                error_message += error.strip()

            if len(errors) == 0: # dekodieren erfolgreich
                file_conclusion.decode.status = Status.OK

                file_conclusion.uncut_video = join(self.config.get('general', 'folder_uncut_avis'), basename(file_conclusion.otrkey[0:len(file_conclusion.otrkey)-7]))

                # move otrkey to trash
                target = self.config.get('general', 'folder_trash_otrkeys')
                fileoperations.move_file(file_conclusion.otrkey, target)
            else:
                file_conclusion.decode.status = Status.ERROR

                try:
                    unicode(error_message)
                except UnicodeDecodeError:
                    error_message = unicode(error_message, 'iso-8859-1')

                file_conclusion.decode.message = error_message

        return True

    def cut(self, file_conclusions, action, default_cut_action=None):
        # now this method may not return "False"
        self.__gui.main_window.set_tasks_visible(True)
        self.__gui.main_window.block_gui(True)

        if not default_cut_action:
            default_cut_action = self.config.get('general', 'cut_action')

        for count, file_conclusion in enumerate(file_conclusions):
            self.__gui.main_window.set_tasks_text("Cutlist %s/%s wählen" % (count + 1, len(file_conclusions)))
            self.__gui.main_window.set_tasks_progress((count + 1) / float(len(file_conclusions)) * 100)

            # file correctly decoded?
            if action == Action.DECODEANDCUT:
                if file_conclusion.decode.status != Status.OK:
                    file_conclusion.cut.status = Status.NOT_DONE
                    file_conclusion.cut.message = "Datei wurde nicht dekodiert."
                    continue

            file_conclusion.cut.cut_action = default_cut_action

            if default_cut_action in [Cut_action.ASK, Cut_action.CHOOSE_CUTLIST]:
                # show dialog
                self.__gui.dialog_cut.setup(
                    file_conclusion.uncut_video,
                    self.config.get('general', 'folder_cut_avis'),
                    default_cut_action == Cut_action.ASK)

                cutlists = []
                self.cutlists_error = False

                def error_cb(error):
                    self.__gui.dialog_cut.builder.get_object('label_status').set_markup("<b>%s</b>" % error)
                    self.cutlists_error = True

                def cutlist_found_cb(cutlist):
                    self.__gui.dialog_cut.add_cutlist(cutlist)
                    cutlists.append(cutlist)

                def completed():
                    if not self.cutlists_error:
                        self.__gui.dialog_cut.builder.get_object('label_status').set_markup("")

                GeneratorTask(cutlists_management.download_cutlists, None, completed).start(file_conclusion.uncut_video, self.config.get('general', 'server'), self.config.get('general', 'choose_cutlists_by'), self.config.get('general', 'cutlist_mp4_as_hq'), error_cb, cutlist_found_cb)

                response = self.__gui.dialog_cut.run()
                self.__gui.dialog_cut.hide()

                if response < 0:
                    file_conclusion.cut.status = Status.NOT_DONE
                    file_conclusion.cut.message = "Abgebrochen."
                else:  # change cut_action accordingly
                    file_conclusion.cut.cut_action = response

            if file_conclusion.cut.cut_action == Cut_action.MANUALLY: # MANUALLY
                error_message, cuts, executable = self.cut_file_manually(file_conclusion.uncut_video)

                if not error_message:
                    file_conclusion.cut.create_cutlist = True
                    file_conclusion.cut.cutlist.cuts_frames = cuts
                    file_conclusion.cut.cutlist.intended_app = basename(executable)
                    file_conclusion.cut.cutlist.usercomment = 'Mit OTR-Verwaltung geschnitten'

                    fps, error = self.__get_fps(file_conclusion.uncut_video)
                    if not error:
                        file_conclusion.cut.cutlist.fps = fps
                    else:
                        file_conclusion.cut.cutlist.fps = 25.
                        print "Achtung! Möglicherweise wurde eine falsche Fps-Anzahl eingetragen! (%s)" % error
                    # calculate seconds
                    for start_frame, duration_frames in cuts:
                        file_conclusion.cut.cutlist.cuts_seconds.append((start_frame / fps, duration_frames / fps))
                else:
                    file_conclusion.cut.status = Status.ERROR
                    file_conclusion.cut.message = error_message

            elif file_conclusion.cut.cut_action == Cut_action.BEST_CUTLIST:
                error, cutlists = cutlists_management.download_cutlists(file_conclusion.uncut_video, self.config.get('general', 'server'), self.config.get('general', 'choose_cutlists_by'), self.config.get('general', 'cutlist_mp4_as_hq'))

                if error:
                    file_conclusion.cut.status = Status.ERROR
                    file_conclusion.cut.message = error
                    continue

                if len(cutlists) == 0:
                    file_conclusion.cut.status = Status.NOT_DONE
                    file_conclusion.cut.message = "Keine Cutlist gefunden."
                    continue

                file_conclusion.cut.cutlist = cutlists_management.get_best_cutlist(cutlists)

            elif file_conclusion.cut.cut_action == Cut_action.CHOOSE_CUTLIST:
                file_conclusion.cut.cutlist = self.__gui.dialog_cut.chosen_cutlist

            elif file_conclusion.cut.cut_action == Cut_action.LOCAL_CUTLIST:
                file_conclusion.cut.cutlist.local_filename = file_conclusion.uncut_video + ".cutlist"

                if not exists(file_conclusion.cut.cutlist.local_filename):
                    file_conclusion.cut.status = Status.ERROR
                    file_conclusion.cut.message = "Keine lokale Cutlist gefunden."

        # and finally cut the file
        for count, file_conclusion in enumerate(file_conclusions):

            if file_conclusion.cut.status in [Status.NOT_DONE, Status.ERROR]:
                continue

            print "[Decodeandcut] Datei %s wird geschnitten" % file_conclusion.uncut_video
            self.__gui.main_window.set_tasks_text("Datei %s/%s schneiden" % (count + 1, len(file_conclusions)))
            self.__gui.main_window.set_tasks_progress(0.5)

            # download cutlist
            if file_conclusion.cut.cut_action in [Cut_action.BEST_CUTLIST, Cut_action.CHOOSE_CUTLIST]:
                file_conclusion.cut.cutlist.download(self.config.get('general', 'server'), file_conclusion.uncut_video)

            cut_video, error = self.cut_file_by_cutlist(file_conclusion.uncut_video, file_conclusion.cut.cutlist)

            if cut_video == None:
                file_conclusion.cut.status = Status.ERROR
                file_conclusion.cut.message = error
            else:
                file_conclusion.cut.status = Status.OK
                file_conclusion.cut_video = cut_video

                if self.config.get('general', 'rename_cut'):
                    file_conclusion.cut.rename = self.rename_by_schema(basename(file_conclusion.uncut_video))
                else:
                    file_conclusion.cut.rename = basename(cut_video)

        return True

    def __get_format(self, filename):
        root, extension = splitext(filename)

        if extension == '.avi':
            if splitext(root)[1] == '.HQ':
                return Format.HQ
            elif splitext(root)[1] == '.HD':
                return Format.HD
            else:
                return Format.AVI
        elif extension == '.mp4':
            return Format.MP4
        else:
            return -1

    def __get_program(self, filename, manually=False):
        if manually:
            programs = { Format.AVI : self.config.get('general', 'cut_avis_man_by'),
                         Format.HQ  : self.config.get('general', 'cut_hqs_man_by'),
                         Format.HD  : self.config.get('general', 'cut_hqs_man_by'),
                         Format.MP4 : self.config.get('general', 'cut_mp4s_man_by') }
        else:
            programs = { Format.AVI : self.config.get('general', 'cut_avis_by'),
                         Format.HQ  : self.config.get('general', 'cut_hqs_by'),
                         Format.HD  : self.config.get('general', 'cut_hqs_by'),
                         Format.MP4 : self.config.get('general', 'cut_mp4s_by') }

        format = self.__get_format(filename)

        if format < 0:
            return -1, "Format konnte nicht bestimmt werden/wird noch nicht unterstützt."

        config_value = programs[format]

        if 'avidemux' in config_value:
            return Program.AVIDEMUX, config_value
        elif 'vdub' in config_value or 'VirtualDub' in config_value:
            return Program.VIRTUALDUB, config_value
        else:
            return -2, "Programm '%s' konnte nicht bestimmt werden. Es werden VirtualDub und Avidemux unterstützt." % config_value

    def __generate_filename(self, filename):
        """ generate filename for a cut video file. """

        root, extension = splitext(basename(filename))

        new_name = root + "-cut" + extension

        cut_video = join(self.config.get('general', 'folder_cut_avis'), new_name)

        return cut_video

    def __get_fps(self, filename):
        """ Gets the fps of a movie using mplayer.
            Returns without error:
                       fps, None
                    with error:
                       None, error_message """

        mplayer = self.config.get('general', 'mplayer')

        if not mplayer:
            return None, "Der Mplayer ist nicht angegeben. Dieser wird zur Bestimmung der FPS benötigt."

        try:
            process = subprocess.Popen([mplayer, "-vo", "null", "-frames", "1", "-nosound", filename], stdout=subprocess.PIPE)
        except OSError:
            return None, "MPlayer wurde nicht gefunden!"

        stdout = process.communicate()[0]

        for line in stdout.split('\n'):
            if "VIDEO" in line:
                try:
                    return float(line.split()[2]), None
                except:
                    return None, "FPS konnte nicht bestimmt werden " + line

        return None, "FPS konnte nicht bestimmt werden."


    def __get_aspect_ratio(self, filename):
        """ Gets the aspect ratio of a movie using mplayer.
            Returns without error:
                       aspect_ratio, None
                    with error:
                       None, error_message """
        mplayer = self.config.get('general', 'mplayer')

        if not mplayer:
            return None, "Der Mplayer ist nicht angegeben. Dieser wird zur Bestimmung der Aspekt Ratio benötigt."

        try:
            process = subprocess.Popen([mplayer, "-vo", "null", "-frames", "1", "-nosound", filename], stdout=subprocess.PIPE)
        except OSError:
            return None, "MPlayer wurde nicht gefunden!"

        stdout = process.communicate()[0]

        for line in stdout.split('\n'):
            if "Aspe" in line:
                if "1.78:1" in line or "0.56:1" in line:
                    return "16:9", None
                elif "1.33:1" in line or "0.75:1" in line:
                    return "4:3", None
                else:
                    return None, "Aspekt konnte nicht bestimmt werden " + line

        return None, "Aspekt Ratio konnte nicht bestimmt werden."

    def __create_cutlist_virtualdub(self, filename):
        """ returns: cuts, error_message """

        try:
            f = open(filename, 'r')
        except IOError:
            return None, "Die VirtualDub-Projektdatei konnte nicht gelesen werden.\nWurde das Projekt in VirtualDub nicht gespeichert?\n(Datei: %s)." % filename

        cuts_frames = [] # (start, duration)
        count = 0

        for line in f.readlines():
            if "VirtualDub.subset.AddRange" in line:
                try:
                    start, duration = line[line.index('(') + 1 : line.index(')')].split(',')
                except (IndexError, ValueError), message:
                    return None, "Konnte Schnitte nicht lesen, um Cutlist zu erstellen. (%s)" % message

                cuts_frames.append((int(start), int(duration)))

        if len(cuts_frames) == 0:
            return None, "Konnte keine Schnitte finden!"

        fileoperations.remove_file(filename)

        return cuts_frames, None
Ejemplo n.º 21
0
    def __cut_file_avidemux(self, filename, program_config_value, cuts):
        format, ac3_file, bframe_delay = self.get_format(filename)
        # make file for avidemux2.5 scripting engine
        f = open("tmp.js", "w")

        f.writelines([
            '//AD\n',
            'var app = new Avidemux();\n',
            '\n'
            '//** Video **\n',
            'app.load("%s");\n' % filename,
            '\n',
            'app.clearSegments();\n'
            ])

        for frame_start, frames_duration in cuts:
            if format == Format.HQ or format == Format.HD:
                #2-Frame-Delay for HQ,HD Format
                f.write("app.addSegment(0, %i, %i);\n" %(frame_start+2, frames_duration))
            else:
                f.write("app.addSegment(0, %i, %i);\n" %(frame_start, frames_duration))

        cut_video = self.generate_filename(filename)

        f.writelines([
            '//** Postproc **\n',
            'app.video.setPostProc(3,3,0);\n'
            ])

        if self.config.get('general', 'smart'):
            f.write('app.video.codec("Copy","CQ=4","0");\n')

        f.writelines([
            '//** Audio **\n',
            'app.audio.reset();\n',
            'app.audio.codec("copy",128,0,"");\n',
            'app.audio.normalizeMode=0;\n',
            'app.audio.normalizeValue=0;\n',
            'app.audio.delay=0;\n',
            'app.audio.mixer="NONE";\n',
            'app.audio.scanVBR="";\n',
            'app.setContainer="AVI";\n',
            'setSuccess(app.save("%s"));\n' % cut_video
            ])

        f.close()

        # start avidemux:
        try:
            avidemux = subprocess.Popen([program_config_value, "--nogui", "--force-smart", "--run", "tmp.js", "--quit"], stderr=subprocess.PIPE)
        except OSError:
            return None, "Avidemux konnte nicht aufgerufen werden: " + program_config_value

        self.gui.main_window.set_tasks_progress(50)

        while avidemux.poll() == None:
            time.sleep(1)
#            TODO: make it happen
#            line = avidemux.stderr.readline()
#
#            if "Done:" in line:
#                progress = line[line.find(":") + 1 : line.find("%")]
#                self.gui.main_window.set_tasks_progress(int(progress))
#
            while events_pending():
                main_iteration(False)

        fileoperations.remove_file('tmp.js')

        return cut_video, None
Ejemplo n.º 22
0
    def create_cutlist(self, filename, program_config_value):
        """ read cuts from avidemux 2 and 3
            returns cut_frames und cutlist_error """

        format, ac3_file = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)
        if fps == None:
            return None, error

        # env
        my_env = os.environ.copy()
        my_env["LANG"] = "C"
        my_env["LC_COLLATE"] = "C"

        if ".avi" in filename and "avidemux3" in program_config_value:
            try:
                mkvmerge = subprocess.Popen(
                    [self.config.get_program("mkvmerge"), "--ui-language", "en_US", "-o", filename + ".mkv", filename],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT,
                    universal_newlines=True,
                    env=my_env,
                )
                self.show_progress(mkvmerge)
                returncode = mkvmerge.wait()
                if returncode != 0 and returncode != 1:
                    return None, "Fehler beim Muxen zu MKV"
            except:
                return None, "mkvmerge konnte nicht aufgerufen werden."

        try:
            if os.path.isfile(filename + ".mkv"):
                avidemux = subprocess.Popen(
                    [program_config_value, filename + ".mkv"], bufsize=-1, stdout=subprocess.PIPE
                )
            else:
                avidemux = subprocess.Popen([program_config_value, filename], bufsize=-1, stdout=subprocess.PIPE)
        except:
            if os.path.isfile(filename + ".mkv"):
                fileoperations.remove_file(filename + ".mkv")
            return None, "Avidemux konnte nicht aufgerufen werden: " + program_config_value

        seg_lines = []
        pts_correction = 0

        for line in avidemux.stdout.readlines():
            if line.startswith(" Seg"):
                # delete not interesting parts
                line = line[: line.find("audio")]

                parts = line.split(",")

                seg_id = int(parts[0].split(":")[-1])
                if format == Format.HQ or format == Format.HD:
                    start = int(parts[1].split(":")[-1]) - 2
                else:
                    start = int(parts[1].split(":")[-1])
                size = int(parts[2].split(":")[-1])
                seg_lines.append((seg_id, start, size))

            # Avidemux3
            # The first frame has a PTS >0, adjusting to 40 ms
            elif "[addReferenceVideo]  The first frame has a PTS >0" in line:
                pts_correction = float(line.split(" ")[13]) * 1000
            elif line.startswith(" We have "):
                seg_lines = []
            elif line.startswith("Segment :"):
                line = line[line.find(":") + 1 :]
                seg_id = int(line.split("/")[0])
            elif "duration     :" in line:
                line = line[line.find(":") + 1 :]
                size = (float(line.split(" ")[0])) * fps / 1000000
            elif "refStartPts  :" in line:
                line = line[line.find(":") + 1 :]
                start = (float(line.split(" ")[0]) - pts_correction) * fps / 1000000
                if start > 0:
                    seg_lines.append((seg_id, start, size))
                else:
                    # correct values for first keyframe
                    seg_lines.append((seg_id, 0.0, size - fps * pts_correction / 1000000))
            else:
                pass

        # keep only necessary items
        seg_lines.reverse()
        temp_cuts = []

        for seg_id, start, duration in seg_lines:
            if seg_id == 0:
                temp_cuts.append((start, duration))
                break
            else:
                temp_cuts.append((start, duration))

        temp_cuts.reverse()

        cuts_frames = []
        count = 0
        for start, duration in temp_cuts:
            cuts_frames.append((start, duration))
            count += 1

        if os.path.isfile(filename + ".mkv"):
            fileoperations.remove_file(filename + ".mkv")

        if len(cuts_frames) == 0:
            cutlist_error = "Es wurde nicht geschnitten."
        else:
            cutlist_error = None

        return cuts_frames, cutlist_error
Ejemplo n.º 23
0
        def mp4():
            # env
            my_env = os.environ.copy()
            my_env["LANG"] = "C"

            for count, filename in enumerate(filenames):
                # analyse file
                cutter = Cut(self.app, self.gui)
                fps, dar, sar, max_frames, ac3_stream, error = cutter.analyse_mediafile(filename)
                if fps == None:
                    self.errors[filename] = error
                    continue

                # mkvmerge pass
                yield 0, count
                self.progress = 0

                if os.path.splitext(filename)[1] != ".mkv":

                    mkvpass_file = fileoperations.make_unique_filename(os.path.splitext(filename)[0] + "_remux.mkv")
                    try:
                        p = subprocess.Popen(
                            [
                                self.app.config.get_program("mkvmerge"),
                                "--ui-language",
                                "en_US",
                                "-o",
                                mkvpass_file,
                                filename,
                            ],
                            stdout=subprocess.PIPE,
                            env=my_env,
                        )
                    except OSError:
                        self.errors[filename] = "MKVmerge wurde nicht gefunden!"
                        continue

                    p.stdout.readline()
                    line = ""

                    while p.poll() == None:
                        # read progress from stdout
                        char = p.stdout.read(1)
                        line += char
                        progress = ""
                        if char == ":":
                            if "Error" in line or "Warning" in line:
                                break

                            while char != "%":
                                char = p.stdout.read(1)
                                progress += char

                            try:
                                self.progress = int(progress.strip(" %"))
                                yield 4, self.progress
                            except ValueError:
                                pass

                    exit_code = p.poll()

                    if exit_code == 0 or exit_code == 1:
                        pass
                    else:
                        error = p.stdout.readline()
                        if os.path.exists(mkvpass_file):
                            fileoperations.remove_file(mkvpass_file)
                        try:
                            error = error.split(":")[1]
                        except IndexError:
                            pass

                        if "unknown type" in error:
                            error = "Datei konnte nicht gelesen werden."
                        self.errors[filename] = error
                        continue
                else:
                    mkvpass_file = filename

                # norm volume ausrechnen
                yield 5, count
                if self.Config["NormalizeAudio"] and self.Config["EncodeAudioToAAC"]:
                    vol, error = self.get_norm_volume(filename)
                else:
                    vol = 1.0

                # ffmpeg pass
                yield 1, count
                self.progress = 0
                ffmpegpass_file = fileoperations.make_unique_filename(os.path.splitext(filename)[0] + "_remux.mp4")

                if self.Config["EncodeAudioToAAC"]:
                    if self.Config["EncodeOnlyFirstAudioToAAC"]:
                        aacaudiostreams = "-c:a:0"
                    else:
                        aacaudiostreams = "-c:a"

                    # convert first audio stream to aac
                    ffmpeg = self.app.config.get_program("ffmpeg")
                    if "nonfree" in ffmpeg:
                        # nonfree ffmpeg version with fdk support available
                        audiocodec = [
                            "-c:a",
                            "copy",
                            aacaudiostreams,
                            "libfdk_aac",
                            "-flags",
                            "+qscale",
                            "-profile:a:0",
                            "aac_low",
                            "-global_quality",
                            "5",
                            "-afterburner",
                            "1",
                        ]
                    else:
                        # only gpl version of ffmpeg available -> use standard aac codec
                        audiocodec = [
                            "-c:a",
                            "copy",
                            aacaudiostreams,
                            "aac",
                            "-strict",
                            "-2",
                            "-profile:a:0",
                            "aac_low",
                            "-ab",
                            "192k",
                            "-cutoff",
                            "18000",
                        ]
                else:
                    # only copy audio
                    ffmpeg = path.get_tools_path("intern-ffmpeg")
                    audiocodec = ["-c:a", "copy"]

                if self.Config["DownMixStereo"] and self.Config["EncodeAudioToAAC"]:
                    audiocodec.extend(["-ac:0", "2"])

                if ac3_stream == None:
                    # no ac3 stream found - all streams are muxed
                    map = ["-map", "0"]
                else:
                    if self.Config["RemoveOtherAudioStreamsThanAC3"]:
                        # mux only video and ac3 stream
                        map = ["-map", "0:v", "-map", ac3_stream]
                    else:
                        map = ["-map", "0"]

                args = [
                    ffmpeg,
                    "-loglevel",
                    "info",
                    "-y",
                    "-drc_scale",
                    "1.0",
                    "-i",
                    mkvpass_file,
                    "-vcodec",
                    "copy",
                    "-af",
                    "volume=volume=" + str(vol),
                    "-vsync",
                    "1",
                    "-async",
                    "1000",
                    "-dts_delta_threshold",
                    "100",
                    "-vf",
                    "fps=" + str(fps),
                    ffmpegpass_file,
                ]
                map.extend(audiocodec)
                args[8:8] = map

                try:
                    p = subprocess.Popen(args, stderr=subprocess.PIPE, universal_newlines=True)
                except OSError:
                    self.errors[filename] = "FFMPEG (intern) wurde nicht gefunden!"
                    if os.path.exists(mkvpass_file) and filename != mkvpass_file:
                        fileoperations.remove_file(mkvpass_file)
                    continue

                yield 4, 0
                line = ""
                infos_match = re.compile(r"frame=\ {0,1}(\d{1,})")

                while p.poll() == None:
                    line = p.stderr.readline()
                    m = re.search(infos_match, line)
                    if m and max_frames != 0:
                        next = float(float(m.group(1)) / float(max_frames)) * 100
                        if next > self.progress:
                            self.progress = next
                            yield 4, self.progress
                    else:
                        pass

                exit_code = p.poll()
                if os.path.exists(mkvpass_file) and filename != mkvpass_file:
                    fileoperations.remove_file(mkvpass_file)

                if exit_code == 0:
                    if self.Config["DumpAVIs"]:
                        yield 3, self.success
                        new_filename = os.path.join(
                            self.app.config.get("general", "folder_trash_avis"), os.path.basename(filename)
                        )
                        if os.path.exists(new_filename):
                            fileoperations.remove_file(new_filename)
                        fileoperations.move_file(filename, self.app.config.get("general", "folder_trash_avis"))
                else:
                    self.errors[filename] = "Fehler beim Erzeugen der MP4 Datei durch FFMPEG"
                    if os.path.exists(ffmpegpass_file):
                        fileoperations.remove_file(ffmpegpass_file)
                    continue

                # mp4box - last turn
                self.progress = 0
                mp4boxpass_file = fileoperations.make_unique_filename(os.path.splitext(filename)[0] + ".mp4")

                if self.Config["DontOptimizeMP4"]:
                    os.rename(ffmpegpass_file, mp4boxpass_file)
                    self.success += 1
                    continue

                yield 2, count
                try:
                    p = subprocess.Popen(
                        [
                            self.app.config.get_program("mp4box"),
                            "-keep-all",
                            "-new",
                            "-packed",
                            "-fps",
                            str(fps),
                            "-add",
                            ffmpegpass_file,
                            mp4boxpass_file,
                        ],
                        stdout=subprocess.PIPE,
                        stderr=subprocess.STDOUT,
                    )
                except OSError:
                    self.errors[filename] = "MP4Box (intern) wurde nicht gefunden!"
                    if os.path.exists(ffmpegpass_file):
                        fileoperations.remove_file(ffmpegpass_file)
                    continue

                yield 4, 0
                infos_match = re.compile(r".*\((\d{2,})\/\d{2,}\).*")

                while p.poll() == None:
                    line = p.stdout.read(60)
                    m = re.search(infos_match, line)
                    if m:
                        self.progress = int(m.group(1))
                        yield 4, self.progress

                        if "Importing" in line:
                            yield 2, count
                        elif "Writing" in line:
                            yield 6, count
                    else:
                        pass

                exit_code = p.poll()
                if os.path.exists(ffmpegpass_file):
                    fileoperations.remove_file(ffmpegpass_file)

                if exit_code == 0:
                    self.success += 1
                else:
                    self.errors[filename] = "Fehler beim Erzeugen der MP4 Datei durch MP4Box"
Ejemplo n.º 24
0
    def create_cutlist(self, filename, program_config_value):
        """ read cuts from avidemux 2 and 3
            returns cut_frames und cutlist_error """

        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(
            filename)
        if fps == None:
            return None, error

        # env
        my_env = os.environ.copy()
        my_env["LANG"] = "C"
        my_env["LC_COLLATE"] = "C"

        if '.avi' in filename and "avidemux3" in program_config_value:
            try:
                mkvmerge = subprocess.Popen([
                    self.config.get_program('mkvmerge'), '--ui-language',
                    'en_US', '-o', filename + '.mkv', filename
                ],
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.STDOUT,
                                            universal_newlines=True,
                                            env=my_env)
                self.show_progress(mkvmerge)
                returncode = mkvmerge.wait()
                if returncode != 0 and returncode != 1:
                    return None, 'Fehler beim Muxen zu MKV'
            except:
                return None, "mkvmerge konnte nicht aufgerufen werden."

        try:
            if os.path.isfile(filename + '.mkv'):
                avidemux = subprocess.Popen(
                    [program_config_value, filename + '.mkv'],
                    bufsize=-1,
                    stdout=subprocess.PIPE)
            else:
                avidemux = subprocess.Popen([program_config_value, filename],
                                            bufsize=-1,
                                            stdout=subprocess.PIPE)
        except:
            if os.path.isfile(filename + '.mkv'):
                fileoperations.remove_file(filename + '.mkv')
            return None, "Avidemux konnte nicht aufgerufen werden: " + program_config_value

        seg_lines = []
        pts_correction = 0

        # Avidemux3
        if "avidemux3" in program_config_value:
            for line in avidemux.stdout.readlines():
                # [addReferenceVideo]  The first frame has a PTS >0, adjusting to 120 ms
                m_pts = re.search(
                    '\\[addReferenceVideo\\]  The first frame has a PTS >0.*?(\\d+)',
                    line)
                if m_pts:
                    pts_correction = float(m_pts.group(1)) * 1000
                    continue
                #Segment :0/1
                m_seg = re.search('Segment :(\\d+)', line)
                if m_seg:
                    seg_id = int(m_seg.group(1))
                    if seg_id == 0:
                        seg_lines = []
                    continue
                #        duration     :10671440000 02:57:51,440
                m_dur = re.search(' *?duration *?:(\\d+)', line)
                if m_dur:
                    size = float(m_dur.group(1)) * fps / 1000000
                    continue
                #        refStartPts  :15740000 00:00:15,740
                m_start = re.search(' *?refStartPts *?:(\\d+)', line)
                if m_start:
                    start = (float(m_start.group(1)) -
                             pts_correction) * fps / 1000000
                    if start > 0:
                        seg_lines.append((seg_id, start, size))
                    else:
                        # correct values for first keyframe
                        seg_lines.append(
                            (seg_id, 0.0,
                             size - fps * pts_correction / 1000000))
                    continue
        else:
            #avidemux2
            for line in avidemux.stdout.readlines():
                if line.startswith(' Seg'):
                    # delete not interesting parts
                    line = line[:line.find("audio")]

                    parts = line.split(',')

                    seg_id = int(parts[0].split(':')[-1])
                    if format == Format.HQ or format == Format.HD:
                        start = int(parts[1].split(':')[-1]) - 2
                    else:
                        start = int(parts[1].split(':')[-1])
                    size = int(parts[2].split(':')[-1])
                    seg_lines.append((seg_id, start, size))
                else:
                    pass

        # keep only necessary items
        seg_lines.reverse()
        temp_cuts = []

        for seg_id, start, duration in seg_lines:
            if seg_id == 0:
                temp_cuts.append((start, duration))
                break
            else:
                temp_cuts.append((start, duration))

        temp_cuts.reverse()

        cuts_frames = []
        count = 0
        for start, duration in temp_cuts:
            cuts_frames.append((start, duration))
            count += 1

        if os.path.isfile(filename + '.mkv'):
            fileoperations.remove_file(filename + '.mkv')

        if len(cuts_frames) == 0:
            cutlist_error = "Es wurde nicht geschnitten."
        else:
            cutlist_error = None

        return cuts_frames, cutlist_error
Ejemplo n.º 25
0
    def __cut_file_avidemux(self, filename, program_config_value, cuts):
        format, ac3_file, bframe_delay = self.get_format(filename)
        # make file for avidemux2.5 scripting engine
        f = open("tmp.js", "w")

        f.writelines([
            '//AD\n', 'var app = new Avidemux();\n', '\n'
            '//** Video **\n',
            'app.load("%s");\n' % filename, '\n', 'app.clearSegments();\n'
        ])

        for frame_start, frames_duration in cuts:
            if format == Format.HQ or format == Format.HD:
                #2-Frame-Delay for HQ,HD Format
                f.write("app.addSegment(0, %i, %i);\n" %
                        (frame_start + 2, frames_duration))
            else:
                f.write("app.addSegment(0, %i, %i);\n" %
                        (frame_start, frames_duration))

        cut_video = self.generate_filename(filename)

        f.writelines(['//** Postproc **\n', 'app.video.setPostProc(3,3,0);\n'])

        if self.config.get('general', 'smart'):
            f.write('app.video.codec("Copy","CQ=4","0");\n')

        f.writelines([
            '//** Audio **\n', 'app.audio.reset();\n',
            'app.audio.codec("copy",128,0,"");\n',
            'app.audio.normalizeMode=0;\n', 'app.audio.normalizeValue=0;\n',
            'app.audio.delay=0;\n', 'app.audio.mixer="NONE";\n',
            'app.audio.scanVBR="";\n', 'app.setContainer="AVI";\n',
            'setSuccess(app.save("%s"));\n' % cut_video
        ])

        f.close()

        # start avidemux:
        try:
            avidemux = subprocess.Popen([
                program_config_value, "--nogui", "--force-smart", "--run",
                "tmp.js", "--quit"
            ],
                                        stderr=subprocess.PIPE)
        except OSError:
            return None, "Avidemux konnte nicht aufgerufen werden: " + program_config_value

        self.gui.main_window.set_tasks_progress(50)

        while avidemux.poll() == None:
            time.sleep(1)
            #            TODO: make it happen
            #            line = avidemux.stderr.readline()
            #
            #            if "Done:" in line:
            #                progress = line[line.find(":") + 1 : line.find("%")]
            #                self.gui.main_window.set_tasks_progress(int(progress))
            #
            while events_pending():
                main_iteration(False)

        fileoperations.remove_file('tmp.js')

        return cut_video, None
Ejemplo n.º 26
0
    def _download(self):
        self.log = ''
        self.information['message_short'] = ''

        self.information['status'] = DownloadStatus.RUNNING

        if self.information['download_type'] == DownloadTypes.TORRENT:
            # download torrent if necessary
            torrent_filename = os.path.join(
                self._config.get('general', 'folder_new_otrkeys'),
                self.filename + '.torrent')
            if not os.path.exists(torrent_filename):
                url = 'http://81.95.11.2/torrents/' + self.filename + '.torrent'
                try:
                    request.urlretrieve(url, torrent_filename)
                    # read filename
                    f = open(torrent_filename, 'r')
                    line = f.readlines()[0]
                except IOError as error:
                    self.information['status'] = DownloadStatus.ERROR
                    self.information[
                        'message_short'] = 'Torrentdatei konnte nicht geladen werden.'
                    yield "Torrentdatei konnte nicht heruntergeladen werden (%s)!" % error
                    return

                if "Hash wrong" in line:
                    os.remove(torrent_filename)
                    self.information['status'] = DownloadStatus.ERROR
                    self.information[
                        'message_short'] = 'OTR-Daten nicht korrekt!'
                    yield 'OTR-Daten nicht korrekt!'
                    return

            self.information['output'] = self._config.get(
                'general', 'folder_new_otrkeys')
            command = [self._config.get_program('aria2c')] + self._config.get(
                'downloader', 'aria2c_opts_torrent') + [
                    "-d", self.information['output'], "-T", torrent_filename
                ]
            yield "Ausgeführt wird:\n%s\n" % " ".join(command)

            try:
                self.__process = subprocess.Popen(command,
                                                  stdout=subprocess.PIPE)
            except OSError as error:
                self.information['status'] = DownloadStatus.ERROR
                self.information[
                    'message_short'] = 'Aria2c ist nicht installiert.'
                yield "Ist aria2c installiert? Der Befehl konnte nicht ausgeführt werden:\nFehlermeldung: %s" % error
                return

            while self.__process.poll() == None:
                line = self.__process.stdout.readline().strip()

                if "Checksum" in line:
                    result = re.findall('Checksum:.*\((.*%)\)', line)
                    if result:
                        self.information[
                            'message_short'] = 'Überprüfen...%s' % result[0]

                elif "SEEDING" in line:
                    self.information['message_short'] = 'Seeden...'
                    self.information[
                        'status'] = DownloadStatus.SEEDING  # _NOT_ DownloadStatus.FINISHED
                    self.information['progress'] = 100
                    self.information['est'] = ''
                    self.information['speed'] = ''
                    self.information['seeders'] = None

                    result = re.findall('ratio:(.*)\) ', line)
                    if result:
                        self.information['ratio'] = result[0]

                    result = re.findall('UP:(.*)\((.*)\)', line)
                    if result:
                        self.information['upspeed'] = result[0][0]
                        self.information['uploaded'] = result[0][1]

                elif "%" in line:
                    self.information['message_short'] = ''
                    # get size
                    if not self.information['size']:
                        try:
                            # aria2c gives size always in MiB (hopefully)
                            size = re.findall('SIZE:.*/(.*)MiB\(', line)[0]
                            size = size.replace(',', '')
                            size = int(round(float(size))) * 1024 * 1024
                            self.information['size'] = size
                            yield line
                        except:
                            pass

                    # get progress
                    result = re.findall('([0-9]{1,3})%', line)
                    if result:
                        self.information['progress'] = int(result[0])

                    # get speed, est
                    if "UP" in line:
                        result = re.findall(
                            'SPD:(.*) UP:(.*)\((.*)\) ETA:(.*)]', line)
                        if result:
                            self.information['speed'] = result[0][0]
                            self.information['upspeed'] = result[0][1]
                            self.information['uploaded'] = result[0][2]
                            self.information['est'] = result[0][3]
                    else:
                        result = re.findall('SPD:(.*) .*ETA:(.*)]', line)
                        if result:
                            self.information['speed'] = result[0][0]
                            self.information['est'] = result[0][1]

                    # get seeder info
                    result = re.findall('SEED:([0-9]*) ', line)
                    if result:
                        self.information['seeders'] = result[0]
                else:
                    yield line
                self.update_view()

            ### Process is terminated
            stdout = self.__process.stdout.read().strip()
            yield stdout

            # A torrent download only stops:
            #   a) when the user clicks 'stop'
            #   b) when an error occured
            if self.information['status'] != DownloadStatus.STOPPED:
                self.information['status'] = DownloadStatus.ERROR

        elif self.information['download_type'] == DownloadTypes.BASIC:
            self.information['output'] = self._config.get(
                'general', 'folder_new_otrkeys')

            if self.information['preferred_downloader'] == 'wget':
                command = [
                    self._config.get_program('wget')
                ] + self._config.get('downloader', 'wget') + [
                    "-c", "-P", self.information['output'], self.link
                ]
                yield "Ausgeführt wird:\n%s\n" % " ".join(command)

                try:
                    self.__process = subprocess.Popen(command,
                                                      stderr=subprocess.PIPE)
                except OSError as error:
                    self.information['status'] = DownloadStatus.ERROR
                    self.information[
                        'message_short'] = 'Wget ist nicht installiert.'
                    yield "Ist Wget installiert? Der Befehl konnte nicht ausgeführt werden:\n%s" % error
                    return

                while True:
                    exit_code = self.__process.poll()
                    if exit_code != None:
                        if self.information['status'] != DownloadStatus.STOPPED:
                            if exit_code == 0:
                                self._finished()
                            else:
                                self.information[
                                    'status'] = DownloadStatus.ERROR
                        break

                    line = self.__process.stderr.readline().strip()

                    if line:
                        if not self.information['size']:
                            result = re.findall(': ([0-9]*) \(', line)
                            if result:
                                self.information['size'] = int(result[0])

                        if "%" in line:
                            result = re.findall('([0-9]{1,3})% (.*)[ =](.*)',
                                                line)

                            if result:
                                progress = int(result[0][0])
                                if self.information['progress'] == progress:
                                    continue
                                else:
                                    self.information['progress'] = progress

                                self.information['speed'] = result[0][1]

                                if progress == 100:
                                    self._finished()
                                else:
                                    self.information['est'] = result[0][2]

                        else:
                            yield line

                        self.update_view()

                ### Process is terminated
                yield self.__process.stderr.read().strip()

            else:
                # Download with aria2c
                self.information[
                    'message_short'] = 'Überprüfung der bereits heruntergeladen Datei ...'
                self.update_view()
                if 'otrkey' in self.filename and os.path.exists(
                        self.information['output'] + '/' + self.filename):
                    torrent_check_return = self._check_file_with_torrent()

                    if torrent_check_return == 0:
                        self.information[
                            'message_short'] = '(OK):Download vollständig.'
                        self._finished()

                command = [
                    self._config.get_program('aria2c')
                ] + self._config.get('downloader', 'aria2c_opts') + [
                    "-d", self.information['output'], '--retry-wait=30',
                    '--max-tries=0', '--summary-interval=5', '--log', '-',
                    '--log-level', 'info', self.link
                ]
                yield "Ausgeführt wird:\n%s\n" % " ".join(command)

                if self.information['status'] == DownloadStatus.RUNNING:
                    self.log = ''
                    self.information[
                        'message_short'] = 'Versuche Download zu starten ... eventuell erst Warteschlange durchlaufen ...'
                    self.update_view()

                    try:
                        self.__process = subprocess.Popen(
                            command, stdout=subprocess.PIPE)
                    except OSError as error:
                        self.information['status'] = DownloadStatus.ERROR
                        self.information[
                            'message_short'] = 'Aria2c ist nicht installiert.'
                        yield "Ist aria2c installiert? Der Befehl konnte nicht ausgeführt werden:\n%s" % error
                        return

                    while self.__process.poll() == None:
                        time.sleep(0.1)
                        line = self.__process.stdout.readline()

                        if 'X-OTR-Queueposition' in line or 'errorCode=29' in line:
                            match = re.search(
                                'X-OTR-Queueposition:\ ([0-9]{1,})', line)
                            if match:
                                self.information[
                                    'message_short'] = 'OTR Warteschlange - %s' % match.group(
                                        0)
                                self.update_view()
                            else:
                                if not 'OTR' in self.information[
                                        'message_short']:
                                    self.information[
                                        'message_short'] = line.strip()
                        elif 'X-OTR-Error-Message' in line:
                            self.information['message_short'] = line.strip()
                            self.update_view()
                        elif 'errorCode=' in line:
                            self.information['message_short'] = line.strip()
                            self.update_view()
                        elif "%" in line:
                            if "FileAlloc" in line:
                                result = re.findall(
                                    'FileAlloc:.*\(([0-9]{1,3}%)', line)
                                self.information[
                                    'message_short'] = 'Datei wird angelegt...%s' % result[
                                        0]
                            else:
                                self.information['message_short'] = ''

                            if not self.information['size']:
                                try:
                                    # aria2c gives size always in MiB (hopefully)
                                    size = re.findall('.*/(.*)\(',
                                                      line.strip())[0]
                                    size = size.strip('MiB')
                                    size = size.replace(',', '')
                                    size = int(round(
                                        float(size))) * 1024 * 1024
                                    self.information['size'] = size
                                    yield line
                                except:
                                    pass

                            result = re.findall(
                                '\(([0-9]{1,3})%\).*CN:([0-9]{1,5}).*DL:(.*) ETA:(.*)]',
                                line)

                            if result:
                                self.information['progress'] = int(
                                    result[0][0])
                                self.information[
                                    'message_short'] = 'Verbindungen: %s' % result[
                                        0][1]
                                self.information['speed'] = result[0][2]
                                self.information['est'] = result[0][3]
                                self.update_view()
                        else:
                            yield line.strip()

                    ### Process is terminated
                    stdout = self.__process.stdout.read().strip()
                    yield stdout
                    if not self.information['status'] in [
                            DownloadStatus.STOPPED, DownloadStatus.ERROR
                    ]:
                        time.sleep(1)  # wait for log being updated - very ugly
                        if '(INPR):wird heruntergeladen.' in self.log:
                            self.information[
                                'message_short'] = '(INPR):Download unvollständig.'
                            self.information['progress'] = 0
                        elif '(INPR):download in-progress.' in self.log:
                            self.information[
                                'message_short'] = '(INPR):Download unvollständig.'
                            self.information['progress'] = 0
                        elif '(OK):Herunterladen abgeschlossen.' in self.log:
                            self.information[
                                'message_short'] = '(OK):Download vollständig.'
                            self._finished()
                        elif '(OK):download completed.' in self.log:
                            self.information[
                                'message_short'] = '(OK):Download vollständig.'
                            self._finished()

                # Download Test
                self.information[
                    'message_short'] = 'Abschliessende Überprüfung der heruntergeladen Datei ...'
                self.update_view()
                if 'otrkey' in self.filename:
                    torrent_check_return = self._check_file_with_torrent()

                    if torrent_check_return == 0:
                        self.information[
                            'message_short'] = '(OK):Download vollständig.'
                        self._finished()
                    elif torrent_check_return == 7:
                        self.information['status'] = DownloadStatus.ERROR
                        self.information[
                            'message_short'] = '(INPR):Download unvollständig - Datei hat Torrent-Prüfung nicht bestanden. z.B. durch fehlerhaften oder nicht mehr gültiger Link. Downloadabbruch oder defekte Mirrordatei.'
                        self.information['progress'] = 0
                    else:
                        self.information['status'] = DownloadStatus.ERROR
                        self.information[
                            'message_short'] = '(EER):Fehler bei der abschliessenden Überprüfung aufgetreten. Eventuell OTR nicht erreichbar.'
                        self.information['progress'] = 0

        elif self.information['download_type'] in [
                DownloadTypes.OTR_DECODE, DownloadTypes.OTR_CUT
        ]:
            decoder = self._config.get_program('decoder')
            email = self._config.get('general', 'email')
            password = self._config.get('general', 'password')
            cache_dir = self._config.get('general', 'folder_trash_otrkeys')
            command = [
                decoder, "-b", "0", "-n", "-i", self.link, "-e", email, "-p",
                password, "-c", cache_dir
            ]

            if self.information['download_type'] == DownloadTypes.OTR_CUT:
                self.information['output'] = self._config.get(
                    'general', 'folder_cut_avis')
                if not self.information['cutlist']:
                    cutlist = Cutlist()
                    cutlist.id = self.information['cutlist_id']
                    error = cutlist.download(
                        self._config.get('general', 'server'),
                        os.path.join(self.information['output'],
                                     self.filename))
                    if error:
                        self.information['status'] = DownloadStatus.ERROR
                        self.information[
                            'message_short'] = 'Cutlist konnte nicht geladen werden.'
                        yield error
                        return

                    self.information['cutlist'] = cutlist

                command += [
                    "-o", self.information['output'], "-C",
                    self.information['cutlist'].local_filename
                ]
            else:
                self.information['output'] = self._config.get(
                    'general', 'folder_uncut_avis')
                command += ["-o", self.information['output']]

            # write command to log, but strip out email and password
            log = list(command)
            log[log.index('-p') + 1] = '*******'
            log[log.index('-e') + 1] = '*******'
            yield "Ausgeführt wird:\n%s\n" % " ".join(log)

            try:
                self.__process = subprocess.Popen(command,
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
            except OSError as error:
                self.information['status'] = DownloadStatus.ERROR
                self.information['message_short'] = 'Dekoder nicht gefunden.'
                yield "Der Pfad zum Dekoder scheint nicht korrekt zu sein. Der folgende Befehl konnte nicht ausgeführt werden\nFehlermeldung: %s" % error
                return

            line = ''
            while self.__process.poll() == None:
                char = self.__process.stdout.read(1)

                if char == '\r' or char == '\n':
                    line = line.strip()
                    if not line:
                        continue

                    if not "%" in line:
                        yield line

                    result = re.findall("([0-9]{1,3})%", line)
                    if result:
                        self.information['progress'] = int(result[0])

                    result = re.findall("[0-9]{1,3}%.*: (.*)", line)
                    if result:
                        self.information['speed'] = result[0]

                    self.update_view()

                    line = ''
                else:
                    line += char

            ### Process is terminated

            stderr = self.__process.stderr.read().strip()
            if stderr:
                self.information['status'] = DownloadStatus.ERROR
                if "invalid option" in stderr:
                    self.information[
                        'message_short'] = 'Der Dekoder ist veraltet.'
                    yield "Es ist ein veralteter Dekoder angegeben!\n"
                elif "maximale Anzahl":
                    self.information[
                        'message_short'] = 'Maximale Anzahl der Dekodierungen erreicht.'
                    yield str(stderr, 'iso-8859-1')
                else:
                    self.information['message_short'] = stderr
                    yield stderr

            if not self.information['status'] in [
                    DownloadStatus.ERROR, DownloadStatus.STOPPED
            ]:
                self._finished()
                # remove otrkey and .segments file
                otrkey = os.path.join(cache_dir, self.filename)
                fileoperations.remove_file(otrkey, None)
                fileoperations.remove_file(
                    os.path.join(cache_dir, self.filename + '.segments'), None)

                if self.information['download_type'] == DownloadTypes.OTR_CUT:
                    # rename file to "cut" filename
                    filename = os.path.join(self.information['output'],
                                            self.filename.rstrip(".otrkey"))
                    new_filename, extension = os.path.splitext(filename)
                    new_filename += ".cut" + extension
                    fileoperations.rename_file(filename, new_filename, None)

                    conclusion = FileConclusion(Action.DECODEANDCUT,
                                                otrkey=otrkey,
                                                uncut_video=filename)
                    conclusion.decode.status = Status.OK
                    conclusion.cut_video = new_filename
                    conclusion.cut.cutlist = self.information['cutlist']
                    conclusion.cut.cutlist.read_from_file()
                    conclusion.cut.status = Status.OK
                    conclusion.cut.cut_action = Cut_action.CHOOSE_CUTLIST
                    if self._config.get('general', 'rename_cut'):
                        conclusion.cut.rename = self._app.rename_by_schema(
                            self.filename.rstrip(".otrkey"))
                    else:
                        conclusion.cut.rename = os.path.basename(new_filename)

                    self._app.conclusions_manager.add_conclusions(conclusion)

        self.update_view()
Ejemplo n.º 27
0
    def __cut_file_virtualdub(self, filename, config_value, cuts=None, manually=False):
        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)
        if sar == None or dar == None:
            return None, error

        # find wine
        cmd_exists = lambda x: any(
            os.access(os.path.join(pathx, x), os.X_OK) for pathx in os.environ["PATH"].split(os.pathsep))
        if cmd_exists('wineconsole'):
            winecommand = 'wineconsole'
        elif cmd_exists('wine'):
            winecommand = 'wine'
        else:
            return None, "Wine konnte nicht aufgerufen werden."

        if format == Format.HQ:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_h264_169()
                else:
                    comp_data = codec.get_comp_data_h264_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar, self.config.get('general', 'x264vfw_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar, self.config.get('general', 'komisar_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.HD:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_hd_169()
                else:
                    comp_data = codec.get_comp_data_hd_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar, self.config.get('general', 'x264vfw_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar, self.config.get('general', 'komisar_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.MP4:
            if self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komsiar_dynamic(sar, self.config.get('general', 'komisar_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar, self.config.get('general', 'x264vfw_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
        elif format == Format.AVI:
            comp_data = codec.get_comp_data_dx50()
            compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
        else:
            return None, "Format nicht unterstützt (Nur Avi DX50, HQ H264 und HD sind möglich)."

        # make file for virtualdub scripting engine
        if manually:
            # TODO: kind of a hack
            curr_dir = os.getcwd()
            try:
                os.chdir(os.path.dirname(config_value))
            except OSError:
                return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        self.gui.main_window.set_tasks_progress(50)
        while Gtk.events_pending():
            Gtk.main_iteration()

        f = open("/tmp/tmp.vcf", "w")

        if not manually:
            f.write('VirtualDub.Open("%s");\n' % filename)

        if self.config.get('general', 'smart'):
            f.writelines([
                'VirtualDub.video.SetMode(1);\n',
                'VirtualDub.video.SetSmartRendering(1);\n',
                compression,
                'VirtualDub.video.SetCompData(%s);\n' % comp_data
            ])
        else:
            f.write('VirtualDub.video.SetMode(0);\n')

        f.write('VirtualDub.subset.Clear();\n')

        if not manually:
            keyframes, error = self.get_keyframes_from_file(filename)

            if keyframes == None:
                return None, "Keyframes konnten nicht ausgelesen werden."

            for frame_start, frames_duration in cuts:
                # interval does not begin with keyframe
                if not frame_start in keyframes and format == Format.HQ or format == Format.HD:
                    try:  # get next keyframe
                        frame_start_keyframe = self.get_keyframe_after_frame(keyframes, frame_start)
                    except ValueError:
                        frame_start_keyframe = -1

                    if frame_start + frames_duration > frame_start_keyframe:
                        # 'Smart Rendering Part mit anschließenden kopierten Part'
                        if frame_start_keyframe < 0:
                            # copy end of file
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start + 2, frames_duration - 2))
                        else:
                            # smart rendering part  (duration -2 due to smart rendering bug)
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (
                            frame_start + 2, frame_start_keyframe - frame_start - 2))
                            # vd smart rendering bug
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe - 1, 1))
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe - 1, 1))
                                # copy part
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (
                            frame_start_keyframe, frames_duration - (frame_start_keyframe - frame_start)))
                    else:
                        print('reiner Smart Rendering Part')
                        try:  # get next keyframe after the interval
                            next_keyframe = self.get_keyframe_after_frame(keyframes, frame_start + frames_duration - 2)
                        except ValueError:
                            next_keyframe = -1
                        if next_keyframe - (frame_start + frames_duration) > 2:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start + 2, frames_duration))
                        else:
                            # workaround for smart rendering bug
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start + 2, frames_duration - 2))
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe - 1, 1))
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe - 1, 1))
                else:
                    if not (frame_start + frames_duration) in keyframes and format == Format.HQ or format == Format.HD:
                        # 'Kopieren mit keinem Keyframe am Ende'
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration - 2))
                        # we all love workarounds
                        if ac3_file != None:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start + frames_duration - 1, 1))
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start + frames_duration - 1, 1))
                    else:
                        print('reines Kopieren')
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration))

            cut_video = self.generate_filename(filename, 1)

            f.writelines([
                'VirtualDub.SaveAVI("%s");\n' % cut_video,
                'VirtualDub.Close();'
            ])

        f.close()

        # start vdub
        if not os.path.exists(config_value):
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        if manually:
            win_filename = "Z:" + filename.replace(r"/", r"\\")
            command = 'VirtualDub.exe /s Z:\\\\tmp\\\\tmp.vcf "%s"' % win_filename
        else:
            command = "%s /s Z:\\\\tmp\\\\tmp.vcf /x" % config_value

        if 'intern-VirtualDub' in config_value:
            command = 'WINEPREFIX=' + os.path.dirname(config_value) + '/wine' + " " + winecommand + " " + command
        else:
            command = winecommand + " " + command

        try:
            vdub = subprocess.Popen(command, shell=True)
        except OSError:
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        while vdub.poll() == None:
            time.sleep(1)

            while Gtk.events_pending():
                Gtk.main_iteration()

        fileoperations.remove_file('/tmp/tmp.vcf')

        if manually:
            os.chdir(curr_dir)
            return None, None

        return cut_video, None
Ejemplo n.º 28
0
        def mkvmerge():
            # env
            my_env = os.environ.copy()
            my_env["LANG"] = "C"

            for count, filename in enumerate(filenames):
                yield 0, count
                yield 3, 0
                self.progress = 0

                #analyse file
                cutter = Cut(self.app, self.gui)
                fps, dar, sar, max_frames, ac3_stream, error = cutter.analyse_mediafile(
                    filename)
                if fps == None:
                    self.errors[filename] = error
                    continue

                # encode aac with ffmpeg
                if self.Config['EncodeAudioToAAC']:
                    #norm volume ausrechnen
                    yield 5, count
                    if self.Config['NormalizeAudio'] and self.Config[
                            'EncodeAudioToAAC']:
                        vol, error = self.get_norm_volume(filename)
                    else:
                        vol = 1.0

                    # ffmpeg pass
                    yield 1, count
                    self.progress = 0
                    ffmpegpass_file = fileoperations.make_unique_filename(
                        os.path.splitext(filename)[0] + "_remux.mkv")

                    # convert first audio stream to aac
                    if self.Config['EncodeOnlyFirstAudioToAAC']:
                        aacaudiostreams = '-c:a:0'
                    else:
                        aacaudiostreams = '-c:a'

                    # convert first audio stream to aac
                    ffmpeg = self.app.config.get_program('ffmpeg')
                    if 'nonfree' in ffmpeg:
                        # nonfree ffmpeg version with fdk support available
                        audiocodec = [
                            '-c:a', 'copy', aacaudiostreams, 'libfdk_aac',
                            '-flags', '+qscale', '-profile:a:0', 'aac_low',
                            '-global_quality', '5', '-afterburner', '1'
                        ]
                    else:
                        # only gpl version of ffmpeg available -> use standard aac codec
                        audiocodec = [
                            '-c:a', 'copy', aacaudiostreams, 'aac', '-strict',
                            '-2', '-profile:a:0', 'aac_low', '-ab', '192k',
                            '-cutoff', '18000'
                        ]

                    if self.Config['DownMixStereo'] and self.Config[
                            'EncodeAudioToAAC']:
                        audiocodec.extend(['-ac:0', '2'])

                    if ac3_stream == None:
                        # no ac3 stream found - all streams are muxed
                        map = ['-map', '0']
                    else:
                        if self.Config['RemoveOtherAudioStreamsThanAC3']:
                            # mux only video and ac3 stream
                            map = ['-map', '0:v', '-map', ac3_stream]
                        else:
                            map = ['-map', '0']

                    args = [
                        ffmpeg, "-loglevel", "info", "-y", "-drc_scale", "1.0",
                        "-i", filename, "-vn", '-af',
                        'volume=volume=' + str(vol), "-vsync", "1", '-async',
                        '1000', "-dts_delta_threshold", "100", "-vf",
                        "fps=" + str(fps), '-threads', '0', ffmpegpass_file
                    ]
                    map.extend(audiocodec)
                    args[8:8] = map

                    try:
                        p = subprocess.Popen(args,
                                             stderr=subprocess.PIPE,
                                             universal_newlines=True)
                    except OSError:
                        self.errors[
                            filename] = "FFMPEG (intern) wurde nicht gefunden!"
                        continue

                    yield 4, 0
                    line = ""
                    infos_match = re.compile(
                        r"time=(\d{2,}):(\d{2,}):(\d{2,}.\d{2,})")

                    while p.poll() == None:
                        line = p.stderr.readline()
                        m = re.search(infos_match, line)
                        if m and max_frames != 0:
                            frame = (float(m.group(1)) * 3600 +
                                     float(m.group(2)) * 60 +
                                     float(m.group(3))) * fps
                            next = float(frame / float(max_frames)) * 100
                            if next > self.progress:
                                self.progress = next
                                yield 4, self.progress
                        else:
                            pass

                    exit_code = p.poll()

                    if exit_code == 0:
                        pass
                    else:
                        self.errors[
                            filename] = "Fehler beim Erzeugen der MP4 Datei durch FFMPEG"
                        if os.path.exists(ffmpegpass_file):
                            fileoperations.remove_file(ffmpegpass_file)
                        continue

                # mkvmerge pass
                yield 2, count
                self.progress = 0

                mkvpass_file = fileoperations.make_unique_filename(
                    os.path.splitext(filename)[0] + ".mkv")

                if self.Config['EncodeAudioToAAC']:
                    args = [
                        self.app.config.get_program('mkvmerge'), '--engage',
                        'no_cue_duration', '--engage',
                        'no_cue_relative_position', '--ui-language', 'en_US',
                        "-o", mkvpass_file, '-A', filename, '-D',
                        ffmpegpass_file
                    ]
                else:
                    if self.Config[
                            'RemoveOtherAudioStreamsThanAC3'] and ac3_stream:
                        args = [
                            self.app.config.get_program('mkvmerge'),
                            '--engage', 'no_cue_duration', '--engage',
                            'no_cue_relative_position', '--ui-language',
                            'en_US', "-o", mkvpass_file, '-a', ac3_stream[2],
                            filename
                        ]
                    else:
                        args = [
                            self.app.config.get_program('mkvmerge'),
                            '--engage', 'no_cue_duration', '--engage',
                            'no_cue_relative_position', '--ui-language',
                            'en_US', "-o", mkvpass_file, filename
                        ]

                p = subprocess.Popen(args, stdout=subprocess.PIPE, env=my_env)
                p.stdout.readline()

                line = ""
                while p.poll() == None:
                    # read progress from stdout
                    char = p.stdout.read(1)
                    line += char
                    progress = ''
                    if char == ':':
                        if "Error" in line or "Warning" in line:
                            break

                        while char != '%':
                            char = p.stdout.read(1)
                            progress += char

                        try:
                            self.progress = int(progress.strip(' %'))
                            yield 3, self.progress
                        except ValueError:
                            pass

                exit_code = p.poll()

                if exit_code == 0 or exit_code == 1:
                    self.success += 1
                    if self.Config['EncodeAudioToAAC']:
                        fileoperations.remove_file(ffmpegpass_file)
                    if self.Config['DumpAVIs']:
                        if self.Config['DumpAVIs_delete']:
                            fileoperations.remove_file(filename)
                        else:
                            new_filename = os.path.join(
                                self.app.config.get('general',
                                                    'folder_trash_avis'),
                                os.path.basename(filename))
                            if os.path.exists(new_filename):
                                fileoperations.remove_file(new_filename)
                            fileoperations.move_file(
                                filename,
                                self.app.config.get('general',
                                                    'folder_trash_avis'))
                else:
                    error = p.stdout.readline()
                    try:
                        error = error.split(":")[1]
                    except IndexError:
                        pass

                    if "unknown type" in error:
                        error = "Datei konnte nicht gelesen werden."
                    self.errors[filename] = error
Ejemplo n.º 29
0
    def show_conclusions(self):
        conclusions = self.app.gui.dialog_conclusion._run(
            self.conclusions, self.app.rename_by_schema,
            self.app.config.get('general', 'folder_archive'))
        self.app.gui.main_window.builder.get_object('box_conclusion').hide()
        self.conclusions = []

        # create cutlists
        cutlists = []

        for conclusion in conclusions:
            if conclusion.action == Action.DECODE:
                continue

            print "[Conclusion] for file ", conclusion.uncut_video

            # rename
            print "[Conclusion] Rename?"
            if conclusion.cut.rename:
                print "[Conclusion] true"
                extension = os.path.splitext(conclusion.cut_video)[1]
                if not conclusion.cut.rename.endswith(extension):
                    conclusion.cut.rename += extension

                new_filename = os.path.join(
                    self.app.config.get('general', 'folder_cut_avis'),
                    conclusion.cut.rename.replace('/', '_'))
                new_filename = fileoperations.make_unique_filename(
                    new_filename)

                if conclusion.cut_video != new_filename:
                    conclusion.cut_video = fileoperations.rename_file(
                        conclusion.cut_video, new_filename)

            # move cut video to archive
            print "[Conclusion] Move to archive?"
            if conclusion.cut.archive_to:
                print "[Conclusion] true"
                fileoperations.move_file(conclusion.cut_video,
                                         conclusion.cut.archive_to)

            # move uncut video to trash if it's ok
            print "[Conclusion] Move to trash?"
            if conclusion.cut.status == Status.OK and conclusion.cut.delete_uncut:
                print "[Conclusion] true"
                if os.path.exists(conclusion.uncut_video):
                    # move to trash
                    target = self.app.config.get('general',
                                                 'folder_trash_avis')
                    conclusion.uncut_video = fileoperations.move_file(
                        conclusion.uncut_video, target)
                    if os.path.exists(conclusion.ac3_file):
                        target = self.app.config.get('general',
                                                     'folder_trash_avis')
                        fileoperations.move_file(conclusion.ac3_file, target)

                # remove local cutlists
                print "[Conclusion] Remove local cutlist?"
                if self.app.config.get('general', 'delete_cutlists'):
                    print "[Conclusion] true"
                    if conclusion.cut.cutlist.local_filename:
                        if os.path.exists(
                                conclusion.cut.cutlist.local_filename):
                            fileoperations.remove_file(
                                conclusion.cut.cutlist.local_filename)

            print "[Conclusion] Create cutlist?"
            if conclusion.cut.create_cutlist:
                print "[Conclusion] true"
                if "VirtualDub" in conclusion.cut.cutlist.intended_app:
                    intended_app_name = "VirtualDub"
                else:
                    intended_app_name = "Avidemux"

                if not conclusion.cut.cutlist.local_filename:
                    conclusion.cut.cutlist.local_filename = self.app.config.get(
                        'general',
                        'folder_uncut_avis') + '/' + os.path.basename(
                            conclusion.uncut_video) + ".cutlist"

                conclusion.cut.cutlist.author = self.app.config.get(
                    'general', 'cutlist_username')
                conclusion.cut.cutlist.intended_version = open(
                    path.getdatapath("VERSION"), 'r').read().strip()
                conclusion.cut.cutlist.smart = self.app.config.get(
                    'general', 'smart')

                conclusion.cut.cutlist.write_local_cutlist(
                    conclusion.uncut_video, intended_app_name,
                    conclusion.cut.my_rating)

                if conclusion.cut.upload_cutlist:
                    cutlists.append(conclusion.cut.cutlist)

        # upload cutlists:
        def upload():
            error_messages = []

            for cutlist in cutlists:
                error_message = cutlist.upload(
                    self.app.config.get('general', 'server'),
                    self.app.config.get('general', 'cutlist_hash'))
                if error_message:
                    error_messages.append(error_message)
                else:
                    if self.app.config.get('general', 'delete_cutlists'):
                        fileoperations.remove_file(cutlist.local_filename)

            count = len(cutlists)

            message = "Es wurden %s/%s Cutlisten hochgeladen!" % (
                str(count - len(error_messages)), str(count))
            if len(error_messages) > 0:
                message += " (" + ", ".join(error_messages) + ")"

            yield message

        if len(cutlists) > 0:
            print "[Conclusion] Upload cutlists"
            if self.app.gui.question_box(
                    "Soll(en) %s Cutlist(en) hochgeladen werden?" %
                    len(cutlists)):

                def change_status(message):
                    self.app.gui.main_window.change_status(0, message)

                GeneratorTask(upload, change_status).start()

        # rate cutlists
        def rate():
            yield 0  # fake generator
            messages = []
            count = 0
            for conclusion in conclusions:
                if conclusion.action == Action.DECODE:
                    continue

                if conclusion.cut.my_rating > -1:
                    print "Rate with ", conclusion.cut.my_rating
                    success, message = conclusion.cut.cutlist.rate(
                        conclusion.cut.my_rating,
                        self.app.config.get('general', 'server'))
                    if success:
                        count += 1
                    else:
                        messages += [message]

            if count > 0 or len(messages) > 0:
                if count == 0:
                    text = "Es wurde keine Cutlist bewertet!"
                if count == 1:
                    text = "Es wurde 1 Cutlist bewertet!"
                else:
                    text = "Es wurden %s Cutlisten bewertet!" % count

                if len(messages) > 0:
                    text += " (Fehler: %s)" % ", ".join(messages)

                self.app.gui.main_window.change_status(0, text)

        print "[Conclusion] Rate cutlists"
        GeneratorTask(rate).start()
Ejemplo n.º 30
0
    def create_cutlist(self,  filename, program_config_value):
        """ read cuts from avidemux 2 and 3
            returns cut_frames und cutlist_error """
            
        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)
        if fps == None:
            return None, error
            
        # env
        my_env = os.environ.copy()
        my_env["LANG"] = "C"
        my_env["LC_COLLATE"] = "C"
        
        if '.avi' in filename and "avidemux3" in program_config_value: 
            try:
                mkvmerge = subprocess.Popen([self.config.get_program('mkvmerge'),  '--ui-language',  'en_US', '-o', filename+'.mkv', filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True,  env=my_env)
                self.show_progress(mkvmerge)
                returncode = mkvmerge.wait()
                if returncode != 0 and returncode != 1:
                    return None,  'Fehler beim Muxen zu MKV'
            except:
                return None, "mkvmerge konnte nicht aufgerufen werden."
            
        try:
            if os.path.isfile(filename+'.mkv'):
                avidemux = subprocess.Popen([program_config_value, filename+'.mkv'], bufsize=-1 ,stdout=subprocess.PIPE)
            else:
                avidemux = subprocess.Popen([program_config_value, filename], bufsize=-1 ,stdout=subprocess.PIPE)
        except:
            if os.path.isfile(filename+'.mkv'):
                fileoperations.remove_file(filename+'.mkv')
            return None, "Avidemux konnte nicht aufgerufen werden: " + program_config_value
            
        seg_lines = []
        pts_correction = 0

        # Avidemux3
        if "avidemux3" in program_config_value:
            for line in avidemux.stdout.readlines():
                # [addReferenceVideo]  The first frame has a PTS >0, adjusting to 120 ms
                m_pts = re.search('\\[addReferenceVideo\\]  The first frame has a PTS >0.*?(\\d+)', line)
                if m_pts:
                    pts_correction = float(m_pts.group(1))*1000
                    continue
                #Segment :0/1
                m_seg = re.search('Segment :(\\d+)', line)
                if m_seg:
                    seg_id = int(m_seg.group(1))
                    if seg_id == 0:
                        seg_lines = []
                    continue
                #        duration     :10671440000 02:57:51,440
                m_dur = re.search(' *?duration *?:(\\d+)', line)
                if m_dur:
                    size = float(m_dur.group(1))*fps/1000000
                    continue
                #        refStartPts  :15740000 00:00:15,740
                m_start = re.search(' *?refStartPts *?:(\\d+)', line)
                if m_start:
                    start = (float(m_start.group(1))-pts_correction)*fps/1000000
                    if start > 0:
                        seg_lines.append((seg_id, start, size))
                    else:
                        # correct values for first keyframe
                        seg_lines.append((seg_id, 0.0, size-fps*pts_correction/1000000))
                    continue
        else:
            #avidemux2
            for line in avidemux.stdout.readlines():
                if line.startswith(' Seg'):
                    # delete not interesting parts
                    line = line[:line.find("audio")]

                    parts = line.split(',')

                    seg_id = int(parts[0].split(':')[-1])
                    if format == Format.HQ or format == Format.HD:
                        start = int(parts[1].split(':')[-1])-2
                    else:
                        start = int(parts[1].split(':')[-1])
                    size = int(parts[2].split(':')[-1])
                    seg_lines.append((seg_id, start, size))
                else:
                    pass


        # keep only necessary items
        seg_lines.reverse()
        temp_cuts = []

        for seg_id, start, duration in seg_lines:
            if seg_id == 0:
                temp_cuts.append((start, duration))
                break
            else:
                temp_cuts.append((start, duration))

        temp_cuts.reverse()

        cuts_frames = []
        count = 0
        for start, duration in temp_cuts:
            cuts_frames.append((start, duration))
            count += 1

        if os.path.isfile(filename+'.mkv'):
            fileoperations.remove_file(filename+'.mkv')

        if len(cuts_frames) == 0:
            cutlist_error = "Es wurde nicht geschnitten."
        else:
            cutlist_error = None
            
        return cuts_frames,  cutlist_error
Ejemplo n.º 31
0
    def mux_ac3(self, filename, cut_video, ac3_file,
                cutlist):  # cuts the ac3 and muxes it with the avi into an mkv
        mkvmerge = self.config.get_program('mkvmerge')
        root, extension = os.path.splitext(filename)
        mkv_file = os.path.splitext(cut_video)[0] + ".mkv"
        # env
        my_env = os.environ.copy()
        my_env["LANG"] = "C"

        # creates the timecodes string for splitting the .ac3 with mkvmerge
        timecodes = (','.join([
            self.get_timecode(start) + ',' +
            self.get_timecode(start + duration)
            for start, duration in cutlist.cuts_seconds
        ]))
        # splitting .ac3. Every second fragment will be used.
        #        return_value = subprocess.call([mkvmerge, "--split", "timecodes:" + timecodes, "-o", root + "-%03d.mka", ac3_file])
        try:
            blocking_process = subprocess.Popen([
                mkvmerge, '--ui-language', 'en_US', "--split",
                "timecodes:" + timecodes, "-o", root + "-%03d.mka", ac3_file
            ],
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.STDOUT,
                                                universal_newlines=True,
                                                env=my_env)
        except OSError as e:
            return None, e.strerror + ": " + mkvmerge
        return_value = blocking_process.wait()
        # return_value=0 is OK, return_value=1 means a warning. Most probably non-ac3-data that has been omitted.
        # TODO: Is there some way to pass this warning to the conclusion dialog?
        if return_value != 0 and return_value != 1:
            return None, None, str(return_value)

        if len(cutlist.cuts_seconds
               ) == 1:  # Only the second fragment is needed. Delete the rest.
            fileoperations.rename_file(root + "-002.mka", root + ".mka")
            fileoperations.remove_file(root + "-001.mka")
            if os.path.isfile(root + "-003.mka"):
                fileoperations.remove_file(root + "-003.mka")

        else:  # Concatenating every second fragment.
            command = [mkvmerge, "-o", root + ".mka", root + "-002.mka"]
            command[len(command):] = [
                "+" + root + "-%03d.mka" % (2 * n)
                for n in range(2,
                               len(cutlist.cuts_seconds) + 1)
            ]
            #            return_value = subprocess.call(command)
            try:
                blocking_process = subprocess.Popen(command,
                                                    stdout=subprocess.PIPE,
                                                    stderr=subprocess.STDOUT,
                                                    universal_newlines=True,
                                                    env=my_env)
            except OSError as e:
                return None, e.strerror + ": " + mkvmerge
            return_value = blocking_process.wait()
            if return_value != 0:  # There should be no warnings here
                return None, None, str(return_value)

            for n in range(1, 2 * len(cutlist.cuts_seconds) +
                           2):  # Delete all temporary audio fragments
                if os.path.isfile(root + "-%03d.mka" % n):
                    fileoperations.remove_file(root + "-%03d.mka" % n)

                    # Mux the cut .avi with the resulting audio-file into mkv_file
                    # TODO: Is there some way to pass possible warnings to the conclusion dialog?
                #        return_value = subprocess.call([mkvmerge, "-o", mkv_file, cut_video, root + ".mka"])
        try:
            blocking_process = subprocess.Popen(
                [mkvmerge, "-o", mkv_file, cut_video, root + ".mka"],
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True,
                env=my_env)
        except OSError as e:
            return None, e.strerror + ": " + mkvmerge
        return_value = blocking_process.wait()
        if return_value != 0 and return_value != 1:
            return None, None, str(return_value)

        fileoperations.remove_file(root +
                                   ".mka")  # Delete remaining temporary files
        fileoperations.remove_file(cut_video)
        return mkv_file, ac3_file, None
Ejemplo n.º 32
0
        def mp4():
            # env
            my_env = os.environ.copy()
            my_env["LANG"] = "C"

            for count, filename in enumerate(filenames):
                # analyse file
                cutter = Cut(self.app, self.gui)
                fps, dar, sar, max_frames, ac3_stream, error = cutter.analyse_mediafile(
                    filename)
                if fps == None:
                    self.errors[filename] = error
                    continue

                # mkvmerge pass
                yield 0, count
                self.progress = 0

                if os.path.splitext(filename)[1] != '.mkv':

                    mkvpass_file = fileoperations.make_unique_filename(
                        os.path.splitext(filename)[0] + "_remux.mkv")
                    try:
                        p = subprocess.Popen([
                            self.app.config.get_program('mkvmerge'),
                            '--ui-language', 'en_US', "-o", mkvpass_file,
                            filename
                        ],
                                             stdout=subprocess.PIPE,
                                             env=my_env)
                    except OSError:
                        self.errors[
                            filename] = "MKVmerge wurde nicht gefunden!"
                        continue

                    p.stdout.readline()
                    line = ""

                    while p.poll() == None:
                        # read progress from stdout
                        char = p.stdout.read(1)
                        line += char.decode('utf-8')
                        progress = ''
                        if char == ':':
                            if "Error" in line or "Warning" in line:
                                break

                            while char != '%':
                                char = p.stdout.read(1)
                                progress += char

                            try:
                                self.progress = int(progress.strip(' %'))
                                yield 4, self.progress
                            except ValueError:
                                pass

                    exit_code = p.poll()

                    if exit_code == 0 or exit_code == 1:
                        pass
                    else:
                        error = p.stdout.readline()
                        if os.path.exists(mkvpass_file):
                            fileoperations.remove_file(mkvpass_file)
                        try:
                            error = error.split(":")[1]
                        except IndexError:
                            pass

                        if "unknown type" in error:
                            error = "Datei konnte nicht gelesen werden."
                        self.errors[filename] = error
                        continue
                else:
                    mkvpass_file = filename

                # norm volume ausrechnen
                yield 5, count
                if self.Config['NormalizeAudio'] and self.Config[
                        'EncodeAudioToAAC']:
                    vol, error = self.get_norm_volume(filename)
                else:
                    vol = 1.0

                # ffmpeg pass
                yield 1, count
                self.progress = 0
                ffmpegpass_file = fileoperations.make_unique_filename(
                    os.path.splitext(filename)[0] + "_remux.mp4")

                if self.Config['EncodeAudioToAAC']:
                    if self.Config['EncodeOnlyFirstAudioToAAC']:
                        aacaudiostreams = '-c:a:0'
                    else:
                        aacaudiostreams = '-c:a'

                    # convert first audio stream to aac
                    ffmpeg = self.app.config.get_program('ffmpeg')
                    if 'nonfree' in ffmpeg:
                        # nonfree ffmpeg version with fdk support available
                        audiocodec = [
                            '-c:a', 'copy', aacaudiostreams, 'libfdk_aac',
                            '-flags', '+qscale', '-profile:a:0', 'aac_low',
                            '-global_quality', '5', '-afterburner', '1'
                        ]
                    else:
                        # only gpl version of ffmpeg available -> use standard aac codec
                        audiocodec = [
                            '-c:a', 'copy', aacaudiostreams, 'aac', '-strict',
                            '-2', '-profile:a:0', 'aac_low', '-ab', '192k',
                            '-cutoff', '18000'
                        ]
                else:
                    # only copy audio
                    ffmpeg = path.get_tools_path('intern-ffmpeg')
                    audiocodec = ['-c:a', 'copy']

                if self.Config['DownMixStereo'] and self.Config[
                        'EncodeAudioToAAC']:
                    audiocodec.extend(['-ac:0', '2'])

                if ac3_stream == None:
                    # no ac3 stream found - all streams are muxed
                    map = ['-map', '0']
                else:
                    if self.Config['RemoveOtherAudioStreamsThanAC3']:
                        # mux only video and ac3 stream
                        map = ['-map', '0:v', '-map', ac3_stream]
                    else:
                        map = ['-map', '0']

                args = [
                    ffmpeg, "-loglevel", "info", "-y", "-drc_scale", "1.0",
                    "-i", mkvpass_file, "-vcodec", "copy", '-af',
                    'volume=volume=' + str(vol), "-vsync", "1", '-async',
                    '1000', "-dts_delta_threshold", "100", "-vf",
                    "fps=" + str(fps), ffmpegpass_file
                ]
                map.extend(audiocodec)
                args[8:8] = map

                try:
                    p = subprocess.Popen(args,
                                         stderr=subprocess.PIPE,
                                         universal_newlines=True)
                except OSError:
                    self.errors[
                        filename] = "FFMPEG (intern) wurde nicht gefunden!"
                    if os.path.exists(
                            mkvpass_file) and filename != mkvpass_file:
                        fileoperations.remove_file(mkvpass_file)
                    continue

                yield 4, 0
                line = ""
                infos_match = re.compile(r"frame=\ {0,1}(\d{1,})")

                while p.poll() == None:
                    line = p.stderr.readline()
                    m = re.search(infos_match, line)
                    if m and max_frames != 0:
                        next = float(
                            float(m.group(1)) / float(max_frames)) * 100
                        if next > self.progress:
                            self.progress = next
                            yield 4, self.progress
                    else:
                        pass

                exit_code = p.poll()
                if os.path.exists(mkvpass_file) and filename != mkvpass_file:
                    fileoperations.remove_file(mkvpass_file)

                if exit_code == 0:
                    if self.Config['DumpAVIs']:
                        yield 3, self.success
                        new_filename = os.path.join(
                            self.app.config.get('general',
                                                'folder_trash_avis'),
                            os.path.basename(filename))
                        if os.path.exists(new_filename):
                            fileoperations.remove_file(new_filename)
                        fileoperations.move_file(
                            filename,
                            self.app.config.get('general',
                                                'folder_trash_avis'))
                else:
                    self.errors[
                        filename] = "Fehler beim Erzeugen der MP4 Datei durch FFMPEG"
                    if os.path.exists(ffmpegpass_file):
                        fileoperations.remove_file(ffmpegpass_file)
                    continue

                # mp4box - last turn
                self.progress = 0
                mp4boxpass_file = fileoperations.make_unique_filename(
                    os.path.splitext(filename)[0] + ".mp4")

                if self.Config['DontOptimizeMP4']:
                    os.rename(ffmpegpass_file, mp4boxpass_file)
                    self.success += 1
                    continue

                yield 2, count
                try:
                    p = subprocess.Popen([
                        self.app.config.get_program('mp4box'), "-keep-all",
                        "-new", "-packed", "-fps",
                        str(fps), "-add", ffmpegpass_file, mp4boxpass_file
                    ],
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT)
                except OSError:
                    self.errors[
                        filename] = "MP4Box (intern) wurde nicht gefunden!"
                    if os.path.exists(ffmpegpass_file):
                        fileoperations.remove_file(ffmpegpass_file)
                    continue

                yield 4, 0
                infos_match = re.compile(r".*\((\d{2,})\/\d{2,}\).*")

                while p.poll() == None:
                    line = p.stdout.read(60)
                    line = line.decode('utf-8')
                    m = re.search(infos_match, line)
                    if m:
                        self.progress = int(m.group(1))
                        yield 4, self.progress

                        if 'Importing' in line:
                            yield 2, count
                        elif 'Writing' in line:
                            yield 6, count
                    else:
                        pass

                exit_code = p.poll()
                if os.path.exists(ffmpegpass_file):
                    fileoperations.remove_file(ffmpegpass_file)

                if exit_code == 0:
                    self.success += 1
                else:
                    self.errors[
                        filename] = "Fehler beim Erzeugen der MP4 Datei durch MP4Box"
Ejemplo n.º 33
0
class CutVirtualdub(Cut):

    def __init__(self, app, gui):
        self.update_list = True
        self.app = app
        self.config = app.config
        self.gui = gui
        
    def __del__(self):
        # clean up
        pass
        
    def cut_file_by_cutlist(self, filename, cutlist=None,  program_config_value=None):
        return self.__cut_file_virtualdub(filename, program_config_value, cutlist.cuts_frames)

    def create_cutlist(self,  filename, program_config_value):
        cut_video_is_none, error = self.__cut_file_virtualdub(filename, program_config_value, cuts=None, manually=True)
 
        if error != None:
            return None,  error
        format, ac3_file, bframe_delay = self.get_format(filename)
        cuts_frames, cutlist_error = self.__create_cutlist_virtualdub(os.path.join(self.config.get('general', 'folder_uncut_avis'), "cutlist.vcf"), format)

        return cuts_frames,  cutlist_error

    def __cut_file_virtualdub(self, filename, config_value, cuts=None, manually=False):
        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)
        if sar == None or dar == None:
            return None, error
            
        # find wine
        cmd_exists = lambda x: any(os.access(os.path.join(pathx, x), os.X_OK) for pathx in os.environ["PATH"].split(os.pathsep))
        if cmd_exists('wineconsole'):
            winecommand = 'wineconsole'
        elif cmd_exists('wine'):
            winecommand = 'wine'
        else:
            return None, "Wine konnte nicht aufgerufen werden."
        
            
        if format == Format.HQ:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_h264_169()
                else:
                    comp_data = codec.get_comp_data_h264_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar,self.config.get('general', 'komisar_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.HD:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_hd_169()
                else:
                    comp_data = codec.get_comp_data_hd_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar,self.config.get('general', 'komisar_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.MP4:
            if self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komsiar_dynamic(sar,self.config.get('general', 'komisar_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
        elif format == Format.AVI:
            comp_data = codec.get_comp_data_dx50()
            compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
        else:
            return None, "Format nicht unterstützt (Nur Avi DX50, HQ H264 und HD sind möglich)."

        # make file for virtualdub scripting engine
        if manually:
            # TODO: kind of a hack
            curr_dir = os.getcwd()
            try:
                os.chdir(os.path.dirname(config_value))
            except OSError:
                return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        self.gui.main_window.set_tasks_progress(50)
        while events_pending():
                main_iteration(False)

        f = open("/tmp/tmp.vcf", "w")

        if not manually:
            f.write('VirtualDub.Open("%s");\n' % filename)

        if self.config.get('general', 'smart'):
            f.writelines([
                'VirtualDub.video.SetMode(1);\n',
                'VirtualDub.video.SetSmartRendering(1);\n',
                compression,
                'VirtualDub.video.SetCompData(%s);\n' % comp_data
                ])
        else:
            f.write('VirtualDub.video.SetMode(0);\n')

        f.write('VirtualDub.subset.Clear();\n')

        if not manually:
            keyframes, error = self.get_keyframes_from_file(filename)
            
            if keyframes == None:
                return None,  "Keyframes konnten nicht ausgelesen werden."
            
            for frame_start, frames_duration in cuts:
                # interval does not begin with keyframe
                if not frame_start in keyframes and format == Format.HQ or format == Format.HD:
                    try: # get next keyframe
                        frame_start_keyframe =self.get_keyframe_after_frame(keyframes, frame_start)
                    except ValueError:
                        frame_start_keyframe = -1
                        
                    if frame_start+frames_duration > frame_start_keyframe:
                        # 'Smart Rendering Part mit anschließenden kopierten Part'
                        if frame_start_keyframe < 0:
                            # copy end of file
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration-2))
                        else:
                            # smart rendering part  (duration -2 due to smart rendering bug)
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frame_start_keyframe-frame_start-2))
                            #vd smart rendering bug
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe-1, 1))                            
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe-1, 1))                            
                            # copy part
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe, frames_duration-(frame_start_keyframe-frame_start)))
                    else:
                        print 'reiner Smart Rendering Part'
                        try: # get next keyframe after the interval
                            next_keyframe = self.get_keyframe_after_frame(keyframes, frame_start+frames_duration-2)
                        except ValueError:
                            next_keyframe = -1   
                        if next_keyframe - (frame_start+frames_duration) > 2:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration))
                        else:
                            # workaround for smart rendering bug
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration-2))
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe-1, 1))                            
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe-1, 1))                            
                else:
                    if not (frame_start+frames_duration) in keyframes and format == Format.HQ or format == Format.HD:
                        # 'Kopieren mit keinem Keyframe am Ende'
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration-2))
                        # we all love workarounds
                        if ac3_file != None:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+frames_duration-1, 1))
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+frames_duration-1, 1))
                    else:
                        print 'reines Kopieren'
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration))
                        
            cut_video = self.generate_filename(filename,1)

            f.writelines([
                'VirtualDub.SaveAVI("%s");\n' % cut_video,
                'VirtualDub.Close();'
                ])

        f.close()

        # start vdub
        if not os.path.exists(config_value):
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        if manually:
            win_filename = "Z:" + filename.replace(r"/", r"\\")
            command = 'VirtualDub.exe /s Z:\\\\tmp\\\\tmp.vcf "%s"' % win_filename
        else:
            command = "%s /s Z:\\\\tmp\\\\tmp.vcf /x" % config_value

        if 'intern-VirtualDub' in config_value:
            command = 'WINEPREFIX=' + os.path.dirname(config_value) + '/wine' + " " + winecommand + " " + command
        else:
            command = winecommand + " " + command
        
        try:
            vdub = subprocess.Popen(command, shell=True)
        except OSError:
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        while vdub.poll() == None:
            time.sleep(1)

            while events_pending():
                main_iteration(False)

        fileoperations.remove_file('/tmp/tmp.vcf')

        if manually:
            os.chdir(curr_dir)
            return None, None

        return cut_video, None

    def __create_cutlist_virtualdub(self, filename, format):
        """ returns: cuts, error_message """

        try:
            f = open(filename, 'r')
        except IOError:
            return None, "Die VirtualDub-Projektdatei konnte nicht gelesen werden.\nWurde das Projekt in VirtualDub nicht gespeichert?\n(Datei: %s)." % filename

        cuts_frames = [] # (start, duration)
        count = 0

        for line in f.readlines():
            if "VirtualDub.subset.AddRange" in line:
                try:
                    start, duration = line[line.index('(') + 1 : line.index(')')].split(',')
                except (IndexError, ValueError), message:
                    return None, "Konnte Schnitte nicht lesen, um Cutlist zu erstellen. (%s)" % message

                if format == Format.HQ or format == Format.HD:
                    cuts_frames.append((int(start)-2, int(duration)))
                else:
                    cuts_frames.append((int(start), int(duration)))

        if len(cuts_frames) == 0:
            return None, "Konnte keine Schnitte finden!"

        fileoperations.remove_file(filename)

        return cuts_frames, None
Ejemplo n.º 34
0
    def __cut_file_virtualdub(self, filename, config_value, cuts=None, manually=False):
        format, ac3_file = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(filename)
        if sar == None or dar == None:
            return None, error
            
        if format == Format.HQ:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_h264_169()
                else:
                    comp_data = codec.get_comp_data_h264_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar,self.config.get('general', 'komisar_hq_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.HD:
            if self.config.get('general', 'h264_codec') == 'ffdshow':
                if dar == "16:9":
                    comp_data = codec.get_comp_data_hd_169()
                else:
                    comp_data = codec.get_comp_data_hd_43()
                compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'x264vfw':
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            elif self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komisar_dynamic(sar,self.config.get('general', 'komisar_hd_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                return None, "Codec nicht unterstützt. Nur ffdshow, x264vfw und komisar unterstützt."

        elif format == Format.MP4:
            if self.config.get('general', 'h264_codec') == 'komisar':
                comp_data = codec.get_comp_data_komsiar_dynamic(sar,self.config.get('general', 'komisar_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
            else:
                comp_data = codec.get_comp_data_x264vfw_dynamic(sar,self.config.get('general', 'x264vfw_mp4_string'))
                compression = 'VirtualDub.video.SetCompression(0x34363278,0,10000,0);\n'
        elif format == Format.AVI:
            comp_data = codec.get_comp_data_dx50()
            compression = 'VirtualDub.video.SetCompression(0x53444646,0,10000,0);\n'
        else:
            return None, "Format nicht unterstützt (Nur Avi DX50, HQ H264 und HD sind möglich)."

        # make file for virtualdub scripting engine
        if manually:
            # TODO: kind of a hack
            curr_dir = os.getcwd()
            try:
                os.chdir(os.path.dirname(config_value))
            except OSError:
                return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        self.gui.main_window.set_tasks_progress(50)
        while events_pending():
                main_iteration(False)

        f = open("/tmp/tmp.vcf", "w")

        if not manually:
            f.write('VirtualDub.Open("%s");\n' % filename)

        if self.config.get('general', 'smart'):
            f.writelines([
                'VirtualDub.video.SetMode(1);\n',
                'VirtualDub.video.SetSmartRendering(1);\n',
                compression,
                'VirtualDub.video.SetCompData(%s);\n' % comp_data
                ])
        else:
            f.write('VirtualDub.video.SetMode(0);\n')

        f.write('VirtualDub.subset.Clear();\n')

        if not manually:
            keyframes, error = self.get_keyframes_from_file(filename)
            
            if keyframes == None:
                return None,  "Keyframes konnten nicht ausgelesen werden."
            
            for frame_start, frames_duration in cuts:
                # interval does not begin with keyframe
                if not frame_start in keyframes and format == Format.HQ or format == Format.HD:
                    try: # get next keyframe
                        frame_start_keyframe =self.get_keyframe_after_frame(keyframes, frame_start)
                    except ValueError:
                        frame_start_keyframe = -1
                        
                    if frame_start+frames_duration > frame_start_keyframe:
                        # 'Smart Rendering Part mit anschließenden kopierten Part'
                        if frame_start_keyframe < 0:
                            # copy end of file
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration-2))
                        else:
                            # smart rendering part  (duration -2 due to smart rendering bug)
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frame_start_keyframe-frame_start-2))
                            #vd smart rendering bug
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe-1, 1))                            
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe-1, 1))                            
                            # copy part
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start_keyframe, frames_duration-(frame_start_keyframe-frame_start)))
                    else:
                        print 'reiner Smart Rendering Part'
                        try: # get next keyframe after the interval
                            next_keyframe = self.get_keyframe_after_frame(keyframes, frame_start+frames_duration-2)
                        except ValueError:
                            next_keyframe = -1   
                        if next_keyframe - (frame_start+frames_duration) > 2:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration))
                        else:
                            # workaround for smart rendering bug
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+2, frames_duration-2))
                            if ac3_file != None:
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe-1, 1))                            
                                f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (next_keyframe-1, 1))                            
                else:
                    if not (frame_start+frames_duration) in keyframes and format == Format.HQ or format == Format.HD:
                        # 'Kopieren mit keinem Keyframe am Ende'
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration-2))
                        # we all love workarounds
                        if ac3_file != None:
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+frames_duration-1, 1))
                            f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start+frames_duration-1, 1))
                    else:
                        print 'reines Kopieren'
                        f.write("VirtualDub.subset.AddRange(%i, %i);\n" % (frame_start, frames_duration))
                        
            cut_video = self.generate_filename(filename,1)

            f.writelines([
                'VirtualDub.SaveAVI("%s");\n' % cut_video,
                'VirtualDub.Close();'
                ])

        f.close()

        # start vdub
        if not os.path.exists(config_value):
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        if manually:
            win_filename = "Z:" + filename.replace(r"/", r"\\")
            command = 'VirtualDub.exe /s Z:\\\\tmp\\\\tmp.vcf "%s"' % win_filename
        else:
            command = "%s /s Z:\\\\tmp\\\\tmp.vcf /x" % config_value

        if 'intern-VirtualDub' in config_value:
            command = 'WINEPREFIX=' + os.path.dirname(config_value) + '/wine' + " wineconsole " + command
        else:
            command = "wineconsole " + command

        try:
            vdub = subprocess.Popen(command, shell=True)
        except OSError:
            return None, "VirtualDub konnte nicht aufgerufen werden: " + config_value

        while vdub.poll() == None:
            time.sleep(1)

            while events_pending():
                main_iteration(False)

        fileoperations.remove_file('/tmp/tmp.vcf')

        if manually:
            os.chdir(curr_dir)
            return None, None

        return cut_video, None
Ejemplo n.º 35
0
        def mkvmerge():
            # env
            my_env = os.environ.copy()
            my_env["LANG"] = "C"
            
            for count, filename in enumerate(filenames):
                yield 0, count
                yield 3, 0
                self.progress = 0

                #analyse file
                cutter = Cut(self.app, self.gui)
                fps, dar, sar, max_frames, ac3_stream, error = cutter.analyse_mediafile(filename)
                if fps == None:
                    self.errors[filename] = error
                    continue

                # encode aac with ffmpeg
                if self.Config['EncodeAudioToAAC']:
                    #norm volume ausrechnen
                    yield 5, count
                    if self.Config['NormalizeAudio'] and self.Config['EncodeAudioToAAC']:
                        vol, error = self.get_norm_volume(filename)
                    else:
                        vol = 1.0

                    # ffmpeg pass               
                    yield 1, count
                    self.progress = 0
                    ffmpegpass_file = fileoperations.make_unique_filename(os.path.splitext(filename)[0] + "_remux.mkv")

                    # convert first audio stream to aac
                    if self.Config['EncodeOnlyFirstAudioToAAC']:
                        aacaudiostreams = '-c:a:0'
                    else:
                        aacaudiostreams = '-c:a'

                    # convert first audio stream to aac
                    ffmpeg = self.app.config.get_program('ffmpeg')
                    if 'nonfree' in ffmpeg:
                        # nonfree ffmpeg version with fdk support available
                        audiocodec = ['-c:a',  'copy',  aacaudiostreams,  'libfdk_aac',  '-flags',  '+qscale',  '-profile:a:0',  'aac_low',  '-global_quality',  '5' ,'-afterburner',  '1']
                    else:
                        # only gpl version of ffmpeg available -> use standard aac codec
                        audiocodec = ['-c:a',  'copy',  aacaudiostreams,  'aac', '-strict', '-2','-profile:a:0',  'aac_low',  '-ab' ,'192k',  '-cutoff',  '18000']

                    if self.Config['DownMixStereo'] and self.Config['EncodeAudioToAAC']:
                        audiocodec.extend(['-ac:0',  '2'])

                    if ac3_stream == None:
                        # no ac3 stream found - all streams are muxed 
                        map = ['-map',  '0']
                    else:
                        if self.Config['RemoveOtherAudioStreamsThanAC3']:
                            # mux only video and ac3 stream
                            map = ['-map',  '0:v',  '-map',  ac3_stream]
                        else:
                            map = ['-map' ,'0']

                    args = [ffmpeg, "-loglevel", "info", "-y", "-drc_scale", "1.0", "-i", filename, "-vn", '-af', 'volume=volume=' + str(vol), "-vsync", "1", '-async',  '1000',  "-dts_delta_threshold", "100", "-vf", "fps="+ str(fps), '-threads',  '0',   ffmpegpass_file]
                    map.extend(audiocodec)
                    args[8:8] = map
                
                    try:
                        p = subprocess.Popen(args, stderr=subprocess.PIPE, universal_newlines=True)
                    except OSError:
                        self.errors[filename] = "FFMPEG (intern) wurde nicht gefunden!"            
                        continue

                    yield 4, 0
                    line = ""
                    infos_match = re.compile(r"time=(\d{2,}):(\d{2,}):(\d{2,}.\d{2,})")

                    while p.poll() == None:
                        line = p.stderr.readline()
                        m = re.search(infos_match,line)
                        if m and max_frames != 0:
                            frame = (float(m.group(1))*3600 + float(m.group(2))*60 + float(m.group(3)))*fps
                            next = float( frame / float(max_frames) ) * 100
                            if next > self.progress:
                                self.progress = next
                                yield 4, self.progress                                
                        else:
                            pass
                
                    exit_code = p.poll()

                    if exit_code == 0:
                        pass
                    else:
                        self.errors[filename] = "Fehler beim Erzeugen der MP4 Datei durch FFMPEG"
                        if os.path.exists(ffmpegpass_file):
                            fileoperations.remove_file(ffmpegpass_file)
                        continue

                # mkvmerge pass
                yield 2, count
                self.progress = 0

                mkvpass_file = fileoperations.make_unique_filename(os.path.splitext(filename)[0] + ".mkv")

                if self.Config['EncodeAudioToAAC']:
                    args = [self.app.config.get_program('mkvmerge'), '--engage', 'no_cue_duration', '--engage',  'no_cue_relative_position', '--ui-language',  'en_US',"-o", mkvpass_file, '-A',  filename, '-D',   ffmpegpass_file]
                else:
                    if self.Config['RemoveOtherAudioStreamsThanAC3'] and ac3_stream:
                        args = [self.app.config.get_program('mkvmerge'), '--engage', 'no_cue_duration', '--engage',  'no_cue_relative_position', '--ui-language',  'en_US', "-o", mkvpass_file, '-a',  ac3_stream[2],  filename]
                    else:
                        args = [self.app.config.get_program('mkvmerge'),  '--engage', 'no_cue_duration', '--engage',  'no_cue_relative_position', '--ui-language',  'en_US', "-o", mkvpass_file, filename]

                p = subprocess.Popen(args, stdout=subprocess.PIPE,  env=my_env)
                p.stdout.readline()

                line = ""                            
                while p.poll() == None:
                    # read progress from stdout 
                    char = p.stdout.read(1)
                    line += char
                    progress = ''
                    if char == ':':
                        if "Error" in line or "Warning" in line:                            
                            break
                    
                        while char != '%':
                            char = p.stdout.read(1)
                            progress += char
                      
                        try:
                            self.progress = int(progress.strip(' %'))
                            yield 3, self.progress
                        except ValueError:
                            pass
                
                exit_code = p.poll()

                if exit_code == 0 or exit_code == 1:
                    self.success += 1
                    if self.Config['EncodeAudioToAAC']:
                        fileoperations.remove_file(ffmpegpass_file)
                    if self.Config['DumpAVIs']:
                        if self.Config['DumpAVIs_delete']:
                            fileoperations.remove_file(filename)
                        else:
                            new_filename = os.path.join(self.app.config.get('general', 'folder_trash_avis'), os.path.basename(filename))
                            if os.path.exists(new_filename):
                                fileoperations.remove_file(new_filename)
                            fileoperations.move_file(filename, self.app.config.get('general', 'folder_trash_avis'))
                else:
                    error = p.stdout.readline()
                    try:
                        error = error.split(":")[1]
                    except IndexError:
                        pass
                        
                    if "unknown type" in error:
                        error = "Datei konnte nicht gelesen werden."
                    self.errors[filename] = error
Ejemplo n.º 36
0
    def cut_file_manually(self, filename):
        """ Cuts a file manually with Avidemux or VirtualDub or the CutInterface and gets cuts from
            possibly created project files (VD) or from output (AD). 
            returns: error_message, cutlist """

        global cutlist_error, cuts_frames
        program, config_value, ac3file = self.get_program(filename,
                                                          manually=True)
        format, ac3_file, bframe_delay = self.get_format(filename)
        fps, dar, sar, max_frames, ac3_stream, error = self.analyse_mediafile(
            filename)

        if error:
            if exists(filename + '.mkv'):
                fileoperations.remove_file(filename + '.mkv')
            return "Konnte FPS nicht bestimmen: " + error, None

        if program < 0:
            return config_value, None

        cutlist = cutlists_management.Cutlist()

        if program == Program.AVIDEMUX:

            cutter = CutAvidemux(self.app, self.gui)
            cuts_frames, cutlist_error = cutter.create_cutlist(
                filename, config_value)

        elif program == Program.VIRTUALDUB:  # VIRTUALDUB

            cutter = CutVirtualdub(self.app, self.gui)
            cuts_frames, cutlist_error = cutter.create_cutlist(
                filename, config_value)

        if program == Program.CUT_INTERFACE:
            # looking for latest cutlist, if any
            p, video_file = os.path.split(filename)
            cutregex = re.compile("^" + video_file + "\.?(.*).cutlist$")
            files = os.listdir(p)
            number = -1
            local_cutlist = None  # use fallback name in conclusions if there are no local cutlists
            for f in files:
                match = cutregex.match(f)
                if match:
                    self.log.debug("Found local cutlist {}".format(
                        match.group()))
                    if match.group(1) == '' or match.group(1) == 'mkv':
                        res_num = 0
                    elif "." in match.group(1):
                        res_num = int(match.group(1).split('.')[1])
                    elif type(eval(
                            match.group(1))) == type(1):  # It's a number
                        res_num = int(match.group(1))
                    else:
                        res_num = 0

                    self.log.debug("local cutlist res_num: {}".format(
                        match.group(1)))
                    if res_num > number:
                        res_num = number
                        local_cutlist = p + "/" + match.group()

            ci = CutinterfaceDialog.NewCutinterfaceDialog(self.gui)
            ci.set_transient_for(self.gui.main_window)
            ci.set_modal(True)
            cutlist = ci._run(filename, local_cutlist, self.app)
            ci.destroy()

            if cutlist.cuts_frames is None or len(cutlist.cuts_frames) == 0:
                cutlist_error = "Keine Schnitte angegeben"
            else:
                cutlist_error = None

        else:  # complete cutlist for Avidemux & VirtualDub

            # create cutlist data
            if cutlist_error is None:
                cutlist.cuts_frames = cuts_frames
                cutlist.intended_app = basename(config_value)
                cutlist.usercomment = 'Mit %s geschnitten' % self.app.app_name
                cutlist.fps = fps

                # calculate seconds
                for start_frame, duration_frames in cuts_frames:
                    cutlist.cuts_seconds.append(
                        (start_frame / fps, duration_frames / fps))

        if cutlist_error:
            return cutlist_error, None
        else:
            return None, cutlist
Ejemplo n.º 37
0
    def show_conclusions(self):
        conclusions = self.app.gui.dialog_conclusion._run(self.conclusions, self.app.rename_by_schema, self.app.config.get('general', 'folder_archive'))
        self.app.gui.main_window.builder.get_object('box_conclusion').hide()   
        self.conclusions = []
        
        # create cutlists            
        cutlists = []

        for conclusion in conclusions:
            if conclusion.action == Action.DECODE:
                continue

            print "[Conclusion] for file ", conclusion.uncut_video

            # rename
            print "[Conclusion] Rename?"
            if conclusion.cut.rename:
                print "[Conclusion] true"
                extension = os.path.splitext(conclusion.cut_video)[1]
                if not conclusion.cut.rename.endswith(extension):
                    conclusion.cut.rename += extension
                
                new_filename = os.path.join(self.app.config.get('general', 'folder_cut_avis'), conclusion.cut.rename.replace('/', '_'))
                #new_filename = fileoperations.make_unique_filename(new_filename)
                    
                if conclusion.cut_video != new_filename:
                    conclusion.cut_video = fileoperations.rename_file(conclusion.cut_video, new_filename)
        
            # move cut video to archive
            print "[Conclusion] Move to archive?"
            if conclusion.cut.archive_to:
                print "[Conclusion] true"
                fileoperations.move_file(conclusion.cut_video, conclusion.cut.archive_to)
        
            # move uncut video to trash if it's ok
            print "[Conclusion] Move to trash?"
            if conclusion.cut.status == Status.OK and conclusion.cut.delete_uncut:                
                print "[Conclusion] true"
                if os.path.exists(conclusion.uncut_video):
                    # move to trash
                    target = self.app.config.get('general', 'folder_trash_avis')
                    conclusion.uncut_video = fileoperations.move_file(conclusion.uncut_video, target)        
                    if os.path.exists(conclusion.ac3_file):
			target = self.app.config.get('general', 'folder_trash_avis')
			fileoperations.move_file(conclusion.ac3_file, target)        
                
                # remove local cutlists      
                print "[Conclusion] Remove local cutlist?"
                if self.app.config.get('general', 'delete_cutlists'):                
                    print "[Conclusion] true"
                    if conclusion.cut.cutlist.local_filename:
                        if os.path.exists(conclusion.cut.cutlist.local_filename):
                            fileoperations.remove_file(conclusion.cut.cutlist.local_filename)
        
            print "[Conclusion] Create cutlist?"
            if conclusion.cut.create_cutlist:
                print "[Conclusion] true"
                if "VirtualDub" in conclusion.cut.cutlist.intended_app:
                    intended_app_name = "VirtualDub"
                else:
                    intended_app_name = "Avidemux"

                if not conclusion.cut.cutlist.local_filename:
                    conclusion.cut.cutlist.local_filename = self.app.config.get('general', 'folder_uncut_avis') + '/' + os.path.basename(conclusion.uncut_video) + ".cutlist"
                
                conclusion.cut.cutlist.author = self.app.config.get('general', 'cutlist_username')
                conclusion.cut.cutlist.intended_version = open(path.getdatapath("VERSION"), 'r').read().strip()
                conclusion.cut.cutlist.smart = self.app.config.get('general', 'smart')                   

                conclusion.cut.cutlist.write_local_cutlist(conclusion.uncut_video, intended_app_name, conclusion.cut.my_rating)
                
                if conclusion.cut.upload_cutlist:
                    cutlists.append(conclusion.cut.cutlist)
                                    
            
        # upload cutlists:
        def upload():
            error_messages = []

            for cutlist in cutlists:
                error_message = cutlist.upload(self.app.config.get('general', 'server'), self.app.config.get('general', 'cutlist_hash'))
                if error_message: 
                    error_messages.append(error_message)
                else:
                    if self.app.config.get('general', 'delete_cutlists'):
                        fileoperations.remove_file(cutlist.local_filename)
                 
            count = len(cutlists)
                
            message = "Es wurden %s/%s Cutlisten hochgeladen!" % (str(count - len(error_messages)), str(count))
            if len(error_messages) > 0:
                message += " (" + ", ".join(error_messages) + ")"

            yield message
                
        if len(cutlists) > 0:
            print "[Conclusion] Upload cutlists"
            if self.app.gui.question_box("Soll(en) %s Cutlist(en) hochgeladen werden?" % len(cutlists)):
                    
                def change_status(message):
                    self.app.gui.main_window.change_status(0, message)
                    
                GeneratorTask(upload, change_status).start()
          
        # rate cutlists                
        def rate():                    
            yield 0 # fake generator
            messages = []
            count = 0
            for conclusion in conclusions:                    
                if conclusion.action == Action.DECODE:
                    continue
                
                if conclusion.cut.my_rating > -1:
                    print "Rate with ", conclusion.cut.my_rating
                    success, message = conclusion.cut.cutlist.rate(conclusion.cut.my_rating, self.app.config.get('general', 'server'))
                    if success:
                        count += 1
                    else:
                        messages += [message]
                
            if count > 0 or len(messages) > 0:
                if count == 0:
                    text = "Es wurde keine Cutlist bewertet!"
                if count == 1:
                    text = "Es wurde 1 Cutlist bewertet!"
                else:
                    text = "Es wurden %s Cutlisten bewertet!" % count
                        
                if len(messages) > 0:
                    text += " (Fehler: %s)" % ", ".join(messages)
                
                self.app.gui.main_window.change_status(0, text)
        
        print "[Conclusion] Rate cutlists"
        GeneratorTask(rate).start()