def nextFrame(self): if not self.isPlaying and self.isSeekable: self.mPlayer.next_frame() tc = TimeCode() tc.setTimeCode(self.tcPos.text()) tc += 1 self.tcPos.setText(tc.timecode) self.tcPos.repaint()
def saveSrt(self, filename): with open(filename, 'w', encoding='utf-8') as fp: for i in range(self.subTablePanel.rowCount()): fp.write(f"{i+1}\n") tcIn = TimeCode(self.subTablePanel.item(i, 0).text()) tcOut = TimeCode(self.subTablePanel.item(i, 1).text()) sub = self.subTablePanel.item(i, 2).text() fp.write(f"{tcIn.get_mstc()} --> {tcOut.get_mstc()}\n") fp.write(f"{sub}\n") fp.write("\n")
def split_row(self): current_sel = self.selectionModel().selectedRows()[0].row() currIn = self.item(current_sel, 0).text() currOut = self.item(current_sel, 1).text() text = self.item(current_sel, 2).text() self.insertRow(current_sel+1) aIn = TimeCode(currIn) aOut = TimeCode(currOut) bIn = aIn + (aOut - aIn) / 2 self.setItem(current_sel, 1, QTableWidgetItem(bIn.timecode, 1)) self.setItem(current_sel+1, 0, QTableWidgetItem(bIn.timecode, 1)) self.setItem(current_sel+1, 1, QTableWidgetItem(currOut, 1)) self.setItem(current_sel+1, 2, QTableWidgetItem(text, 1)) self.row_added.emit()
def loadVideoFile(self, videoFile): self.fileParsed = False t_media = self.vlc_instance.media_new(videoFile) self.mPlayer.set_media(t_media) self.mPlayer.video_set_aspect_ratio(b"16:9") t_media.parse_with_options(1, 0) sleep(1) # Time to parse video if t_media.get_parsed_status() == vlc.MediaParsedStatus().done: self.fileParsed = True self.currVideoFile = videoFile self.message.emit(f"{path.basename(videoFile)} Loaded!") self.dur = t_media.get_duration() / 1000 # video duration in seconds self.video_duration = TimeCode() self.video_duration.setSecs(self.dur) # self.video_slider.setMaximum(floor(self.dur)) self.tcPos.setText(self.video_duration.getTimeCode())
def import_project(self): file_dialog = QFileDialog(self, "Import File") selected_file, valid = file_dialog.getOpenFileName() if valid: self.importing = True # print(f"Importing {selected_file}") fileName, ext = splitext(selected_file) if ext == ".xml": self.clear_table() self.editPanel.no.setValue(1) project = xmlET.parse(selected_file) # print(project.findall('.//generatoritem')) for card in project.findall('.//generatoritem'): tcIn = TimeCode() tcOut = TimeCode() tcIn.setFrames(int(card[5].text)) tcOut.setFrames(int(card[6].text)) # print(tcIn.timecode, tcOut.timecode, card[10][6][2].text) try: sub = deepcopy( card[10][6][2].text) # Standard FCP Outline Text except IndexError: sub = deepcopy( card[13][6][2].text) # Texte avec bordure self.editPanel.tcIn.setText(tcIn.timecode) self.editPanel.tcOut.setText(tcOut.timecode) self.editPanel.subtitle.setText(sub) self.insert_new_subtitle() videofile = project.find( ".//media/video/track/clipitem/file/pathurl") p = urlparse(videofile.text) finalPath = abspath(join(p.netloc, p.path)) if exists(finalPath): # print(f"Loading {finalPath}") self.videoPanel.loadVideoFile(finalPath) else: # print(f"File not found {finalPath}") self.updateStatusBar(f"File not found {finalPath}") videofile, videoext = splitext(finalPath) if not exists(f"{videofile}.srt"): self.setup_temp_subtitles() self.importing = False self.saveSrt(self.tmp)
def processWaveformSelection(self): try: wavIn, wavOut = self.waveFormPanel.selectionCtrl.getRegion() total_audio_frames = self.waveFormPanel.getTotalAudioFrames() total_video_frames = self.videoPanel.video_duration.frames x = self.map(int(wavIn), 0, total_audio_frames / 100, 0, total_video_frames) # Because audio filtering y = self.map( int(wavOut), 0, total_audio_frames / 100, 0, total_video_frames) # of 100 in wavformPanel.py Line 83 selIn = TimeCode() selIn.setFrames(int(x)) selOut = TimeCode() selOut.setFrames(int(y)) # print("Selected ->", wavIn, wavOut, "->", x, y, "->",selIn, selOut, "->", selIn.frames, selOut.frames) self.editPanel.tcIn.setText(selIn.timecode) self.editPanel.tcOut.setText(selOut.timecode) self.editPanel.calculate_duration() except AttributeError: print("please make sure you have a video and audio file loaded!")
def get_format_value(my, value, format, format_option=None): '''format is required. format_option is optional where applicable like fps for timecode''' if value == '': return value if isinstance(value, datetime.datetime): value = str(value) elif not isinstance(value, basestring): value = str(value) if value.startswith("{") and value.endswith("}"): from pyasm.search import Search value = Search.eval(value) # ------------------------------------------------ # Integer if format == '-1234': if not value: # Case where value is '', 0, 0.0, -0.0 . value = 0 value = "%0.0f" % my.convert_to_float(value) elif format == '-1,234': if not value: value = 0 # Group the value into three numbers seperated by a comma. value = my.number_format(value, places=0) # ------------------------------------------------ # Float elif format == '-1234.12': if not value: value = 0 value = "%0.2f" % my.convert_to_float(value) elif format == '-1,234.12': # break the value up by 3s if not value: value = 0 elif isinstance(value, basestring): value = float(value) value = my.number_format(value, places=2) # ------------------------------------------------ # Percentage elif format == '-13%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.0f" % my.convert_to_float(value) + "%" elif format == '-12.95%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.2f" % my.convert_to_float(value) + "%" # ------------------------------------------------ # Currency elif format == '-$1,234': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] elif format == '-$1,234.00': if not value: value = 0 value = my.currency_format(value, grouping=True) elif format == '-$1,234.--': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] + ".--" elif format == '-$1,234.00 CAD': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True, monetary=True) elif format == '($1,234.00)': # break the value up by 3s if not value: value = "-" else: value = my.currency_format(value, grouping=True) if value.startswith("-"): value = "(%s)" % value.replace("-", "") # ------------------------------------------------ # Date elif format == '31/12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y") elif format == 'December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B %d, %Y") elif format == '31/12/1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%Y") elif format == 'Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %y") elif format == 'Dec 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %Y") elif format == '31 Dec, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %b, %Y") elif format == '31 December 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %B %Y") elif format == 'Fri, Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %b %d, %y") elif format == 'Fri 31/Dec 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a %d/%b %y") elif format == 'Fri, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %B %d, %Y") elif format == 'Friday, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%A, %B %d, %Y") elif format == '12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d") elif format == '99-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y-%m-%d") elif format == '1999-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y-%m-%d") elif format == '12-31-1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d-%Y") elif format == '12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%y") elif format == '31/Dec': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%b") elif format == 'December': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B") elif format == '52': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%U") # ------------------------------------------------ # Time elif format == '13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M") elif format == '13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M:%S") elif format == '01:37 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M %p") elif format == '01:37:46 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M:%S %p") elif format == '31/12/99 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M") elif format == '99/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y/%m/%d %H:%M") elif format == '1999/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %H:%M") elif format == 'YYYY/MM/DD HH:MM AM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %I:%M %p") elif format == '31/12/99 13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M:%S") elif format == 'DATETIME': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATETIME') if not setting: setting = "%Y-%m-%d %H:%M" value = value.strftime(setting) elif format == 'DATE': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATE') if not setting: setting = "%Y-%m-%d" value = value.strftime(setting) # ------------------------------------------------ # Scientific elif format == '-1.23E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" elif format == '-1.234E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" # ------------------------------------------------ # Boolean # false = 0, true = 1 elif format in ['True|False']: if value: value = 'True' else: value = 'False' elif format in ['true|false']: if value: value = 'true' else: value = 'false' # ------------------------------------------------ # Timecode elif format in ['MM:SS.FF','MM:SS:FF', 'MM:SS', 'HH:MM:SS.FF', 'HH:MM:SS:FF','HH:MM:SS']: #fps = my.get_option('fps') fps = format_option if not fps: fps = 24 else: fps = int(fps) timecode = TimeCode(frames=value, fps=fps) value = timecode.get_timecode(format) # ------------------------------------------------ # Dictionary elif format == "DICT": dict_as_str = "" dict_list = [] if not value: value = '' else: for key, value in sorted(value.iteritems()): dict_list.append("%s : %s" % (key, value)) dict_as_str = "<br />".join(dict_list) value = dict_as_str # ------------------------------------------------ # File Size elif format in ['KB']: value = float(value) ext = " B" if not value: value = 0 ext = "B" elif value > 1024**5/2: value = float(value)/1024**5 ext = "PB" elif value > 1024**4/2: value = float(value)/1024**4 ext = "TB" elif value > 1024**3/2: value = float(value)/1024**3 ext = "GB" elif value > 1024**2/2: value = float(value)/1024**2 ext = "MB" elif value > 1024/2: value = float(value)/1024 ext = "KB" else: value = int(value) return "%s B" % value value = my.currency_format(value, grouping=True) # HACK: remove $ and last decimal value = value[1:-1] value = "%s %s" % (value, ext) return value
def get_format_value(my, value, format, format_option=None): '''format is required. format_option is optional where applicable like fps for timecode''' if value == '': return value if isinstance(value, datetime.datetime): value = str(value) elif not isinstance(value, basestring): value = str(value) if value.startswith("{") and value.endswith("}"): from pyasm.search import Search value = Search.eval(value) # ------------------------------------------------ # Integer if format == '-1234': if not value: # Case where value is '', 0, 0.0, -0.0 . value = 0 value = "%0.0f" % my.convert_to_float(value) elif format == '-1,234': if not value: value = 0 # Group the value into three numbers seperated by a comma. value = my.number_format(value, places=0) # ------------------------------------------------ # Float elif format == '-1234.12': if not value: value = 0 value = "%0.2f" % my.convert_to_float(value) elif format == '-1,234.12': # break the value up by 3s if not value: value = 0 elif isinstance(value, basestring): value = float(value) value = my.number_format(value, places=2) # ------------------------------------------------ # Percentage elif format == '-13%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.0f" % my.convert_to_float(value) + "%" elif format == '-12.95%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.2f" % my.convert_to_float(value) + "%" # ------------------------------------------------ # Currency elif format == '-$1,234': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] elif format == '-$1,234.00': if not value: value = 0 value = my.currency_format(value, grouping=True) elif format == '-$1,234.--': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] + ".--" elif format == '-$1,234.00 CAD': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True, monetary=True) elif format == '($1,234.00)': # break the value up by 3s if not value: value = "-" else: value = my.currency_format(value, grouping=True) if value.startswith("-"): value = "(%s)" % value.replace("-", "") # ------------------------------------------------ # Date elif format == '31/12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y") elif format == 'December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B %d, %Y") elif format == '31/12/1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%Y") elif format == 'Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %y") elif format == 'Dec 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %Y") elif format == '31 Dec, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %b, %Y") elif format == '31 December 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %B %Y") elif format == 'Fri, Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %b %d, %y") elif format == 'Fri 31/Dec 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a %d/%b %y") elif format == 'Fri, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %B %d, %Y") elif format == 'Friday, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%A, %B %d, %Y") elif format == '12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d") elif format == '99-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y-%m-%d") elif format == '1999-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y-%m-%d") elif format == '12-31-1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d-%Y") elif format == '12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%y") elif format == '31/Dec': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%b") elif format == 'December': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B") elif format == '52': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%U") # ------------------------------------------------ # Time elif format == '13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M") elif format == '13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M:%S") elif format == '01:37 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M %p") elif format == '01:37:46 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M:%S %p") elif format == '31/12/99 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M") elif format == '99/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y/%m/%d %H:%M") elif format == '1999/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %H:%M") elif format == 'YYYY/MM/DD HH:MM AM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %I:%M %p") elif format == '31/12/99 13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M:%S") elif format == 'DATETIME': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATETIME') if not setting: setting = "%Y-%m-%d %H:%M" value = value.strftime(setting) elif format == 'DATE': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATE') if not setting: setting = "%Y-%m-%d" value = value.strftime(setting) # ------------------------------------------------ # Scientific elif format == '-1.23E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" elif format == '-1.234E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" # ------------------------------------------------ # Boolean # false = 0, true = 1 elif format in ['True|False']: if value: value = 'True' else: value = 'False' elif format in ['true|false']: if value: value = 'true' else: value = 'false' # ------------------------------------------------ # Timecode elif format in [ 'MM:SS.FF', 'MM:SS:FF', 'MM:SS', 'HH:MM:SS.FF', 'HH:MM:SS:FF', 'HH:MM:SS' ]: #fps = my.get_option('fps') fps = format_option if not fps: fps = 24 else: fps = int(fps) timecode = TimeCode(frames=value, fps=fps) value = timecode.get_timecode(format) # ------------------------------------------------ # Dictionary elif format == "DICT": dict_as_str = "" dict_list = [] if not value: value = '' else: for key, value in sorted(value.iteritems()): dict_list.append("%s : %s" % (key, value)) dict_as_str = "<br />".join(dict_list) value = dict_as_str # ------------------------------------------------ # File Size elif format in ['KB']: value = float(value) ext = " B" if not value: value = 0 ext = "B" elif value > 1024**5 / 2: value = float(value) / 1024**5 ext = "PB" elif value > 1024**4 / 2: value = float(value) / 1024**4 ext = "TB" elif value > 1024**3 / 2: value = float(value) / 1024**3 ext = "GB" elif value > 1024**2 / 2: value = float(value) / 1024**2 ext = "MB" elif value > 1024 / 2: value = float(value) / 1024 ext = "KB" else: value = int(value) return "%s B" % value value = my.currency_format(value, grouping=True) # HACK: remove $ and last decimal value = value[1:-1] value = "%s %s" % (value, ext) elif format in ['ROOT']: value, ext = os.path.splitext(value) elif format in ['EXT']: base, value = os.path.splitext(value) value = value.lstrip(".") elif format in ['BASENAME']: value = os.path.basename(value) elif format in ['DIRNAME']: value = os.path.dirname(value) return value
thumb_frame = start_frame + (duration/2) plate_path = "%s.%s.%s"%(plates[0], g_write_frame_format, mainplate_ext) start_file_path = "%s.%s.%s"%(plates[0], mainplate_first, mainplate_ext) end_file_path = "%s.%s.%s"%(plates[0], mainplate_last, mainplate_ext) thumb_frame_path = "%s.%s.%s"%(plates[0], thumb_frame, mainplate_ext) clip_name = plate_name scene = "" take = "" start_file = None start_timecode = 0 try: start_file = OpenEXR.InputFile(start_file_path) start_timecode = int(start_frame)*1000 start_tc_obj = start_file.header()['timeCode'] header_fps = float(start_file.header()['framesPerSecond'].n)/float(start_file.header()['framesPerSecond'].d) start_timecode = int((TimeCode("%02d:%02d:%02d:%02d"%(start_tc_obj.hours, start_tc_obj.minutes, start_tc_obj.seconds, start_tc_obj.frame), inputfps=header_fps).frame_number() * 1000) / header_fps) clip_name = start_file.header()['reelName'] scene = start_file.header()['Scene'] take = start_file.header()['Take'] except KeyError: e = sys.exc_info() print "KeyError: metadata key %s not available in EXR file."%e[1] except ValueError as ve: print "ERROR: %s"%ve.message except IOError as ioe: print "WARNING: Image is not in EXR format." end_file = None end_timecode = 0 try:
def calculate_duration(self): tcIn = TimeCode(self.tcIn.text()) tcOut = TimeCode(self.tcOut.text()) if tcOut.frames > tcIn.frames: Dur = tcOut - tcIn self.tcDur.setText(Dur.timecode)
class vlcPlayer(QWidget): message = Signal(str) def __init__(self): super(vlcPlayer, self).__init__() self.vlc_instance = vlc.Instance('-q') # '--verbose 2'.split() self.mPlayer = self.vlc_instance.media_player_new() self.event_manager = self.mPlayer.event_manager() self.currVideoFile = "" self.fileParsed = False self.isPlaying = False self.isSeekable = False self.event_manager.event_attach(EventType.MediaPlayerTimeChanged, self.vlc_event_handle_timeChanged) self.event_manager.event_attach(EventType.MediaPlayerPlaying, self.vlc_event_handle_MediaPlaying) self.event_manager.event_attach(EventType.MediaPlayerPaused, self.vlc_event_handle_MediaPaused) self.event_manager.event_attach(EventType.MediaPlayerEndReached, self.vlc_event_handle_MediaEnded) self.timer = QTimer(self) self.safezone = False self.initUI() def initUI(self): # Main Layout mainlayout = QVBoxLayout() mainlayout.setContentsMargins(0, 0, 0, 0) mainlayout.setMargin(5) mainlayout.setSpacing(0) videoFrame = video_frame() mainlayout.addWidget(videoFrame) vframeID = videoFrame.winId() if sys.platform.startswith('linux'): # linux self.mPlayer.set_xwindow(vframeID) elif sys.platform == "win32": # windows self.mPlayer.set_hwnd(vframeID) elif sys.platform == "darwin": # mac self.mPlayer.set_nsobject(vframeID) # Connect to Slot videoFrame.fileDroped.connect(self.loadVideoFile) vctrl_layout = QHBoxLayout() # Previous Frame btn_pf = QPushButton() btn_pf.setFixedSize(QSize(32, 32)) ico_pf = QIcon(QPixmap(resource_path("icons/previous.png"))) btn_pf.setIcon(ico_pf) btn_pf.clicked.connect(self.previousFrame) # Rewind btn_rewind = QPushButton() btn_rewind.setFixedSize(QSize(32, 32)) ico_re = QIcon(QPixmap(resource_path("icons/rewind.png"))) btn_rewind.setIcon(ico_re) btn_rewind.clicked.connect(self.rewind) # btn_rewind.release.connect(self.playVideo) btn_rewind.setAutoRepeat(True) btn_rewind.setAutoRepeatInterval(1000) btn_rewind.setAutoRepeatDelay(1000) # Play btn_play = QPushButton() btn_play.setFixedSize(QSize(32, 32)) ico_play = QIcon(QPixmap( resource_path("icons/play-button.png"))) # "icons/play-button.png" btn_play.setIcon(ico_play) btn_play.clicked.connect(self.playVideo) # Pause btn_pause = QPushButton() btn_pause.setFixedSize(QSize(32, 32)) ico_pause = QIcon(QPixmap(resource_path("icons/pause-button.png"))) btn_pause.setIcon(ico_pause) btn_pause.clicked.connect(self.pauseVideo) # Fast Forward btn_ff = QPushButton() btn_ff.setFixedSize(QSize(32, 32)) ico_ff = QIcon(QPixmap(resource_path("icons/fast-forward.png"))) btn_ff.setIcon(ico_ff) btn_ff.clicked.connect(self.fastforward) # Next Frame btn_nf = QPushButton() btn_nf.setFixedSize(QSize(32, 32)) ico_nf = QIcon(QPixmap(resource_path("icons/next.png"))) btn_nf.setIcon(ico_nf) btn_nf.clicked.connect(self.nextFrame) # Video Lenght Slider self.video_slider = QSlider(Qt.Orientation.Horizontal) self.video_slider.setMinimum(0) self.video_slider.setMaximum(1000) # Rough # self.video_slider.sliderPressed.connect(self.pauseVideo) self.video_slider.sliderMoved.connect(self.vslider_moved) self.video_slider.sliderReleased.connect(self.vslider_released) # self.video_slider.valueChanged.connect(self.sliderChanged) # Duration self.tcPos = QLabel("00:00:00:00") self.tcPos.setMaximumHeight(20) self.tcPos.setStyleSheet("border: 1px solid black") vctrl_layout.addWidget(btn_pf) vctrl_layout.addWidget(btn_rewind) vctrl_layout.addWidget(btn_play) vctrl_layout.addWidget(btn_pause) vctrl_layout.addWidget(btn_ff) vctrl_layout.addWidget(btn_nf) vctrl_layout.addWidget(self.video_slider) vctrl_layout.addWidget(self.tcPos) mainlayout.addLayout(vctrl_layout, 1) self.setLayout(mainlayout) self.show() self.timer.setInterval(200) self.timer.timeout.connect(self.vslider_posUpdate) # Disable Controls # btn_rewind.setDisabled(True) @Slot(str) def loadVideoFile(self, videoFile): self.fileParsed = False t_media = self.vlc_instance.media_new(videoFile) self.mPlayer.set_media(t_media) self.mPlayer.video_set_aspect_ratio(b"16:9") t_media.parse_with_options(1, 0) sleep(1) # Time to parse video if t_media.get_parsed_status() == vlc.MediaParsedStatus().done: self.fileParsed = True self.currVideoFile = videoFile self.message.emit(f"{path.basename(videoFile)} Loaded!") self.dur = t_media.get_duration() / 1000 # video duration in seconds self.video_duration = TimeCode() self.video_duration.setSecs(self.dur) # self.video_slider.setMaximum(floor(self.dur)) self.tcPos.setText(self.video_duration.getTimeCode()) # self.set_subtitle_file("/Users/promo3/Desktop/PHB0138.srt") def set_subtitle_file(self, filename) -> bool: final_path = f"file://{filename}" # https://github.com/caprica/vlcj/issues/497 # 0 for subtitle 1 for audio vlc.MediaSlaveType(0) x = vlc.libvlc_media_player_add_slave(self.mPlayer, 0, str_to_bytes(final_path), True) if x == 0: return True else: return False def get_video_size(self): if self.fileParsed: return vlc.libvlc_video_get_size(self.mPlayer, 0) def getPosition(self): # More accurate video position newPos = self.mPlayer.get_time() / 1000 self.currPos = TimeCode() self.currPos.setSecs(newPos) return newPos def vlc_event_handle_timeChanged(self, event): # MediaPlayerTimeChanged self.getPosition() self.tcPos.setText(self.currPos.timecode) def vlc_event_handle_MediaParsed( self, event): # vlc ParseChanged event never fires pass def vlc_event_handle_MediaPlaying(self, event): # MediaPlayerPlaying # Processing event.u causes Segmentation 11 errors self.isPlaying = True self.message.emit(f"Video Playing!") def vlc_event_handle_MediaPaused(self, event): # MediaPlayerPaused self.isPlaying = False self.message.emit(f"Video Paused!") def vlc_event_handle_MediaEnded(self, event): # MediaPlayerEndReached self.isPlaying = False self.isSeekable = False self.message.emit("Video End Reached!") def playVideo(self): if not self.isPlaying: self.mPlayer.play() self.timer.start() if self.isSeekable == False: # Check once if self.mPlayer.is_seekable() == 1: self.isSeekable = True sleep(1) else: self.mPlayer.set_rate(1.0) @Slot() def pauseVideo(self): if self.isPlaying and self.mPlayer.can_pause(): self.mPlayer.pause() self.timer.stop() self.mPlayer.set_rate(1.0) @Slot() def nextFrame(self): if not self.isPlaying and self.isSeekable: self.mPlayer.next_frame() tc = TimeCode() tc.setTimeCode(self.tcPos.text()) tc += 1 self.tcPos.setText(tc.timecode) self.tcPos.repaint() @Slot() def previousFrame(self): if not self.isPlaying and self.isSeekable: currPos = self.mPlayer.get_position() # Not accurate self.mPlayer.set_position(currPos - 0.001) self.getPosition() self.tcPos.setText(self.currPos.timecode) self.tcPos.repaint() @Slot() def fastforward(self): curPlayRate = self.mPlayer.get_rate() self.mPlayer.set_rate(curPlayRate * 2) @Slot() def rewind(self): if self.isPlaying: self.pauseVideo() currPos = self.mPlayer.get_position() # Not accurate # print("Seeking to ", currPos-0.1) self.mPlayer.set_position(currPos - 0.01) pos_msecs = self.getPosition() self.tcPos.setText(self.currPos.timecode) self.tcPos.repaint() self.video_slider.setSliderPosition(floor(pos_msecs)) def vslider_moved(self, position): self.mPlayer.set_position(position / 1000) def vslider_released(self): self.mPlayer.play() def vslider_posUpdate(self): self.video_slider.setSliderPosition(self.mPlayer.get_position() * 1000) self.video_slider.repaint() @Slot() def play_pause(self): if self.fileParsed: if not self.isPlaying: self.mPlayer.play() self.timer.start() if self.isSeekable == False: # Check once if self.mPlayer.is_seekable() == 1: self.isSeekable = True else: self.mPlayer.pause() self.timer.stop() sleep(1) self.mPlayer.set_rate(1.0) @Slot() def load_video(self): file_dialog = QFileDialog(self, "Open Video File") selected_file = file_dialog.getOpenFileName() if selected_file: self.loadVideoFile(selected_file[0]) def set_overlay_text(self, text): # Timeout and Refresh options available self.mPlayer.video_set_marquee_int(VideoMarqueeOption.Enable, 1) self.mPlayer.video_set_marquee_int(VideoMarqueeOption.Size, 20) self.mPlayer.video_set_marquee_int(VideoMarqueeOption.Position, Position.Bottom + Position.Center) self.mPlayer.video_set_marquee_string(VideoMarqueeOption.Text, str_to_bytes(text)) @Slot() def set_overlay_safezone(self): if not self.safezone: self.mPlayer.video_set_logo_int(VideoLogoOption.logo_enable, 1) self.mPlayer.video_set_logo_string( VideoLogoOption.logo_file, str_to_bytes( resource_path("icons/camera_safe_areas_646x360.png"))) self.safezone = True else: self.mPlayer.video_set_logo_int(VideoLogoOption.logo_enable, 0) self.safezone = False
def getPosition(self): # More accurate video position newPos = self.mPlayer.get_time() / 1000 self.currPos = TimeCode() self.currPos.setSecs(newPos) return newPos
def load_from_filesystem(self): hires_path = self.version_data['dbversion'].g_path_to_frames delivery_root = os.path.dirname(os.path.dirname(hires_path)) if os.path.basename(os.path.dirname(delivery_root)) != 'delivery': raise Exception( "Hires frames must be located in the delivery subfolder of the shot. Alternative paths are not supported at this time. This version\'s hires frames are located here: %s" % os.path.dirname(delivery_root)) tmp_xmlfile = os.path.join( delivery_root, 'support_files', '%s.xml' % self.version_data['dbversion'].g_version_code) if not os.path.exists(tmp_xmlfile): raise Exception("Unable to locate XML file at %s" % tmp_xmlfile) self.version_data['xmlfile'] = tmp_xmlfile xmlfile_handle = open(tmp_xmlfile) xml_data = xmlfile_handle.read() xmlfile_handle.close() root = ET.fromstring(xml_data) dsub_dict = {} for element in root.getchildren(): dsub_dict[element.tag] = element.text self.version_data['shot'] = dsub_dict['Shot'] try: self.version_data['avidqt'] = os.path.join( delivery_root, 'mov', dsub_dict['AvidQTFileName']) self.version_data['avidqt_base'] = dsub_dict['AvidQTFileName'] self.version_data['lores_ext'] = os.path.splitext( dsub_dict['AvidQTFileName'])[1].lstrip('.') self.version_data['b_avidqt'] = True except KeyError: self.version_data['lores_ext'] = 'mov' pass try: self.version_data['vfxqt'] = os.path.join( delivery_root, 'mov', dsub_dict['VFXQTFileName']) self.version_data['vfxqt_base'] = dsub_dict['VFXQTFileName'] self.version_data['b_vfxqt'] = True except KeyError: pass try: self.version_data['exportqt'] = os.path.join( delivery_root, 'mov', dsub_dict['ExportQTFileName']) self.version_data['exportqt_base'] = dsub_dict['ExportQTFileName'] self.version_data['b_exportqt'] = True except KeyError: pass self.version_data['b_hires'] = False try: self.version_data['hires_format'] = dsub_dict['HiResFormat'] self.version_data['hires'] = hires_path.replace('%04d', '*') self.version_data['hires_ext'] = os.path.splitext( hires_path)[1].replace('.', '') self.version_data['b_hires'] = True except KeyError: self.version_data['hires_format'] = '1920x1080' self.version_data['hires'] = 'NO_HIRES_FRAMES' self.version_data['hires_ext'] = 'NO_HIRES' self.version_data['b_hires'] = False try: self.version_data['matte'] = os.path.join( delivery_root, 'matte', dsub_dict['MatteFileName']) self.version_data['matte_ext'] = os.path.splitext( dsub_dict['MatteFileName'])[1].replace('.', '') self.version_data['b_matte'] = True except KeyError: pass self.version_data['start_frame'] = int(dsub_dict['StartFrame']) self.version_data['end_frame'] = int(dsub_dict['EndFrame']) self.version_data['duration'] = self.version_data[ 'end_frame'] - self.version_data['start_frame'] + 1 self.version_data['start_tc'] = TimeCode(dsub_dict['StartTimeCode']) self.version_data['end_tc'] = TimeCode(dsub_dict['EndTimeCode']) self.version_data['artist'] = dsub_dict['Artist'] self.version_data['notes'] = dsub_dict['SubmissionNotes'] version_re_text = '%s([0-9]+)' % self.version_data['version_separator'] try: self.version_data['version_number'] = int( re.search( version_re_text, self.version_data['dbversion'].g_version_code).group(1)) except: pass # try and find a .CC file ccfiles = glob.glob( os.path.join(delivery_root, 'support_files', '*.c*')) b_use_default_cc = True if len(ccfiles) > 0: fileext = os.path.splitext(ccfiles[0])[-1] if fileext not in ['.ccc', '.cc', '.cdl']: self.log_message( m_log_level='warning', m_log_message= 'Color Correction file at %s is NOT an XML file. Skipping.' % ccfiles[0]) else: b_use_default_cc = False self.log_message(m_log_level='info', m_log_message='Using CC file located at %s.' % ccfiles[0]) self.version_data['ccfile'] = ccfiles[0] self.version_data['ccdata'] = CCData(ccfiles[0]) if b_use_default_cc: __location__ = os.path.realpath( os.path.join(os.getcwd(), os.path.dirname(__file__))) self.log_message(m_log_level='info', m_log_message='Using default CC file at %s.' % os.path.join(__location__, 'default.cc')) self.version_data['ccfile'] = os.path.join(__location__, 'default.cc') self.version_data['ccdata'] = CCData( os.path.join(__location__, 'default.cc'))