def __init__(self, timeline, parent=None): QWidget.__init__(self, parent) self.layout = QVBoxLayout() self.setLayout(self.layout) # Setup video preview QWidget self.videoPreview = VideoWidget(self) self.layout.addWidget(self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height()) timeline.SetMaxSize(viewport_rect.width(), viewport_rect.height()) self.setLayout(self.layout) self.initialized = False # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, timeline, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set pause callback self.PauseSignal.connect(self.handlePausedVideo) self.hover = YYPlayerHover(self, self)
def __init__(self): QWidget.__init__(self) # Setup video preview QWidget self.videoPreview = VideoWidget() #self.layout().insertWidget(0, self.videoPreview) wlayout = QHBoxLayout() wlayout.addWidget(self.videoPreview) self.setLayout(wlayout) # Start the preview thread self.preview_parent = PreviewParent(self) self.preview_parent.MInit(self, self.videoPreview) self.preview_thread = self.preview_parent.worker self.setFixedSize(600, 800) self.initialized = True
def __init__(self, cuts_json, clips_json, preview=False): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") # If preview, hide cutting controls if preview: self.lblInstructions.setVisible(False) self.widgetControls.setVisible(False) self.setWindowTitle(_("Preview")) self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None project = get_app().project # Keep track of file object #self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) self.width = int(file.data['width']) self.height = int(file.data['height']) self.sample_rate = int(file.data['sample_rate']) self.channels = int(file.data['channels']) self.channel_layout = int(file.data['channel_layout']) # Open video file with Reader log.info(self.file_path) # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline( self.width, self.height, openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout try: # Add clip for current preview file self.clip = openshot.Clip(self.file_path) # Show waveform for audio files if not self.clip.Reader().info.has_video and self.clip.Reader( ).info.has_audio: self.clip.Waveform(True) # Set has_audio property self.r.info.has_audio = self.clip.Reader().info.has_audio if preview: # Display frame #'s during preview self.clip.display = openshot.FRAME_DISPLAY_CLIP self.r.AddClip(self.clip) except: log.error('Failed to load media file into preview player: %s' % self.file_path) return # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport( self.videoPreview.width(), self.videoPreview.height()) self.r.SetMaxSize(viewport_rect.width(), viewport_rect.height()) # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked) self.initialized = True
class YYCutPlayerDlg(QDialog): """ Cutting Dialog """ # Path to ui file ui_path = os.path.join(info.PATH, 'windows', 'ui', 'cutting.ui') # Signals for preview thread previewFrameSignal = pyqtSignal(int) refreshFrameSignal = pyqtSignal() LoadFileSignal = pyqtSignal(str) PlaySignal = pyqtSignal(int) PauseSignal = pyqtSignal() SeekSignal = pyqtSignal(int) SpeedSignal = pyqtSignal(float) StopSignal = pyqtSignal() def __init__(self, cuts_json, clips_json, preview=False): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") # If preview, hide cutting controls if preview: self.lblInstructions.setVisible(False) self.widgetControls.setVisible(False) self.setWindowTitle(_("Preview")) self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None project = get_app().project # Keep track of file object #self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) self.width = int(file.data['width']) self.height = int(file.data['height']) self.sample_rate = int(file.data['sample_rate']) self.channels = int(file.data['channels']) self.channel_layout = int(file.data['channel_layout']) # Open video file with Reader log.info(self.file_path) # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline( self.width, self.height, openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout try: # Add clip for current preview file self.clip = openshot.Clip(self.file_path) # Show waveform for audio files if not self.clip.Reader().info.has_video and self.clip.Reader( ).info.has_audio: self.clip.Waveform(True) # Set has_audio property self.r.info.has_audio = self.clip.Reader().info.has_audio if preview: # Display frame #'s during preview self.clip.display = openshot.FRAME_DISPLAY_CLIP self.r.AddClip(self.clip) except: log.error('Failed to load media file into preview player: %s' % self.file_path) return # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport( self.videoPreview.width(), self.videoPreview.height()) self.r.SetMaxSize(viewport_rect.width(), viewport_rect.height()) # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked) self.initialized = True def actionPlay_Triggered(self): # Trigger play button (This action is invoked from the preview thread, so it must exist here) self.btnPlay.click() def movePlayhead(self, frame_number): """Update the playhead position""" # Move slider to correct frame position self.sliderIgnoreSignal = True self.sliderVideo.setValue(frame_number) self.sliderIgnoreSignal = False # Convert frame to seconds seconds = (frame_number - 1) / self.fps # Convert seconds to time stamp time_text = self.secondsToTime(seconds, self.fps_num, self.fps_den) timestamp = "%s:%s:%s:%s" % (time_text["hour"], time_text["min"], time_text["sec"], time_text["frame"]) # Update label self.lblVideoTime.setText(timestamp) def btnPlay_clicked(self, force=None): log.info("btnPlay_clicked") if force == "pause": self.btnPlay.setChecked(False) elif force == "play": self.btnPlay.setChecked(True) if self.btnPlay.isChecked(): log.info('play (icon to pause)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-pause") self.preview_thread.Play(self.video_length) else: log.info('pause (icon to play)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-start") # to default self.preview_thread.Pause() # Send focus back to toolbar self.sliderVideo.setFocus() def sliderVideo_valueChanged(self, new_frame): if self.preview_thread and not self.sliderIgnoreSignal: log.info('sliderVideo_valueChanged') # Pause video self.btnPlay_clicked(force="pause") # Seek to new frame self.preview_thread.previewFrame(new_frame) def btnStart_clicked(self): """Start of clip button was clicked""" _ = get_app()._tr # Pause video self.btnPlay_clicked(force="pause") # Get the current frame current_frame = self.sliderVideo.value() # Check if starting frame less than end frame if self.btnEnd.isEnabled() and current_frame >= self.end_frame: # Handle exception msg = QMessageBox() msg.setText( _("Please choose valid 'start' and 'end' values for your clip." )) msg.exec_() return # remember frame # self.start_frame = current_frame # Save thumbnail image self.start_image = os.path.join(info.USER_PATH, 'thumbnail', '%s.png' % self.start_frame) self.r.GetFrame(self.start_frame).Thumbnail(self.start_image, 160, 90, '', '', '#000000', True) # Set CSS on button self.btnStart.setStyleSheet('background-image: url(%s);' % self.start_image.replace('\\', '/')) # Enable end button self.btnEnd.setEnabled(True) self.btnClear.setEnabled(True) # Send focus back to toolbar self.sliderVideo.setFocus() log.info('btnStart_clicked, current frame: %s' % self.start_frame) def btnEnd_clicked(self): """End of clip button was clicked""" _ = get_app()._tr # Pause video self.btnPlay_clicked(force="pause") # Get the current frame current_frame = self.sliderVideo.value() # Check if ending frame greater than start frame if current_frame <= self.start_frame: # Handle exception msg = QMessageBox() msg.setText( _("Please choose valid 'start' and 'end' values for your clip." )) msg.exec_() return # remember frame # self.end_frame = current_frame # Save thumbnail image self.end_image = os.path.join(info.USER_PATH, 'thumbnail', '%s.png' % self.end_frame) self.r.GetFrame(self.end_frame).Thumbnail(self.end_image, 160, 90, '', '', '#000000', True) # Set CSS on button self.btnEnd.setStyleSheet('background-image: url(%s);' % self.end_image.replace('\\', '/')) # Enable create button self.btnAddClip.setEnabled(True) # Send focus back to toolbar self.sliderVideo.setFocus() log.info('btnEnd_clicked, current frame: %s' % self.end_frame) def btnClear_clicked(self): """Clear the current clip and reset the form""" log.info('btnClear_clicked') # Reset form self.clearForm() def clearForm(self): """Clear all form controls""" # Clear buttons self.start_frame = 1 self.end_frame = 1 self.start_image = '' self.end_image = '' self.btnStart.setStyleSheet('background-image: None;') self.btnEnd.setStyleSheet('background-image: None;') # Clear text self.txtName.setText('') # Disable buttons self.btnEnd.setEnabled(False) self.btnAddClip.setEnabled(False) self.btnClear.setEnabled(False) def btnAddClip_clicked(self): """Add the selected clip to the project""" log.info('btnAddClip_clicked') # Remove unneeded attributes if 'name' in self.file.data.keys(): self.file.data.pop('name') # Save new file self.file.id = None self.file.key = None self.file.type = 'insert' self.file.data['start'] = (self.start_frame - 1) / self.fps self.file.data['end'] = (self.end_frame - 1) / self.fps if self.txtName.text(): self.file.data['name'] = self.txtName.text() self.file.save() # Reset form self.clearForm() def padNumber(self, value, pad_length): format_mask = '%%0%sd' % pad_length return format_mask % value def secondsToTime(self, secs, fps_num, fps_den): # calculate time of playhead milliseconds = secs * 1000 sec = math.floor(milliseconds / 1000) milli = milliseconds % 1000 min = math.floor(sec / 60) sec = sec % 60 hour = math.floor(min / 60) min = min % 60 day = math.floor(hour / 24) hour = hour % 24 week = math.floor(day / 7) day = day % 7 frame = round((milli / 1000.0) * (fps_num / fps_den)) + 1 return { "week": self.padNumber(week, 2), "day": self.padNumber(day, 2), "hour": self.padNumber(hour, 2), "min": self.padNumber(min, 2), "sec": self.padNumber(sec, 2), "milli": self.padNumber(milli, 2), "frame": self.padNumber(frame, 2) } # TODO: Remove these 4 methods def accept(self): """ Ok button clicked """ log.info('accept') def close(self): """ Actually close window and accept dialog """ log.info('close') def closeEvent(self, event): log.info('closeEvent') # Stop playback self.preview_parent.worker.Stop() # Stop preview thread (and wait for it to end) self.preview_parent.worker.kill() self.preview_parent.background.exit() self.preview_parent.background.wait(5000) # Close readers self.r.Close() self.clip.Close() self.r.ClearAllCache() def reject(self): log.info('reject')
def __init__(self, file=None): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None # Keep track of file object self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) # Open video file with Reader log.info(self.file_path) self.r = openshot.FFmpegReader(self.file_path) self.r.Open() # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot(500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot(600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked)
class Cutting(QDialog): """ Cutting Dialog """ # Path to ui file ui_path = os.path.join(info.PATH, 'windows', 'ui', 'cutting.ui') # Signals for preview thread previewFrameSignal = pyqtSignal(int) refreshFrameSignal = pyqtSignal() LoadFileSignal = pyqtSignal(str) PlaySignal = pyqtSignal() PauseSignal = pyqtSignal() SeekSignal = pyqtSignal(int) SpeedSignal = pyqtSignal(float) def __init__(self, file=None): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None # Keep track of file object self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) # Open video file with Reader log.info(self.file_path) self.r = openshot.FFmpegReader(self.file_path) self.r.Open() # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot(500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot(600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked) def movePlayhead(self, frame_number): """Update the playhead position""" # Move slider to correct frame position self.sliderIgnoreSignal = True self.sliderVideo.setValue(frame_number) self.sliderIgnoreSignal = False # Convert frame to seconds seconds = (frame_number-1) / self.fps # Convert seconds to time stamp time_text = self.secondsToTime(seconds, self.fps_num, self.fps_den) timestamp = "%s:%s:%s:%s" % (time_text["hour"], time_text["min"], time_text["sec"], time_text["frame"]) # Update label self.lblVideoTime.setText(timestamp) def btnPlay_clicked(self, force=None): log.info("btnPlay_clicked") if force == "pause": self.btnPlay.setChecked(False) elif force == "play": self.btnPlay.setChecked(True) if self.btnPlay.isChecked(): log.info('play (icon to pause)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-pause") self.preview_thread.Play() else: log.info('pause (icon to play)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-start") # to default self.preview_thread.Pause() def sliderVideo_valueChanged(self, new_frame): if self.preview_thread and not self.sliderIgnoreSignal: log.info('sliderVideo_valueChanged') # Pause video self.btnPlay_clicked(force="pause") # Seek to new frame self.preview_thread.previewFrame(new_frame) def btnStart_clicked(self): """Start of clip button was clicked""" _ = get_app()._tr # Pause video self.btnPlay_clicked(force="pause") # Get the current frame current_frame = self.sliderVideo.value() # Check if starting frame less than end frame if self.btnEnd.isEnabled() and current_frame >= self.end_frame: # Handle exception msg = QMessageBox() msg.setText(_("Please choose valid 'start' and 'end' values for your clip.")) msg.exec_() return # remember frame # self.start_frame = current_frame # Save thumbnail image self.start_image = os.path.join(info.USER_PATH, 'thumbnail', '%s.png' % self.start_frame) self.r.GetFrame(self.start_frame).Thumbnail(self.start_image, 160, 90, '', '', '#000000', True) # Set CSS on button self.btnStart.setStyleSheet('background-image: url(%s);' % self.start_image.replace('\\', '/')) # Enable end button self.btnEnd.setEnabled(True) self.btnClear.setEnabled(True) log.info('btnStart_clicked, current frame: %s' % self.start_frame) def btnEnd_clicked(self): """End of clip button was clicked""" _ = get_app()._tr # Pause video self.btnPlay_clicked(force="pause") # Get the current frame current_frame = self.sliderVideo.value() # Check if ending frame greater than start frame if current_frame <= self.start_frame: # Handle exception msg = QMessageBox() msg.setText(_("Please choose valid 'start' and 'end' values for your clip.")) msg.exec_() return # remember frame # self.end_frame = current_frame # Save thumbnail image self.end_image = os.path.join(info.USER_PATH, 'thumbnail', '%s.png' % self.end_frame) self.r.GetFrame(self.end_frame).Thumbnail(self.end_image, 160, 90, '', '', '#000000', True) # Set CSS on button self.btnEnd.setStyleSheet('background-image: url(%s);' % self.end_image.replace('\\', '/')) # Enable create button self.btnAddClip.setEnabled(True) log.info('btnEnd_clicked, current frame: %s' % self.end_frame) def btnClear_clicked(self): """Clear the current clip and reset the form""" log.info('btnClear_clicked') # Reset form self.clearForm() def clearForm(self): """Clear all form controls""" # Clear buttons self.start_frame = 1 self.end_frame = 1 self.start_image = '' self.end_image = '' self.btnStart.setStyleSheet('background-image: None;') self.btnEnd.setStyleSheet('background-image: None;') # Clear text self.txtName.setText('') # Disable buttons self.btnEnd.setEnabled(False) self.btnAddClip.setEnabled(False) self.btnClear.setEnabled(False) def btnAddClip_clicked(self): """Add the selected clip to the project""" log.info('btnAddClip_clicked') # Remove unneeded attributes if 'name' in self.file.data.keys(): self.file.data.pop('name') # Save new file self.file.id = None self.file.key = None self.file.type = 'insert' self.file.data['start'] = (self.start_frame-1) / self.fps self.file.data['end'] = (self.end_frame-1) / self.fps if self.txtName.text(): self.file.data['name'] = self.txtName.text() self.file.save() # Reset form self.clearForm() def padNumber(self, value, pad_length): format_mask = '%%0%sd' % pad_length return format_mask % value def secondsToTime(self, secs, fps_num, fps_den): # calculate time of playhead milliseconds = secs * 1000 sec = math.floor(milliseconds/1000) milli = milliseconds % 1000 min = math.floor(sec/60) sec = sec % 60 hour = math.floor(min/60) min = min % 60 day = math.floor(hour/24) hour = hour % 24 week = math.floor(day/7) day = day % 7 frame = round((milli / 1000.0) * (fps_num / fps_den)) + 1 return { "week":self.padNumber(week,2), "day":self.padNumber(day,2), "hour":self.padNumber(hour,2), "min":self.padNumber(min,2), "sec":self.padNumber(sec,2), "milli":self.padNumber(milli,2), "frame":self.padNumber(frame,2) }; # TODO: Remove these 4 methods def accept(self): """ Ok button clicked """ log.info('accept') def close(self): """ Actually close window and accept dialog """ log.info('close') def closeEvent(self, event): log.info('closeEvent') # Stop preview and kill thread self.preview_parent.worker.Pause() self.preview_parent.worker.kill() # Wait for thread self.preview_parent.background.wait(250) # Stop reader self.r.Close() def reject(self): log.info('reject')
def __init__(self, file=None): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None # Keep track of file object self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) # Open video file with Reader log.info(self.file_path) self.r = openshot.FFmpegReader(self.file_path) self.r.Open() # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked)
class YYPlayerBaseWidget(QWidget, updates.UpdateWatcher): previewFrameSignal = pyqtSignal(int) refreshFrameSignal = pyqtSignal() LoadFileSignal = pyqtSignal(str) PlaySignal = pyqtSignal(int) PauseSignal = pyqtSignal() StopSignal = pyqtSignal() SeekSignal = pyqtSignal(int) SpeedSignal = pyqtSignal(float) movePlayheadSignal = pyqtSignal(float) PlayModeChangedSignal = pyqtSignal(int) MaxSizeChanged = pyqtSignal(object) def __init__(self, timeline, parent=None): QWidget.__init__(self, parent) self.layout = QVBoxLayout() self.setLayout(self.layout) # Setup video preview QWidget self.videoPreview = VideoWidget(self) self.layout.addWidget(self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height()) timeline.SetMaxSize(viewport_rect.width(), viewport_rect.height()) self.setLayout(self.layout) self.initialized = False # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, timeline, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set pause callback self.PauseSignal.connect(self.handlePausedVideo) self.hover = YYPlayerHover(self, self) # Save window settings on close def closeEvent(self, event): # Stop threads self.StopSignal.emit() # Process any queued events QCoreApplication.processEvents() # Stop preview thread (and wait for it to end) self.preview_thread.player.CloseAudioDevice() self.preview_thread.kill() self.preview_parent.background.exit() self.preview_parent.background.wait(5000) def btnPlay_clicked(self, force=None): log.info("btnPlay_clicked") if force == "pause": self.hover.btnPlay.setChecked(False) elif force == "play": self.hover.btnPlay.setChecked(True) if self.hover.btnPlay.isChecked(): log.info('play (icon to pause)') #ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-pause") self.preview_thread.Play(1000)#======todo else: log.info('pause (icon to play)') #ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-start") # to default self.preview_thread.Pause() # Send focus back to toolbar #self.sliderVideo.setFocus() def resizeEvent(self, QResizeEvent): super().resizeEvent(QResizeEvent) self.hover.setGeometry((self.width() - self.hover.width()) / 2, 20, self.hover.width(), self.hover.height()) def onModeChanged(self, current_mode): log.info('onModeChanged %s', current_mode) self.PlayModeChangedSignal.emit(current_mode) def Mode(self): return self.preview_thread.player.Mode() def handlePausedVideo(self): log.info("base handlePausedVideo") def onPlayFinished(self): log.info("base onPlayFinished") def movePlayhead(self, position_frames): log.info("movePlayhead %s", position_frames) """Update playhead position"""
def __init__(self, cuts=[], preview=False): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") # If preview, hide cutting controls if preview: self.lblInstructions.setVisible(False) self.widgetControls.setVisible(False) self.setWindowTitle(_("Preview")) self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None #timeline = get_app().window.timeline_sync.timeline #app = get_app() #project = app.project # Get some settings from the project ''' self.fps = project.get(["fps"]) self.width = project.get(["width"]) self.height = project.get(["height"]) self.sample_rate = project.get(["sample_rate"]) self.channels = project.get(["channels"]) self.channel_layout = project.get(["channel_layout"]) self.fps_num = int(self.fps['num']) self.fps_den = int(self.fps['den']) self.fps = float(self.fps_num) / float(self.fps_den) ''' # Get the original timeline settings self.width = get_app().window.timeline_sync.timeline.info.width self.height = get_app().window.timeline_sync.timeline.info.height self.fps = get_app().window.timeline_sync.timeline.info.fps self.sample_rate = get_app( ).window.timeline_sync.timeline.info.sample_rate self.channels = get_app().window.timeline_sync.timeline.info.channels self.channel_layout = get_app( ).window.timeline_sync.timeline.info.channel_layout self.fps_num = int(self.fps.num) self.fps_den = int(self.fps.den) #self.fps = float(self.fps_num) / float(self.fps_den) ''' # Keep track of file object self.file = file self.file_path = file.absolute_path() self.video_length = 0 self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) self.width = int(file.data['width']) self.height = int(file.data['height']) self.sample_rate = int(file.data['sample_rate']) self.channels = int(file.data['channels']) self.channel_layout = int(file.data['channel_layout']) # Open video file with Reader log.info(self.file_path) ''' self.video_length = 0 # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline( self.width, self.height, openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout ''' #cuts = [{"start_seconds":8.466666666666667, "end_seconds":15.3}, {"start_seconds":18.9, "end_seconds":22.133333333333333}] position = 0 print(cuts) cs = app.window.timeline_sync.timeline.Clips() for c in cs: print("-----id=", c.Id()) clip_json = Clip.filter(id=c.Id()) path = clip_json[0].data["reader"]["path"] print("==============", path, c.Position()) offset = c.Position() for cut in cuts: try: # Add clip for current preview file clip = openshot.Clip(path) self.clips.append(clip) # Show waveform for audio files if not clip.Reader().info.has_video and clip.Reader().info.has_audio: clip.Waveform(True) # Set has_audio property self.r.info.has_audio = clip.Reader().info.has_audio if preview: # Display frame #'s during preview clip.display = openshot.FRAME_DISPLAY_CLIP start = float(cut["start_seconds"] - offset) end = float(cut["end_seconds"] - offset) print("=======================-------start:", start, "end:", end) clip.Start(start) clip.End(end) #clip.Position(0) clip.Position(position) position = position + (end - start) - offset #clip.Duration(end-start) self.r.AddClip(clip) self.video_length = self.video_length + (end - start) except: log.error('Failed to load media file into preview player: %s' % self.file_path) return ''' self.clips, self.video_length = CutsToClips(cuts) for clip in self.clips: # Show waveform for audio files if not clip.Reader().info.has_video and clip.Reader( ).info.has_audio: clip.Waveform(True) if preview: # Display frame #'s during preview clip.display = openshot.FRAME_DISPLAY_CLIP self.r.AddClip(clip) #self.video_length = self.video_length * self.fps_num / self.fps_den # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport( self.videoPreview.width(), self.videoPreview.height()) self.r.SetMaxSize(viewport_rect.width(), viewport_rect.height()) # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 #if 'start' in self.file.data.keys(): # start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked) self.initialized = True
def __init__(self, file=None, clip=None): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None self.current_frame = 1 # Create region clip with Reader self.clip = openshot.Clip(clip.Reader()) self.clip.Open() # Set region clip start and end self.clip.Start(clip.Start()) self.clip.End(clip.End()) self.clip.Id(get_app().project.generate_id()) print("IDS {} {}".format(clip.Id(), self.clip.Id())) # Keep track of file object self.file = file self.file_path = file.absolute_path() c_info = clip.Reader().info self.fps = c_info.fps.ToInt( ) #float(self.fps_num) / float(self.fps_den) self.fps_num = self.fps #int(file.data['fps']['num']) self.fps_den = 1 #int(file.data['fps']['den']) self.width = c_info.width #int(file.data['width']) self.height = c_info.height #int(file.data['height']) self.sample_rate = c_info.sample_rate #int(file.data['sample_rate']) self.channels = c_info.channels #int(file.data['channels']) self.channel_layout = c_info.channel_layout #int(file.data['channel_layout']) self.video_length = int(self.clip.Duration() * self.fps) + 1 #int(file.data['video_length']) # Apply effects to region frames for effect in clip.Effects(): self.clip.AddEffect(effect) # Open video file with Reader log.info(self.clip.Reader()) # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set aspect ratio to match source content aspect_ratio = openshot.Fraction(self.width, self.height) aspect_ratio.Reduce() self.videoPreview.aspect_ratio = aspect_ratio # Set max size of video preview (for speed) self.viewport_rect = self.videoPreview.centeredViewport( self.width, self.height) # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline( self.viewport_rect.width(), self.viewport_rect.height(), openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout self.r.SetMaxSize(self.viewport_rect.width(), self.viewport_rect.height()) try: # Add clip for current preview file self.clip = openshot.Clip(self.file_path) # Show waveform for audio files if not self.clip.Reader().info.has_video and self.clip.Reader( ).info.has_audio: self.clip.Waveform(True) # Set has_audio property self.r.info.has_audio = self.clip.Reader().info.has_audio # Update video_length property of the Timeline object self.r.info.video_length = self.video_length self.r.AddClip(self.clip) except: log.error( 'Failed to load media file into region select player: %s' % self.file_path) return # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 # if 'start' in self.file.data.keys(): # start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Add buttons self.cancel_button = QPushButton(_('Cancel')) self.process_button = QPushButton(_('Select Region')) self.buttonBox.addButton(self.process_button, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(self.cancel_button, QDialogButtonBox.RejectRole) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.initialized = True get_app().window.SelectRegionSignal.emit(clip.Id())
class SelectRegion(QDialog): """ SelectRegion Dialog """ # Path to ui file ui_path = os.path.join(info.PATH, 'windows', 'ui', 'region.ui') # Signals for preview thread previewFrameSignal = pyqtSignal(int) refreshFrameSignal = pyqtSignal() LoadFileSignal = pyqtSignal(str) PlaySignal = pyqtSignal(int) PauseSignal = pyqtSignal() SeekSignal = pyqtSignal(int) SpeedSignal = pyqtSignal(float) StopSignal = pyqtSignal() def __init__(self, file=None, clip=None): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None self.current_frame = 1 # Create region clip with Reader self.clip = openshot.Clip(clip.Reader()) self.clip.Open() # Set region clip start and end self.clip.Start(clip.Start()) self.clip.End(clip.End()) self.clip.Id(get_app().project.generate_id()) print("IDS {} {}".format(clip.Id(), self.clip.Id())) # Keep track of file object self.file = file self.file_path = file.absolute_path() c_info = clip.Reader().info self.fps = c_info.fps.ToInt( ) #float(self.fps_num) / float(self.fps_den) self.fps_num = self.fps #int(file.data['fps']['num']) self.fps_den = 1 #int(file.data['fps']['den']) self.width = c_info.width #int(file.data['width']) self.height = c_info.height #int(file.data['height']) self.sample_rate = c_info.sample_rate #int(file.data['sample_rate']) self.channels = c_info.channels #int(file.data['channels']) self.channel_layout = c_info.channel_layout #int(file.data['channel_layout']) self.video_length = int(self.clip.Duration() * self.fps) + 1 #int(file.data['video_length']) # Apply effects to region frames for effect in clip.Effects(): self.clip.AddEffect(effect) # Open video file with Reader log.info(self.clip.Reader()) # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set aspect ratio to match source content aspect_ratio = openshot.Fraction(self.width, self.height) aspect_ratio.Reduce() self.videoPreview.aspect_ratio = aspect_ratio # Set max size of video preview (for speed) self.viewport_rect = self.videoPreview.centeredViewport( self.width, self.height) # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline( self.viewport_rect.width(), self.viewport_rect.height(), openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout self.r.SetMaxSize(self.viewport_rect.width(), self.viewport_rect.height()) try: # Add clip for current preview file self.clip = openshot.Clip(self.file_path) # Show waveform for audio files if not self.clip.Reader().info.has_video and self.clip.Reader( ).info.has_audio: self.clip.Waveform(True) # Set has_audio property self.r.info.has_audio = self.clip.Reader().info.has_audio # Update video_length property of the Timeline object self.r.info.video_length = self.video_length self.r.AddClip(self.clip) except: log.error( 'Failed to load media file into region select player: %s' % self.file_path) return # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 # if 'start' in self.file.data.keys(): # start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot( 500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot( 600, functools.partial(self.sliderVideo.setValue, start_frame)) # Add buttons self.cancel_button = QPushButton(_('Cancel')) self.process_button = QPushButton(_('Select Region')) self.buttonBox.addButton(self.process_button, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(self.cancel_button, QDialogButtonBox.RejectRole) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.initialized = True get_app().window.SelectRegionSignal.emit(clip.Id()) def actionPlay_Triggered(self): # Trigger play button (This action is invoked from the preview thread, so it must exist here) self.btnPlay.click() def movePlayhead(self, frame_number): """Update the playhead position""" self.current_frame = frame_number # Move slider to correct frame position self.sliderIgnoreSignal = True self.sliderVideo.setValue(frame_number) self.sliderIgnoreSignal = False # Convert frame to seconds seconds = (frame_number - 1) / self.fps # Convert seconds to time stamp time_text = time_parts.secondsToTime(seconds, self.fps_num, self.fps_den) timestamp = "%s:%s:%s:%s" % (time_text["hour"], time_text["min"], time_text["sec"], time_text["frame"]) # Update label self.lblVideoTime.setText(timestamp) def btnPlay_clicked(self, force=None): log.info("btnPlay_clicked") if force == "pause": self.btnPlay.setChecked(False) elif force == "play": self.btnPlay.setChecked(True) if self.btnPlay.isChecked(): log.info('play (icon to pause)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-pause") self.preview_thread.Play(self.video_length) else: log.info('pause (icon to play)') ui_util.setup_icon(self, self.btnPlay, "actionPlay", "media-playback-start") # to default self.preview_thread.Pause() # Send focus back to toolbar self.sliderVideo.setFocus() def sliderVideo_valueChanged(self, new_frame): if self.preview_thread and not self.sliderIgnoreSignal: log.info('sliderVideo_valueChanged') # Pause video self.btnPlay_clicked(force="pause") # Seek to new frame self.preview_thread.previewFrame(new_frame) def accept(self): """ Ok button clicked """ self.shutdownPlayer() get_app().window.SelectRegionSignal.emit("") super(SelectRegion, self).accept() def shutdownPlayer(self): log.info('shutdownPlayer') # Stop playback self.preview_parent.worker.Stop() # Stop preview thread (and wait for it to end) self.preview_parent.worker.kill() self.preview_parent.background.exit() self.preview_parent.background.wait(5000) # Close readers self.clip.Close() # self.r.RemoveClip(self.clip) self.r.Close() # self.clip.Close() self.r.ClearAllCache() def reject(self): # Cancel dialog self.shutdownPlayer() get_app().window.SelectRegionSignal.emit("") super(SelectRegion, self).reject()
def __init__(self, mode=None): # Create main window base class QMainWindow.__init__(self) self.initialized = False # set window on app for reference during initialization of children get_app().window = self _ = get_app()._tr # Track metrics track_metric_session() # start session # Load user settings for window s = settings.get_settings() # Load UI from designer ui_util.load_ui(self, self.ui_path) # Set all keyboard shortcuts from the settings file #self.InitKeyboardShortcuts() # Init UI ui_util.init_ui(self) # Setup toolbars that aren't on main window, set initial state of items, etc self.setup_toolbars() # Add window as watcher to receive undo/redo status updates get_app().updates.add_watcher(self) # Create the timeline sync object (used for previewing timeline) self.timeline_sync = TimelineSync(self) # Setup timeline self.timeline = TimelineWebView(self) self.frameWeb.layout().addWidget(self.timeline) # Configure the side docks to full-height self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea) # Process events before continuing # TODO: Figure out why this is needed for a backup recovery to correctly show up on the timeline get_app().processEvents() # Setup video preview QWidget self.videoPreview = VideoWidget() self.tabVideo.layout().insertWidget(0, self.videoPreview) # Load window state and geometry #self.load_settings() # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.timeline_sync.timeline, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set pause callback self.PauseSignal.connect(self.handlePausedVideo) # QTimer for Autosave self.auto_save_timer = QTimer(self) self.auto_save_timer.setInterval( s.get("autosave-interval") * 1000 * 60) self.auto_save_timer.timeout.connect(self.auto_save_project) if s.get("enable-auto-save"): self.auto_save_timer.start() # Set hardware decode if s.get("hardware_decode"): openshot.Settings.Instance().HARDWARE_DECODE = True else: openshot.Settings.Instance().HARDWARE_DECODE = False # Set hardware encode if s.get("hardware_encode"): openshot.Settings.Instance().HARDWARE_ENCODE = True else: openshot.Settings.Instance().HARDWARE_ENCODE = False # Set OMP thread enabled flag (for stability) if s.get("omp_threads_enabled"): openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = False else: openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = True # Set scaling mode to lower quality scaling (for faster previews) openshot.Settings.Instance().HIGH_QUALITY_SCALING = False # Create lock file self.create_lock_file() # Connect OpenProject Signal self.OpenProjectSignal.connect(self.open_project) # Show window self.show() # Save settings s.save() # Refresh frame QTimer.singleShot(100, self.refreshFrameSignal.emit) # Main window is initialized self.initialized = True
def __init__(self, file=None, preview=False): _ = get_app()._tr # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # Track metrics track_metric_screen("cutting-screen") # If preview, hide cutting controls if preview: self.lblInstructions.setVisible(False) self.widgetControls.setVisible(False) self.setWindowTitle(_("Preview")) self.start_frame = 1 self.start_image = None self.end_frame = 1 self.end_image = None # Keep track of file object self.file = file self.file_path = file.absolute_path() self.video_length = int(file.data['video_length']) self.fps_num = int(file.data['fps']['num']) self.fps_den = int(file.data['fps']['den']) self.fps = float(self.fps_num) / float(self.fps_den) self.width = int(file.data['width']) self.height = int(file.data['height']) self.sample_rate = int(file.data['sample_rate']) self.channels = int(file.data['channels']) self.channel_layout = int(file.data['channel_layout']) # Open video file with Reader log.info(self.file_path) # Create an instance of a libopenshot Timeline object self.r = openshot.Timeline(self.width, self.height, openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate, self.channels, self.channel_layout) self.r.info.channel_layout = self.channel_layout try: # Add clip for current preview file self.clip = openshot.Clip(self.file_path) # Show waveform for audio files if not self.clip.Reader().info.has_video and self.clip.Reader().info.has_audio: self.clip.Waveform(True) # Set has_audio property self.r.info.has_audio = self.clip.Reader().info.has_audio if preview: # Display frame #'s during preview self.clip.display = openshot.FRAME_DISPLAY_CLIP self.r.AddClip(self.clip) except: log.error('Failed to load media file into preview player: %s' % self.file_path) return # Add Video Widget self.videoPreview = VideoWidget() self.videoPreview.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.verticalLayout.insertWidget(0, self.videoPreview) # Set max size of video preview (for speed) viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height()) self.r.SetMaxSize(viewport_rect.width(), viewport_rect.height()) # Open reader self.r.Open() # Start the preview thread self.initialized = False self.transforming_clip = False self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.r, self.videoPreview) self.preview_thread = self.preview_parent.worker # Set slider constraints self.sliderIgnoreSignal = False self.sliderVideo.setMinimum(1) self.sliderVideo.setMaximum(self.video_length) self.sliderVideo.setSingleStep(1) self.sliderVideo.setSingleStep(1) self.sliderVideo.setPageStep(24) # Determine if a start or end attribute is in this file start_frame = 1 if 'start' in self.file.data.keys(): start_frame = (float(self.file.data['start']) * self.fps) + 1 # Display start frame (and then the previous frame) QTimer.singleShot(500, functools.partial(self.sliderVideo.setValue, start_frame + 1)) QTimer.singleShot(600, functools.partial(self.sliderVideo.setValue, start_frame)) # Connect signals self.actionPlay.triggered.connect(self.actionPlay_Triggered) self.btnPlay.clicked.connect(self.btnPlay_clicked) self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged) self.btnStart.clicked.connect(self.btnStart_clicked) self.btnEnd.clicked.connect(self.btnEnd_clicked) self.btnClear.clicked.connect(self.btnClear_clicked) self.btnAddClip.clicked.connect(self.btnAddClip_clicked) self.initialized = True