Esempio n. 1
0
	def bool_value_changed(self, widget, param, state ):
		# Save setting
		if state == Qt.Checked:
			self.s.set(param["setting"], True)
		else:
			self.s.set(param["setting"], False)
		log.info(value)
Esempio n. 2
0
    def cboProfile_index_changed(self, widget, index):
        selected_profile_path = widget.itemData(index)
        log.info(selected_profile_path)

        # get translations
        app = get_app()
        _ = app._tr

        # Load profile
        profile = openshot.Profile(selected_profile_path)

        # Load profile settings into advanced editor
        self.txtWidth.setValue(profile.info.width)
        self.txtHeight.setValue(profile.info.height)
        self.txtFrameRateNum.setValue(profile.info.fps.num)
        self.txtFrameRateDen.setValue(profile.info.fps.den)
        self.txtAspectRatioNum.setValue(profile.info.display_ratio.num)
        self.txtAspectRatioDen.setValue(profile.info.display_ratio.den)
        self.txtPixelRatioNum.setValue(profile.info.pixel_ratio.num)
        self.txtPixelRatioDen.setValue(profile.info.pixel_ratio.den)

        # Load the interlaced options
        self.cboInterlaced.clear()
        self.cboInterlaced.addItem(_("Yes"), "Yes")
        self.cboInterlaced.addItem(_("No"), "No")
        if profile.info.interlaced_frame:
            self.cboInterlaced.setCurrentIndex(0)
        else:
            self.cboInterlaced.setCurrentIndex(1)
Esempio n. 3
0
    def updateFrameRate(self):
        """Callback for changing the frame rate"""
        log.info('Adjust the framerate of the project')

        # Adjust the main timeline reader
        get_app().updates.update(["width"], self.txtWidth.value())
        get_app().updates.update(["height"], self.txtHeight.value())
        get_app().updates.update(["fps"], {"num" : self.txtFrameRateNum.value(), "den" : self.txtFrameRateDen.value()})
        get_app().updates.update(["sample_rate"], self.txtSampleRate.value())
        get_app().updates.update(["channels"], self.txtChannels.value())
        get_app().updates.update(["channel_layout"], self.cboChannelLayout.currentData())

        # Force ApplyMapperToClips to apply these changes
        get_app().window.timeline_sync.timeline.ApplyMapperToClips()

        # Determine max frame (based on clips)
        timeline_length = 0.0
        fps = get_app().window.timeline_sync.timeline.info.fps.ToFloat()
        clips = get_app().window.timeline_sync.timeline.Clips()
        for clip in clips:
            clip_last_frame = clip.Position() + clip.Duration()
            if clip_last_frame > timeline_length:
                # Set max length of timeline
                timeline_length = clip_last_frame

        # Convert to int and round
        self.timeline_length_int = round(timeline_length * fps) + 1

        # Set the min and max frame numbers for this project
        self.txtStartFrame.setMaximum(self.timeline_length_int)
        self.txtEndFrame.setMaximum(self.timeline_length_int)
        self.txtStartFrame.setValue(1)
        self.txtEndFrame.setValue(self.timeline_length_int)
Esempio n. 4
0
    def Start(self):
        """ This method starts the video player """
        log.info("QThread Start Method Invoked")

        # Flag to run thread
        self.is_running = True
        self.number = None
        self.videoPreview = self.parent.videoPreview
        self.player = None
        self.current_frame = None
        self.current_mode = None

        # Init new player
        self.initPlayer()

        # Connect player to timeline reader
        self.player.Reader(self.timeline)
        self.player.Play()
        self.player.Pause()

        # Main loop, waiting for frames to process
        while self.is_running:

            # Emit position changed signal (if needed)
            if self.current_frame != self.player.Position():
                self.current_frame = self.player.Position()
                self.position_changed.emit(self.current_frame)

            # Emit mode changed signal (if needed)
            if self.player.Mode() != self.current_mode:
                self.current_mode = self.player.Mode()
                self.mode_changed.emit(self.current_mode)

            # wait for a small delay
            time.sleep(0.01)
Esempio n. 5
0
    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)
Esempio n. 6
0
    def actionThumbnailView_trigger(self, event):
        log.info("Switch to Thumbnail View")

        # Get settings
        app = get_app()
        s = settings.get_settings()

        # Files
        if app.context_menu_object == "files":
            s.set("file_view", "thumbnail")
            self.tabFiles.layout().removeWidget(self.filesTreeView)
            self.filesTreeView.deleteLater()
            self.filesTreeView = None
            self.filesTreeView = FilesListView(self)
            self.tabFiles.layout().addWidget(self.filesTreeView)

        # Transitions
        elif app.context_menu_object == "transitions":
            s.set("transitions_view", "thumbnail")
            self.tabTransitions.layout().removeWidget(self.transitionsTreeView)
            self.transitionsTreeView.deleteLater()
            self.transitionsTreeView = None
            self.transitionsTreeView = TransitionsListView(self)
            self.tabTransitions.layout().addWidget(self.transitionsTreeView)

        # Effects
        elif app.context_menu_object == "effects":
            s.set("effects_view", "thumbnail")
            self.tabEffects.layout().removeWidget(self.effectsTreeView)
            self.effectsTreeView.deleteLater()
            self.effectsTreeView = None
            self.effectsTreeView = EffectsListView(self)
            self.tabEffects.layout().addWidget(self.effectsTreeView)
Esempio n. 7
0
    def updateProperty(self, id, frame_number, property_key, new_value):
        """Update a keyframe property to a new value, adding or updating keyframes as needed"""
        found_point = False
        clip_updated = False

        c = Clip.get(id=id)
        if not c:
            # No clip found
            return

        for point in c.data[property_key]["Points"]:
            log.info("looping points: co.X = %s" % point["co"]["X"])

            if point["co"]["X"] == frame_number:
                found_point = True
                clip_updated = True
                point["interpolation"] = openshot.BEZIER
                point["co"]["Y"] = float(new_value)

        if not found_point and new_value != None:
            clip_updated = True
            log.info("Created new point at X=%s" % frame_number)
            c.data[property_key]["Points"].append({'co': {'X': frame_number, 'Y': new_value}, 'interpolation': openshot.BEZIER})

        # Reduce # of clip properties we are saving (performance boost)
        c.data = {property_key: c.data.get(property_key)}

        # Save changes
        if clip_updated:
            # Save
            c.save()

            # Update the preview
            get_app().window.refreshFrameSignal.emit()
Esempio n. 8
0
 def actionDonate_trigger(self, event):
     try:
         webbrowser.open("http://openshot.org/donate/")
         log.info("Open the Donate web page with success")
     except:
         QMessageBox.information(self, "Error !", "Unable to open the Donate web page")
         log.info("Unable to open the Donate web page")
Esempio n. 9
0
    def actionNextMarker_trigger(self, event):
        log.info("actionNextMarker_trigger")
        log.info(self.preview_thread.current_frame)

        # Calculate current position (in seconds)
        fps = get_app().project.get(["fps"])
        fps_float = float(fps["num"]) / float(fps["den"])
        current_position = self.preview_thread.current_frame / fps_float

        # Loop through all markers, and find the closest one to the right
        closest_position = None
        for marker in Marker.filter():
            marker_position = marker.data["position"]

            # Is marker smaller than position?
            if marker_position > current_position:
                # Is marker larger than previous marker
                if closest_position and marker_position < closest_position:
                    # Set a new closest marker
                    closest_position = marker_position
                elif not closest_position:
                    # First one found
                    closest_position = marker_position

        # Seek to marker position (if any)
        if closest_position:
            # Seek
            frame_to_seek = int(closest_position * fps_float)
            self.preview_thread.player.Seek(frame_to_seek)
Esempio n. 10
0
 def actionAskQuestion_trigger(self, event):
     try:
         webbrowser.open("https://answers.launchpad.net/openshot/+addquestion")
         log.info("Open the Question launchpad web page with success")
     except:
         QMessageBox.information(self, "Error !", "Unable to open the Question web page")
         log.info("Unable to open the Question web page")
Esempio n. 11
0
    def changed(self, action):

        # Handle change
        if action.key and action.key[0] in ["clips", "effects"] and action.type in ["update", "insert"]:
            log.info(action.values)
            # Update the model data
            self.update_model(get_app().window.txtPropertyFilter.text())
Esempio n. 12
0
 def actionTranslate_trigger(self, event):
     try:
         webbrowser.open("https://translations.launchpad.net/openshot")
         log.info("Open the Translate launchpad web page with success")
     except:
         QMessageBox.information(self, "Error !", "Unable to open the Translation web page")
         log.info("Unable to open the Translation web page")
Esempio n. 13
0
    def open_project(self, file_path):
        """ Open a project from a file path, and refresh the screen """

        app = get_app()

        try:
            if os.path.exists(file_path.encode('UTF-8')):
                # Load project file
                app.project.load(file_path)

                # Set Window title
                self.SetWindowTitle()

                # Reset undo/redo history
                app.updates.reset()

                # Refresh file tree
                self.filesTreeView.refresh_view()

                # Load recent projects again
                self.load_recent_menu()

                log.info("Loaded project {}".format(file_path))

        except Exception as ex:
            log.error("Couldn't save project {}".format(file_path))
Esempio n. 14
0
 def actionReportBug_trigger(self, event):
     try:
         webbrowser.open("https://bugs.launchpad.net/openshot/+filebug")
         log.info("Open the Report Bug Launchpad web page with success")
     except:
         QMessageBox.information(self, "Error !", "Unable to open the launchpad web page")
         log.info("Unable to open the Report Bug launchpad web page")
Esempio n. 15
0
    def move_temp_paths_to_project_folder(self, file_path):
        """ Move all temp files (such as Blender anmiations) to the project folder. """

        # Get project folder
        new_project_folder = os.path.dirname(file_path)

        # Get list of files
        files = self._data["files"]

        # Loop through each file
        for file in files:
            path = file["path"]

            # Find any temp file paths
            if info.BLENDER_PATH in path:
                log.info("TEMP FOLDER DETECTED")

                # Get folder of file
                folder_path, file_name = os.path.split(path)
                parent_path, folder_name = os.path.split(folder_path)

                # Update path to new folder
                path = os.path.join(new_project_folder, folder_name)

                # Copy temp folder to project folder
                shutil.copytree(folder_path, path)

                # Update paths in project to new location
                file["path"] = os.path.join(path, file_name)
Esempio n. 16
0
    def changed(self, action):
        """ This method is invoked by the UpdateManager each time a change happens (i.e UpdateInterface) """

        # Ignore changes that don't affect libopenshot
        if len(action.key) >= 1 and action.key[0].lower() in ["files", "history", "markers", "layers", "export_path", "import_path", "scale"]:
            return

        elif len(action.key) >= 1 and action.key[0].lower() in ["profile"]:

            # The timeline's profile changed, so update all clips
            self.timeline.ApplyMapperToClips()
            return

        # Pass the change to the libopenshot timeline
        try:
            if action.type == "load":
                # This JSON is initially loaded to libopenshot to update the timeline
                self.timeline.SetJson(action.json(only_value=True))
                self.timeline.Open()  # Re-Open the Timeline reader

                # The timeline's profile changed, so update all clips
                self.timeline.ApplyMapperToClips()

                # Refresh current frame (since the entire timeline was updated)
                self.window.refreshFrameSignal.emit()

            else:
                # This JSON DIFF is passed to libopenshot to update the timeline
                self.timeline.ApplyJsonDiff(action.json(is_array=True))

        except Exception as e:
            log.info("Error applying JSON to timeline object in libopenshot: %s. %s" % (e, action.json(is_array=True)))
Esempio n. 17
0
    def init_slider_values(self):
        """ Init the slider and preview frame label to the currently selected animation """
        log.info("init_slider_values")

        # Get current preview slider frame
        preview_frame_number = self.win.sliderPreview.value()
        length = int(self.params.get("end_frame", 1))

        # Get the animation speed (if any)
        if not self.params.get("animation_speed"):
            self.params["animation_speed"] = 1
        else:
            # Adjust length (based on animation speed multiplier)
            length *= int(self.params["animation_speed"])

        # Update the preview slider
        middle_frame = int(length / 2)

        self.win.sliderPreview.setMinimum(self.params.get("start_frame", 1))
        self.win.sliderPreview.setMaximum(length)
        self.win.sliderPreview.setValue(middle_frame)

        # Update preview label
        self.win.lblFrame.setText("{}/{}".format(middle_frame, length))

        # Click the refresh button
        self.btnRefresh_clicked(None)
Esempio n. 18
0
    def save(self, file_path, move_temp_files=True, make_paths_relative=True):
        """ Save project file to disk """
        import openshot

        log.info("Saving project file: {}".format(file_path))

        # Move all temp files (i.e. Blender animations) to the project folder
        if move_temp_files:
            self.move_temp_paths_to_project_folder(file_path)

        # Append version info
        v = openshot.GetVersion()
        self._data["version"] = { "openshot-qt" : info.VERSION,
                                  "libopenshot" : v.ToString() }

        # Try to save project settings file, will raise error on failure
        self.write_to_file(file_path, self._data, path_mode="relative", previous_path=self.current_filepath)

        # On success, save current filepath
        self.current_filepath = file_path

        # Add to recent files setting
        self.add_to_recent_files(file_path)

        # Track unsaved changes
        self.has_unsaved_changes = False
Esempio n. 19
0
    def changed(self, action):

        # Handle change
        if action.key and action.key[0] == "clips":
            log.info(action.values)
            # Update the model data
            self.update_model(get_app().window.txtPropertyFilter.text())
Esempio n. 20
0
	def color_button_clicked(self, widget, param, index ):
		# Show color dialog
		currentColor = QColor(self.params[param["name"]])
		newColor = QColorDialog.getColor(currentColor)
		widget.setStyleSheet("background-color: {}".format(newColor.name()))
		self.params[param["name"]] = [newColor.redF(), newColor.greenF(), newColor.blueF()]
		log.info(newColor.name())
Esempio n. 21
0
    def btnAdvanced_clicked(self):
        _ = self.app._tr
        # use an external editor to edit the image
        try:
            # Get settings
            s = settings.get_settings()

            # get the title editor executable path
            prog = s.get("title_editor")

            # launch advanced title editor
            # debug info
            log.info("Advanced title editor command: {} {} ".format(prog, self.filename))

            p = subprocess.Popen([prog, self.filename])

            # wait for process to finish (so we can update the preview)
            p.communicate()

            # update image preview
            self.load_svg_template()
            self.display_svg()

        except OSError:
            msg = QMessageBox()
            msg.setText(_("Please install {} to use this function").format(prog.capitalize()))
            msg.exec_()
Esempio n. 22
0
    def save_history(self, project, history_length):
        """Save history to project"""
        redo_list = []
        undo_list = []

        # Loop through each updateAction object and serialize
        # Ignore any load actions or history update actions
        history_length_int = int(history_length)
        for action in self.redoHistory[-history_length_int:]:
            if action.type != "load" and action.key[0] != "history":
                actionDict = json.loads(action.json(), strict=False)
                redo_list.append(actionDict)
            else:
                log.info("Saving redo history, skipped key: %s" % str(action.key))
        for action in self.actionHistory[-history_length_int:]:
            if action.type != "load" and action.key[0] != "history":
                actionDict = json.loads(action.json(), strict=False)
                undo_list.append(actionDict)
            else:
                log.info("Saving undo, skipped key: %s" % str(action.key))

        # Set history data in project
        self.ignore_history = True
        self.update(["history"], { "redo": redo_list, "undo": undo_list})
        self.ignore_history = False
Esempio n. 23
0
    def ChangelogMenuTriggered(self, hash=""):
        log.info("ChangelogMenuTriggered")

        try:
            webbrowser.open(self.commit_url % hash)
        except:
            pass
Esempio n. 24
0
    def btnMoveDownClicked(self, event):
        """Callback for move up button click"""
        log.info("btnMoveDownClicked")

        # Get selected file
        files = self.treeFiles.timeline_model.files
        selected_index = self.treeFiles.selected.row()

        # Ignore if empty files
        if not files:
            return

        # New index
        new_index = min(selected_index + 1, len(files) - 1)
        log.info(new_index)

        # Remove item and move it
        files.insert(new_index, files.pop(selected_index))

        # Refresh tree
        self.treeFiles.refresh_view()

        # Select new position
        idx = self.treeFiles.timeline_model.model.index(new_index, 0)
        self.treeFiles.setCurrentIndex(idx)
Esempio n. 25
0
    def changed(self, action):
        """ This method is invoked by the UpdateManager each time a change happens (i.e UpdateInterface) """

        # Ignore changes that don't affect libopenshot
        if len(action.key) >= 1 and action.key[0].lower() in ["files", "markers", "layers"]:
            return
        elif len(action.key) >= 1 and action.key[0].lower() in ["profile"]:
            # The timeline's profile changed, so update all clips
            self.timeline.ApplyMapperToClips()
            return

        # Pass the change to the libopenshot timeline
        try:
            if action.type == "load":
                # This JSON is initially loaded to libopenshot to update the timeline
                self.timeline.SetJson(action.json(only_value=True))
                self.timeline.Open()  # Re-Open the Timeline reader

            else:
                # This JSON DIFF is passed to libopenshot to update the timeline
                print(action.json(is_array=True))
                self.timeline.ApplyJsonDiff(action.json(is_array=True))

        except:
            log.info("Error applying JSON to timeline object in libopenshot")
Esempio n. 26
0
	def btnAdvanced_clicked(self):
		_ = self.app._tr
		#use an external editor to edit the image
		try:
			prog = "inkscape"
			#check if inkscape is installed
			if subprocess.call('which ' + prog + ' 2>/dev/null', shell=True) == 0:
				# launch Inkscape
				# debug info
				log.info("Inkscape command: {} {} ".format(prog, self.filename))

				p=subprocess.Popen([prog, self.filename])

				# wait for process to finish (so we can update the preview)
				p.communicate()

				# update image preview
				self.load_svg_template()
				self.display_svg()
			else:
				msg = QMessageBox()
				msg.setText(_("There was an error trying to open {}.").format(prog.capitalize()))
				msg.exec_()

		except OSError:
			msg = QMessageBox()
			msg.setText(_("Please install {} to use this function").format(prog.capitalize()))
			msg.exec_()
Esempio n. 27
0
    def btnRemoveClicked(self, event):
        """Callback for move up button click"""
        log.info("btnRemoveClicked")

        # Get selected file
        files = self.treeFiles.timeline_model.files
        selected_index = self.treeFiles.selected.row()

        # Ignore if empty files
        if not files:
            return

        # Remove item
        files.pop(selected_index)

        # Refresh tree
        self.treeFiles.refresh_view()

        # Select next item (if any)
        new_index = max(len(files) - 1, 0)

        # Select new position
        idx = self.treeFiles.timeline_model.model.index(new_index, 0)
        self.treeFiles.setCurrentIndex(idx)

        # Update total
        self.updateTotal()
Esempio n. 28
0
    def json(self, is_array=False, only_value=False):
        """ Get the JSON string representing this UpdateAction """

        # Build the dictionary to be serialized
        if only_value:
            data_dict = copy.deepcopy(self.values)
        else:
            data_dict = {"type": self.type,
                         "key": self.key,
                         "value": copy.deepcopy(self.values),
                         "partial": self.partial_update,
                         "old_values": copy.deepcopy(self.old_values)}

        # Always remove 'history' key (if found). This prevents nested "history"
        # attributes when a project dict is loaded.
        try:
            if data_dict.get("value") and "history" in data_dict.get("value"):
                data_dict.get("value").pop("history", None)
            if data_dict.get("old_values") and "history" in data_dict.get("old_values"):
                data_dict.get("old_values").pop("history", None)
        except Exception:
            log.info('Warning: failed to clear history attribute from undo/redo data.')

        if not is_array:
            # Use a JSON Object as the root object
            update_action_dict = data_dict
        else:
            # Use a JSON Array as the root object
            update_action_dict = [data_dict]

        # Serialize as JSON
        return json.dumps(update_action_dict)
Esempio n. 29
0
    def bool_value_changed(self, widget, param, state):
        # Save setting
        if state == Qt.Checked:
            self.s.set(param["setting"], True)
        else:
            self.s.set(param["setting"], False)

        # Trigger specific actions
        if param["setting"] == "debug-mode":
            # Update debug setting of timeline
            log.info("Setting debug-mode to %s" % (state == Qt.Checked))
            debug_enabled = (state == Qt.Checked)

            # Enable / Disable logger
            openshot.ZmqLogger.Instance().Enable(debug_enabled)

        elif param["setting"] == "enable-auto-save":
            # Toggle autosave
            if (state == Qt.Checked):
                # Start/Restart autosave timer
                get_app().window.auto_save_timer.start()
            else:
                # Stop autosave timer
                get_app().window.auto_save_timer.stop()

        # Check for restart
        self.check_for_restart(param)
Esempio n. 30
0
    def load_history(self, project):
        """Load history from project"""
        self.redoHistory.clear()
        self.actionHistory.clear()

        # Get history from project data
        history = project.get(["history"])

        # Loop through each, and load serialized data into updateAction objects
        # Ignore any load actions or history update actions
        for actionDict in history.get("redo", []):
            action = UpdateAction()
            action.load_json(json.dumps(actionDict))
            if action.type != "load" and action.key[0] != "history":
                self.redoHistory.append(action)
            else:
                log.info("Loading redo history, skipped key: %s" % str(action.key))
        for actionDict in history.get("undo", []):
            action = UpdateAction()
            action.load_json(json.dumps(actionDict))
            if action.type != "load" and action.key[0] != "history":
                self.actionHistory.append(action)
            else:
                log.info("Loading undo history, skipped key: %s" % str(action.key))

        # Notify watchers of new status
        self.update_watchers()
Esempio n. 31
0
 def load_credit(self):
     """ Load Credits for everybody who has contribuated in several domain for Openshot """
     log.info('Credit screen has been opened')
     windo = Credits()
     windo.exec_()
Esempio n. 32
0
    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
Esempio n. 33
0
    def reject(self):
        """ Cancel button clicked """
        log.info('reject')

        # Accept dialog
        super(AddToTimeline, self).reject()
Esempio n. 34
0
    def accept(self):
        """ Ok button clicked """
        log.info('accept')

        # Get settings from form
        start_position = self.txtStartTime.value()
        track_num = self.cmbTrack.currentData()
        fade_value = self.cmbFade.currentData()
        fade_length = self.txtFadeLength.value()
        transition_path = self.cmbTransition.currentData()
        transition_length = self.txtTransitionLength.value()
        image_length = self.txtImageLength.value()
        zoom_value = self.cmbZoom.currentData()

        # Init position
        position = start_position

        random_transition = False
        if transition_path == "random":
            random_transition = True

        # Get frames per second
        fps = get_app().project.get(["fps"])
        fps_float = float(fps["num"]) / float(fps["den"])

        # Loop through each file (in the current order)
        for file in self.treeFiles.timeline_model.files:
            # Create a clip
            clip = Clip()
            clip.data = {}

            if (file.data["media_type"] == "video"
                    or file.data["media_type"] == "image"):
                # Determine thumb path
                thumb_path = os.path.join(info.THUMBNAIL_PATH,
                                          "%s.png" % file.data["id"])
            else:
                # Audio file
                thumb_path = os.path.join(info.PATH, "images",
                                          "AudioThumbnail.png")

            # Get file name
            path, filename = os.path.split(file.data["path"])

            # Convert path to the correct relative path (based on this folder)
            file_path = file.absolute_path()

            # Create clip object for this file
            c = openshot.Clip(file_path)

            # Append missing attributes to Clip JSON
            new_clip = json.loads(c.Json())
            new_clip["position"] = position
            new_clip["layer"] = track_num
            new_clip["file_id"] = file.id
            new_clip["title"] = filename
            new_clip["image"] = thumb_path

            # Skip any clips that are missing a 'reader' attribute
            # TODO: Determine why this even happens, as it shouldn't be possible
            if not new_clip.get("reader"):
                continue  # Skip to next file

            # Overwrite frame rate (incase the user changed it in the File Properties)
            file_properties_fps = float(file.data["fps"]["num"]) / float(
                file.data["fps"]["den"])
            file_fps = float(new_clip["reader"]["fps"]["num"]) / float(
                new_clip["reader"]["fps"]["den"])
            fps_diff = file_fps / file_properties_fps
            new_clip["reader"]["fps"]["num"] = file.data["fps"]["num"]
            new_clip["reader"]["fps"]["den"] = file.data["fps"]["den"]
            # Scale duration / length / and end properties
            new_clip["reader"]["duration"] *= fps_diff
            new_clip["end"] *= fps_diff
            new_clip["duration"] *= fps_diff

            # Check for optional start and end attributes
            start_time = 0
            end_time = new_clip["reader"]["duration"]

            if 'start' in file.data.keys():
                start_time = file.data['start']
                new_clip["start"] = start_time
            if 'end' in file.data.keys():
                end_time = file.data['end']
                new_clip["end"] = end_time

            # Adjust clip duration, start, and end
            new_clip["duration"] = new_clip["reader"]["duration"]
            if file.data["media_type"] == "image":
                end_time = image_length
                new_clip["end"] = end_time

            # Adjust Fade of Clips (if no transition is chosen)
            if not transition_path:
                if fade_value != None:
                    # Overlap this clip with the previous one (if any)
                    position = max(start_position,
                                   new_clip["position"] - fade_length)
                    new_clip["position"] = position

                if fade_value == 'Fade In' or fade_value == 'Fade In & Out':
                    start = openshot.Point((start_time * fps_float) + 1, 0.0,
                                           openshot.BEZIER)
                    start_object = json.loads(start.Json())
                    end = openshot.Point(
                        min((start_time + fade_length) * fps_float,
                            end_time * fps_float), 1.0, openshot.BEZIER)
                    end_object = json.loads(end.Json())
                    new_clip['alpha']["Points"].append(start_object)
                    new_clip['alpha']["Points"].append(end_object)

                if fade_value == 'Fade Out' or fade_value == 'Fade In & Out':
                    start = openshot.Point(
                        max((end_time * fps_float) - (fade_length * fps_float),
                            start_time * fps_float), 1.0, openshot.BEZIER)
                    start_object = json.loads(start.Json())
                    end = openshot.Point(end_time * fps_float, 0.0,
                                         openshot.BEZIER)
                    end_object = json.loads(end.Json())
                    new_clip['alpha']["Points"].append(start_object)
                    new_clip['alpha']["Points"].append(end_object)

            # Adjust zoom amount
            if zoom_value != None:
                # Location animation
                if zoom_value == "Random":
                    animate_start_x = uniform(-0.5, 0.5)
                    animate_end_x = uniform(-0.15, 0.15)
                    animate_start_y = uniform(-0.5, 0.5)
                    animate_end_y = uniform(-0.15, 0.15)

                    # Scale animation
                    start_scale = uniform(0.5, 1.5)
                    end_scale = uniform(0.85, 1.15)

                elif zoom_value == "Zoom In":
                    animate_start_x = 0.0
                    animate_end_x = 0.0
                    animate_start_y = 0.0
                    animate_end_y = 0.0

                    # Scale animation
                    start_scale = 1.0
                    end_scale = 1.25

                elif zoom_value == "Zoom Out":
                    animate_start_x = 0.0
                    animate_end_x = 0.0
                    animate_start_y = 0.0
                    animate_end_y = 0.0

                    # Scale animation
                    start_scale = 1.25
                    end_scale = 1.0

                # Add keyframes
                start = openshot.Point((start_time * fps_float) + 1,
                                       start_scale, openshot.BEZIER)
                start_object = json.loads(start.Json())
                end = openshot.Point(end_time * fps_float, end_scale,
                                     openshot.BEZIER)
                end_object = json.loads(end.Json())
                new_clip["gravity"] = openshot.GRAVITY_CENTER
                new_clip["scale_x"]["Points"].append(start_object)
                new_clip["scale_x"]["Points"].append(end_object)
                new_clip["scale_y"]["Points"].append(start_object)
                new_clip["scale_y"]["Points"].append(end_object)

                # Add keyframes
                start_x = openshot.Point((start_time * fps_float) + 1,
                                         animate_start_x, openshot.BEZIER)
                start_x_object = json.loads(start_x.Json())
                end_x = openshot.Point(end_time * fps_float, animate_end_x,
                                       openshot.BEZIER)
                end_x_object = json.loads(end_x.Json())
                start_y = openshot.Point((start_time * fps_float) + 1,
                                         animate_start_y, openshot.BEZIER)
                start_y_object = json.loads(start_y.Json())
                end_y = openshot.Point(end_time * fps_float, animate_end_y,
                                       openshot.BEZIER)
                end_y_object = json.loads(end_y.Json())
                new_clip["gravity"] = openshot.GRAVITY_CENTER
                new_clip["location_x"]["Points"].append(start_x_object)
                new_clip["location_x"]["Points"].append(end_x_object)
                new_clip["location_y"]["Points"].append(start_y_object)
                new_clip["location_y"]["Points"].append(end_y_object)

            if transition_path:
                # Add transition for this clip (if any)
                # Open up QtImageReader for transition Image
                if random_transition:
                    random_index = randint(0, len(self.transitions))
                    transition_path = self.transitions[random_index]

                # Get reader for transition
                transition_reader = openshot.QtImageReader(transition_path)

                brightness = openshot.Keyframe()
                brightness.AddPoint(1, 1.0, openshot.BEZIER)
                brightness.AddPoint(
                    min(transition_length, end_time - start_time) * fps_float,
                    -1.0, openshot.BEZIER)
                contrast = openshot.Keyframe(3.0)

                # Create transition dictionary
                transitions_data = {
                    "layer": track_num,
                    "title": "Transition",
                    "type": "Mask",
                    "start": 0,
                    "end": min(transition_length, end_time - start_time),
                    "brightness": json.loads(brightness.Json()),
                    "contrast": json.loads(contrast.Json()),
                    "reader": json.loads(transition_reader.Json()),
                    "replace_image": False
                }

                # Overlap this clip with the previous one (if any)
                position = max(start_position, position - transition_length)
                transitions_data["position"] = position
                new_clip["position"] = position

                # Create transition
                tran = Transition()
                tran.data = transitions_data
                tran.save()

            # Save Clip
            clip.data = new_clip
            clip.save()

            # Increment position by length of clip
            position += (end_time - start_time)

        # Accept dialog
        super(AddToTimeline, self).accept()
    def Choice_Action_Triggered(self, event):
        log.info("Choice_Action_Triggered")
        choice_value = self.sender().data()

        # Update value of dropdown item
        self.clip_properties_model.value_updated(self.selected_item, value=choice_value)
 def Remove_Action_Triggered(self, event):
     log.info("Remove_Action_Triggered")
     self.clip_properties_model.remove_keyframe(self.selected_item)
Esempio n. 37
0
 def load_license(self):
     """ Load License of the project """
     log.info('License screen has been opened')
     windo = License()
     windo.exec_()
Esempio n. 38
0
         os.path.join(PATH, "openshot_qt", "launch-openshot"))

if os.path.exists(os.path.join(PATH, "openshot_qt")):
    # Append path to system path
    sys.path.append(os.path.join(PATH, "openshot_qt"))
    print("Loaded modules from openshot_qt directory: %s" %
          os.path.join(PATH, "openshot_qt"))

# Append possible build server paths
sys.path.insert(0, os.path.join(PATH, "build", "install-x86", "lib"))
sys.path.insert(0, os.path.join(PATH, "build", "install-x64", "lib"))

from classes import info
from classes.logger import log

log.info("Execution path: %s" % os.path.abspath(__file__))


# Find files matching patterns
def find_files(directory, patterns):
    """ Recursively find all files in a folder tree """
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if ".pyc" not in basename and "__pycache__" not in basename:
                for pattern in patterns:
                    if fnmatch.fnmatch(basename, pattern):
                        filename = os.path.join(root, basename)
                        yield filename


# GUI applications require a different base on Windows
Esempio n. 39
0
 def close(self):
     """ Actually close window and accept dialog """
     log.info('close')
Esempio n. 40
0
    def update_model(self, clear=True):
        log.info("updating files model.")
        app = get_app()

        # Get window to check filters
        win = app.window
        _ = app._tr

        # Skip updates (if needed)
        if self.ignore_update_signal:
            return

        # Clear all items
        if clear:
            self.model_ids = {}
            self.model.clear()

        # Add Headers
        self.model.setHorizontalHeaderLabels(
            ["", _("Name"), _("Tags"), "", "", ""])

        # Get list of files in project
        files = File.filter()  # get all files

        # add item for each file
        for file in files:
            path, filename = os.path.split(file.data["path"])
            tags = ""
            if "tags" in file.data.keys():
                tags = file.data["tags"]
            name = filename
            if "name" in file.data.keys():
                name = file.data["name"]

            if not win.actionFilesShowAll.isChecked():
                if win.actionFilesShowVideo.isChecked():
                    if not file.data["media_type"] == "video":
                        continue  # to next file, didn't match filter
                elif win.actionFilesShowAudio.isChecked():
                    if not file.data["media_type"] == "audio":
                        continue  # to next file, didn't match filter
                elif win.actionFilesShowImage.isChecked():
                    if not file.data["media_type"] == "image":
                        continue  # to next file, didn't match filter

            if win.filesFilter.text() != "":
                if not win.filesFilter.text().lower() in filename.lower() \
                        and not win.filesFilter.text().lower() in tags.lower() \
                        and not win.filesFilter.text().lower() in name.lower():
                    continue

            # Generate thumbnail for file (if needed)
            if (file.data["media_type"] == "video"
                    or file.data["media_type"] == "image"):
                # Determine thumb path
                thumb_path = os.path.join(info.THUMBNAIL_PATH,
                                          "{}.png".format(file.id))

                # Check if thumb exists
                if not os.path.exists(thumb_path):

                    try:
                        # Convert path to the correct relative path (based on this folder)
                        file_path = file.absolute_path()

                        # Reload this reader
                        clip = openshot.Clip(file_path)
                        reader = clip.Reader()

                        # Open reader
                        reader.Open()

                        # Determine if video overlay should be applied to thumbnail
                        overlay_path = ""
                        if file.data["media_type"] == "video":
                            overlay_path = os.path.join(
                                info.IMAGES_PATH, "overlay.png")

                        # Check for start and end attributes (optional)
                        thumbnail_frame = 1
                        if 'start' in file.data.keys():
                            fps = file.data["fps"]
                            fps_float = float(fps["num"]) / float(fps["den"])
                            thumbnail_frame = round(
                                float(file.data['start']) * fps_float) + 1

                        # Save thumbnail
                        reader.GetFrame(thumbnail_frame).Thumbnail(
                            thumb_path, 98, 64,
                            os.path.join(info.IMAGES_PATH, "mask.png"),
                            overlay_path, "#000", False)
                        reader.Close()
                        clip.Close()

                    except:
                        # Handle exception
                        msg = QMessageBox()
                        msg.setText(
                            _("{} is not a valid video, audio, or image file.".
                              format(filename)))
                        msg.exec_()
                        continue

            else:
                # Audio file
                thumb_path = os.path.join(info.PATH, "images",
                                          "AudioThumbnail.png")

            row = []

            # Append thumbnail
            col = QStandardItem()
            col.setIcon(QIcon(thumb_path))
            col.setText(name)
            col.setToolTip(filename)
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsDragEnabled)
            row.append(col)

            # Append Filename
            col = QStandardItem("Name")
            col.setData(filename, Qt.DisplayRole)
            col.setText(name)
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsDragEnabled | Qt.ItemIsEditable)
            row.append(col)

            # Append Tags
            col = QStandardItem("Tags")
            col.setData(tags, Qt.DisplayRole)
            col.setText(tags)
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsDragEnabled | Qt.ItemIsEditable)
            row.append(col)

            # Append Media Type
            col = QStandardItem("Type")
            col.setData(file.data["media_type"], Qt.DisplayRole)
            col.setText(file.data["media_type"])
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsDragEnabled | Qt.ItemIsEditable)
            row.append(col)

            # Append Path
            col = QStandardItem("Path")
            col.setData(path, Qt.DisplayRole)
            col.setText(path)
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
            row.append(col)

            # Append ID
            col = QStandardItem("ID")
            col.setData(file.data["id"], Qt.DisplayRole)
            col.setText(file.data["id"])
            col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                         | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
            row.append(col)

            # Append ROW to MODEL (if does not already exist in model)
            if not file.data["id"] in self.model_ids:
                self.model.appendRow(row)
                self.model_ids[file.data["id"]] = file.data["id"]

            # Process events in QT (to keep the interface responsive)
            app.processEvents()

            # Refresh view and filters (to hide or show this new item)
            get_app().window.resize_contents()

        # Emit signal
        self.model.ModelRefreshed.emit()
Esempio n. 41
0
    def btnClear_clicked(self):
        """Clear the current clip and reset the form"""
        log.info('btnClear_clicked')

        # Reset form
        self.clearForm()
Esempio n. 42
0
 def reject(self):
     log.info('reject')
Esempio n. 43
0
 def cancel(self):
     log.info("Exit the dialog of super resolution. ")
     super(SuperResolution, self).reject()
Esempio n. 44
0
 def accept(self):
     """ Ok button clicked """
     log.info('accept')
Esempio n. 45
0
 def onModeChanged(self, current_mode):
     log.info('onModeChanged %s', current_mode)
     self.PlayModeChangedSignal.emit(current_mode)
Esempio n. 46
0
def init_language():
    """ Find the current locale, and install the correct translators """

    # Get app instance
    app = QCoreApplication.instance()

    # Setup of our list of translators and paths
    translator_types = (
        {
            "type": 'QT',
            "pattern":
            'qt_%s',  # Older versions of Qt use this file (built-in translations)
            "path": QLibraryInfo.location(QLibraryInfo.TranslationsPath)
        },
        {
            "type": 'QT',
            "pattern":
            'qtbase_%s',  # Newer versions of Qt use this file (built-in translations)
            "path": QLibraryInfo.location(QLibraryInfo.TranslationsPath)
        },
        {
            "type": 'QT',
            "pattern": 'qt_%s',
            "path": os.path.join(info.PATH, 'locale', 'QT')
        },  # Optional path where we package QT translations
        {
            "type": 'QT',
            "pattern": 'qtbase_%s',
            "path": os.path.join(info.PATH, 'locale', 'QT')
        },  # Optional path where we package QT translations
        {
            "type": 'OpenShot',
            "pattern": os.path.join('%s', 'LC_MESSAGES',
                                    'OpenShot'),  # Our custom translations
            "path": os.path.join(info.PATH, 'locale')
        },
    )

    # Determine the environment locale, or default to system locale name
    locale_names = [
        os.environ.get('LANG',
                       QLocale().system().name()),
        os.environ.get('LOCALE',
                       QLocale().system().name())
    ]

    # Determine if the user has overwritten the language (in the preferences)
    preference_lang = settings.get_settings().get('default-language')
    if preference_lang != "Default":
        # Append preference lang to top of list
        locale_names.insert(0, preference_lang)

    # Output all system languages detected
    log.info("Qt Detected Languages: {}".format(
        QLocale().system().uiLanguages()))
    log.info("LANG Environment Variable: {}".format(
        os.environ.get('LANG',
                       QLocale().system().name())))
    log.info("LOCALE Environment Variable: {}".format(
        os.environ.get('LOCALE',
                       QLocale().system().name())))

    # Default the locale to C, for number formatting
    locale.setlocale(locale.LC_ALL, 'C')

    # Loop through environment variables
    found_language = False
    for locale_name in locale_names:

        # Don't try on default locale, since it fails to load what is the default language
        if QLocale().system().name() in locale_name:
            log.info("Skipping English language (no need for translation): {}".
                     format(locale_name))
            continue

        # Go through each translator and try to add for current locale
        for type in translator_types:
            trans = QTranslator(app)
            if find_language_match(type["pattern"], type["path"], trans,
                                   locale_name):
                # Install translation
                app.installTranslator(trans)
                found_language = True

        # Exit if found language
        if found_language:
            log.info(
                "Exiting translation system (since we successfully loaded: {})"
                .format(locale_name))
            info.CURRENT_LANGUAGE = locale_name
            break
Esempio n. 47
0
 def onRenableInterface(self):
     log.info('onRenableInterface')
     self.enable_interface()
Esempio n. 48
0
    def uploadSequence(self):
        """ Start exporting video """

        # get translations
        _ = get_app()._tr

        # Init progress bar
        # 应该仅仅是用来展示进度条
        # self.progressExportVideo.setMinimum(self.txtStartFrame.value())
        # self.progressExportVideo.setMaximum(self.txtEndFrame.value())
        # self.progressExportVideo.setValue(self.txtStartFrame.value())

        # 这个是默认的图片文件输出格式
        self.image_format = "-%05d.png"

        export_type = _("Image Sequence")

        # Determine final exported file path (and replace blank paths with default ones)
        default_filename = "IM"
        default_folder = os.path.join(info.HOME_PATH, 'Desktop/temp')
        # 如果要导出图片序列,就规定好导出文件的命名
        file_name_with_ext = "%s%s" % (default_filename,
                                       self.image_format.strip())

        # 确定导出文件的路径
        export_file_path = os.path.join(default_folder, file_name_with_ext)
        log.info("锁定了的文件保存路径: %s" % export_file_path)

        # Init export settings
        # 以下的设定全部都已经写死了
        video_settings = {
            "vformat": 'mp4',
            "vcodec": 'libx264',
            "fps": {
                "num": 25,
                "den": 1
            },
            "width": 1024,
            "height": 576,
            "pixel_ratio": {
                "num": 1,
                "den": 1
            },
            "video_bitrate": 15000000,
            "start_frame": 1,
            "end_frame": 17
        }

        audio_settings = {
            "acodec": 'aac',
            "sample_rate": 48000,
            "channels": 2,
            "channel_layout": 3,
            "audio_bitrate": 192000
        }

        # Override vcodec and format for Image Sequences
        image_ext = os.path.splitext(self.image_format.strip())[1].replace(
            ".", "")
        video_settings["vformat"] = image_ext
        if image_ext in ["jpg", "jpeg"]:
            video_settings["vcodec"] = "mjpeg"
        else:
            video_settings["vcodec"] = image_ext

        # Store updated export folder path in project file
        get_app().updates.update_untracked(["export_path"],
                                           os.path.dirname(export_file_path))
        # Mark project file as unsaved
        get_app().project.has_unsaved_changes = True

        # Set MaxSize (so we don't have any downsampling)
        self.timeline.SetMaxSize(video_settings.get("width"),
                                 video_settings.get("height"))

        # Set lossless cache settings (temporarily)
        export_cache_object = openshot.CacheMemory(500)
        self.timeline.SetCache(export_cache_object)

        # Rescale all keyframes (if needed)
        if self.export_fps_factor != 1.0:
            log.info("导出文件fps因子不为1")
            # Get a copy of rescaled project data (this does not modify the active project)
            rescaled_app_data = get_app().project.rescale_keyframes(
                self.export_fps_factor)

            # Load the "export" Timeline reader with the JSON from the real timeline
            self.timeline.SetJson(json.dumps(rescaled_app_data))

            # Re-update the timeline FPS again (since the timeline just got clobbered)
            self.updateFrameRate()

        # Create FFmpegWriter
        try:
            w = openshot.FFmpegWriter(export_file_path)

            # Set video options
            if export_type in [
                    _("Video & Audio"),
                    _("Video Only"),
                    _("Image Sequence")
            ]:
                w.SetVideoOptions(
                    True, video_settings.get("vcodec"),
                    openshot.Fraction(
                        video_settings.get("fps").get("num"),
                        video_settings.get("fps").get("den")),
                    video_settings.get("width"), video_settings.get("height"),
                    openshot.Fraction(
                        video_settings.get("pixel_ratio").get("num"),
                        video_settings.get("pixel_ratio").get("den")), False,
                    False, video_settings.get("video_bitrate"))

            # Prepare the streams
            w.PrepareStreams()

            # These extra options should be set in an extra method
            # No feedback is given to the user
            # TODO: Tell user if option is not available
            # Muxing options for mp4/mov
            w.SetOption(openshot.VIDEO_STREAM, "muxing_preset",
                        "mp4_faststart")
            # Set the quality in case crf was selected
            # if "crf" in self.txtVideoBitRate.text():
            #     w.SetOption(openshot.VIDEO_STREAM, "crf", str(int(video_settings.get("video_bitrate"))))
            # # Set the quality in case qp was selected
            # if "qp" in self.txtVideoBitRate.text():
            #     w.SetOption(openshot.VIDEO_STREAM, "qp", str(int(video_settings.get("video_bitrate"))))

            # Open the writer
            w.Open()

            # Notify window of export started
            title_message = ""
            get_app().window.ExportStarted.emit(
                export_file_path, video_settings.get("start_frame"),
                video_settings.get("end_frame"))

            progressstep = max(
                1,
                round((video_settings.get("end_frame") -
                       video_settings.get("start_frame")) / 1000))
            start_time_export = time.time()
            start_frame_export = video_settings.get("start_frame")
            end_frame_export = video_settings.get("end_frame")
            # Write each frame in the selected range
            # 接下来就是导出动作的重要内容
            for frame in range(video_settings.get("start_frame"),
                               video_settings.get("end_frame") + 1):
                # Update progress bar (emit signal to main window)
                if (frame % progressstep) == 0:
                    end_time_export = time.time()
                    if (((frame - start_frame_export) != 0) &
                        ((end_time_export - start_time_export) != 0)):
                        seconds_left = round(
                            (start_time_export - end_time_export) *
                            (frame - end_frame_export) /
                            (frame - start_frame_export))
                        fps_encode = ((frame - start_frame_export) /
                                      (end_time_export - start_time_export))
                        title_message = _(
                            "%(hours)d:%(minutes)02d:%(seconds)02d Remaining (%(fps)5.2f FPS)"
                        ) % {
                            'hours': seconds_left / 3600,
                            'minutes': (seconds_left / 60) % 60,
                            'seconds': seconds_left % 60,
                            'fps': fps_encode
                        }

                    # Emit frame exported
                    # get_app().window.ExportFrame.emit(title_message, video_settings.get("start_frame"), video_settings.get("end_frame"), frame)

                    # Process events (to show the progress bar moving)
                    # QCoreApplication.processEvents()

                # Write the frame object to the video
                w.WriteFrame(self.timeline.GetFrame(frame))

                # Check if we need to bail out
                # if not self.exporting:
                #     break

            # Close writer
            w.Close()

            # 下面的内容应该都是配合进度提示的,删除
            '''
            # Emit final exported frame (with elapsed time)
            seconds_run = round((end_time_export - start_time_export))
            title_message = _("%(hours)d:%(minutes)02d:%(seconds)02d Elapsed (%(fps)5.2f FPS)") % {
                'hours': seconds_run / 3600,
                'minutes': (seconds_run / 60) % 60,
                'seconds': seconds_run % 60,
                'fps': fps_encode}

            get_app().window.ExportFrame.emit(title_message, video_settings.get("start_frame"), video_settings.get("end_frame"), frame)
            '''

        except Exception as e:
            # TODO: Find a better way to catch the error. This is the only way I have found that
            # does not throw an error
            error_type_str = str(e)
            log.info("Error type string: %s" % error_type_str)

            if "InvalidChannels" in error_type_str:
                log.info("Error setting invalid # of channels (%s)" %
                         (audio_settings.get("channels")))
                track_metric_error("invalid-channels-%s-%s-%s-%s" %
                                   (video_settings.get("vformat"),
                                    video_settings.get("vcodec"),
                                    audio_settings.get("acodec"),
                                    audio_settings.get("channels")))

            elif "InvalidSampleRate" in error_type_str:
                log.info("Error setting invalid sample rate (%s)" %
                         (audio_settings.get("sample_rate")))
                track_metric_error("invalid-sample-rate-%s-%s-%s-%s" %
                                   (video_settings.get("vformat"),
                                    video_settings.get("vcodec"),
                                    audio_settings.get("acodec"),
                                    audio_settings.get("sample_rate")))

            elif "InvalidFormat" in error_type_str:
                log.info("Error setting invalid format (%s)" %
                         (video_settings.get("vformat")))
                track_metric_error("invalid-format-%s" %
                                   (video_settings.get("vformat")))

            elif "InvalidCodec" in error_type_str:
                log.info("Error setting invalid codec (%s/%s/%s)" %
                         (video_settings.get("vformat"),
                          video_settings.get("vcodec"),
                          audio_settings.get("acodec")))
                track_metric_error("invalid-codec-%s-%s-%s" %
                                   (video_settings.get("vformat"),
                                    video_settings.get("vcodec"),
                                    audio_settings.get("acodec")))

            elif "ErrorEncodingVideo" in error_type_str:
                log.info("Error encoding video frame (%s/%s/%s)" %
                         (video_settings.get("vformat"),
                          video_settings.get("vcodec"),
                          audio_settings.get("acodec")))
                track_metric_error("video-encode-%s-%s-%s" %
                                   (video_settings.get("vformat"),
                                    video_settings.get("vcodec"),
                                    audio_settings.get("acodec")))

            # Show friendly error
            friendly_error = error_type_str.split("> ")[0].replace("<", "")

            # Prompt error message
            msg = QMessageBox()
            msg.setWindowTitle(_("Export Error"))
            msg.setText(
                _("Sorry, there was an error exporting your video: \n%s") %
                friendly_error)
            msg.exec_()

        # Notify window of export started
        get_app().window.ExportEnded.emit(export_file_path)

        # Close timeline object
        self.timeline.Close()

        # Clear all cache
        self.timeline.ClearAllCache()

        # Re-set OMP thread enabled flag
        if self.s.get("omp_threads_enabled"):
            openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = False
        else:
            openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = True

        # Return scale mode to lower quality scaling (for faster previews)
        openshot.Settings.Instance().HIGH_QUALITY_SCALING = False

        # Handle end of export (for non-canceled exports)
        # if self.s.get("show_finished_window") and self.exporting:
        #     # Hide cancel and export buttons
        #     self.cancel_button.setVisible(False)
        #     self.export_button.setVisible(False)
        #
        #     # Reveal done button
        #     self.close_button.setVisible(True)
        #
        #     # Make progress bar green (to indicate we are done)
        #     # from PyQt5.QtGui import QPalette
        #     # p = QPalette()
        #     # p.setColor(QPalette.Highlight, Qt.green)
        #     # self.progressExportVideo.setPalette(p)
        #
        #     # Raise the window
        #     self.show()
        # else:
        #     # Accept dialog
        #     super(SuperResolution, self).accept()

        success_hint = QDialog()
        success_hint.setWindowTitle("成功")
        success_hint.exec_()
Esempio n. 49
0
 def onBlenderErrorNoData(self):
     log.info('onBlenderErrorNoData')
     self.error_with_blender()
Esempio n. 50
0
    def Render(self, blend_file_path, target_script, preview_mode=False):
        """ Worker's Render method which invokes the Blender rendering commands """
        log.info("QThread Render Method Invoked")

        # Init regex expression used to determine blender's render progress
        s = settings.get_settings()

        # get the blender executable path
        self.blender_exec_path = s.get("blender_command")
        self.blender_frame_expression = re.compile(
            r"Fra:([0-9,]*).*Mem:(.*?) .*Part ([0-9,]*)-([0-9,]*)")
        self.blender_saved_expression = re.compile(r"Saved: (.*.png)(.*)")
        self.blender_version = re.compile(r"Blender (.*?) ")
        self.blend_file_path = blend_file_path
        self.target_script = target_script
        self.preview_mode = preview_mode
        self.frame_detected = False
        self.version = None
        self.command_output = ""
        self.process = None
        self.is_running = True
        _ = get_app()._tr

        try:
            # Shell the blender command to create the image sequence
            command_get_version = [self.blender_exec_path, '-v']
            command_render = [
                self.blender_exec_path, '-b', self.blend_file_path, '-P',
                self.target_script
            ]
            self.process = subprocess.Popen(command_get_version,
                                            stdout=subprocess.PIPE)

            # Check the version of Blender
            self.version = self.blender_version.findall(
                str(self.process.stdout.readline()))

            if self.version:
                if float(self.version[0]) < 2.62:
                    # change cursor to "default" and stop running blender command
                    self.is_running = False

                    # Wrong version of Blender.  Must be 2.62+:
                    self.blender_version_error.emit(float(self.version[0]))
                    return

            # debug info
            log.info("Blender command: {} {} '{}' {} '{}'".format(
                command_render[0], command_render[1], command_render[2],
                command_render[3], command_render[4]))

            # Run real command to render Blender project
            self.process = subprocess.Popen(command_render,
                                            stdout=subprocess.PIPE)

        except:
            # Error running command.  Most likely the blender executable path in the settings
            # is not correct, or is not the correct version of Blender (i.e. 2.62+)
            self.is_running = False
            self.blender_error_nodata.emit()
            return

        while self.is_running and self.process.poll() is None:

            # Look for progress info in the Blender Output
            line = str(self.process.stdout.readline())
            self.command_output = self.command_output + line + "\n"  # append all output into a variable
            output_frame = self.blender_frame_expression.findall(line)

            # Does it have a match?
            if output_frame:
                # Yes, we have a match
                self.frame_detected = True
                current_frame = output_frame[0][0]
                memory = output_frame[0][1]
                current_part = output_frame[0][2]
                max_parts = output_frame[0][3]

                # Update progress bar
                if not self.preview_mode:
                    # only update progress if in 'render' mode
                    self.progress.emit(float(current_frame),
                                       float(current_part), float(max_parts))

            # Look for progress info in the Blender Output
            output_saved = self.blender_saved_expression.findall(str(line))

            # Does it have a match?
            if output_saved:
                # Yes, we have a match
                self.frame_detected = True
                image_path = output_saved[0][0]
                time_saved = output_saved[0][1]

                # Update preview image
                self.image_updated.emit(image_path)

        # Re-enable the interface
        self.enable_interface.emit()

        # Check if NO FRAMES are detected
        if not self.frame_detected:
            # Show Error that no frames are detected.  This is likely caused by
            # the wrong command being executed... or an error in Blender.
            self.blender_error_with_data.emit(
                _("No frame was found in the output from Blender"))

        # Done with render (i.e. close window)
        elif not self.preview_mode:
            # only close window if in 'render' mode
            self.finished.emit()

        # Thread finished
        log.info("Blender render thread finished")
        if self.is_running == False:
            # close window if thread was killed
            self.closed.emit()

        # mark thread as finished
        self.is_running = False
Esempio n. 51
0
 def onRenderFinish(self):
     log.info('onRenderFinish')
     self.render_finished()
Esempio n. 52
0
 def onBlenderErrorMessage(self, error):
     log.info('onBlenderErrorMessage')
     self.error_with_blender(None, error)
Esempio n. 53
0
    def currentChanged(self, selected, deselected):
        # Get selected item
        self.selected = selected
        self.deselected = deselected

        # Get translation object
        _ = self.app._tr

        # Clear existing settings
        self.win.clear_effect_controls()

        # Get animation details
        animation = self.get_animation_details()
        self.selected_template = animation["service"]

        # Assign a new unique id for each template selected
        self.generateUniqueFolder()

        # Loop through params
        for param in animation["params"]:
            log.info(param["title"])

            # Is Hidden Param?
            if param["name"] == "start_frame" or param["name"] == "end_frame":
                # add value to dictionary
                self.params[param["name"]] = int(param["default"])

                # skip to next param without rendering the controls
                continue

            # Create Label
            widget = None
            label = QLabel()
            label.setText(_(param["title"]))
            label.setToolTip(_(param["title"]))

            if param["type"] == "spinner":
                # add value to dictionary
                self.params[param["name"]] = float(param["default"])

                # create spinner
                widget = QDoubleSpinBox()
                widget.setMinimum(float(param["min"]))
                widget.setMaximum(float(param["max"]))
                widget.setValue(float(param["default"]))
                widget.setSingleStep(0.01)
                widget.setToolTip(param["title"])
                widget.valueChanged.connect(
                    functools.partial(self.spinner_value_changed, param))

            elif param["type"] == "text":
                # add value to dictionary
                self.params[param["name"]] = _(param["default"])

                # create spinner
                widget = QLineEdit()
                widget.setText(_(param["default"]))
                widget.textChanged.connect(
                    functools.partial(self.text_value_changed, widget, param))

            elif param["type"] == "multiline":
                # add value to dictionary
                self.params[param["name"]] = _(param["default"])

                # create spinner
                widget = QTextEdit()
                widget.setText(_(param["default"]).replace("\\n", "\n"))
                widget.textChanged.connect(
                    functools.partial(self.text_value_changed, widget, param))

            elif param["type"] == "dropdown":
                # add value to dictionary
                self.params[param["name"]] = param["default"]

                # create spinner
                widget = QComboBox()
                widget.currentIndexChanged.connect(
                    functools.partial(self.dropdown_index_changed, widget,
                                      param))

                # Add values to dropdown
                if "project_files" in param["name"]:
                    # override files dropdown
                    param["values"] = {}
                    for file in File.filter():
                        if file.data["media_type"] in ("image", "video"):
                            (dirName,
                             fileName) = os.path.split(file.data["path"])
                            (fileBaseName,
                             fileExtension) = os.path.splitext(fileName)

                            if fileExtension.lower() not in (".svg"):
                                param["values"][fileName] = "|".join(
                                    (file.data["path"],
                                     str(file.data["height"]),
                                     str(file.data["width"]),
                                     file.data["media_type"],
                                     str(file.data["fps"]["num"] /
                                         file.data["fps"]["den"])))

                # Add normal values
                box_index = 0
                for k, v in sorted(param["values"].items()):
                    # add dropdown item
                    widget.addItem(_(k), v)

                    # select dropdown (if default)
                    if v == param["default"]:
                        widget.setCurrentIndex(box_index)
                    box_index = box_index + 1

                if not param["values"]:
                    widget.addItem(_("No Files Found"), "")
                    widget.setEnabled(False)

            elif param["type"] == "color":
                # add value to dictionary
                color = QColor(param["default"])
                self.params[param["name"]] = [
                    color.redF(), color.greenF(),
                    color.blueF()
                ]

                widget = QPushButton()
                widget.setText("")
                widget.setStyleSheet("background-color: {}".format(
                    param["default"]))
                widget.clicked.connect(
                    functools.partial(self.color_button_clicked, widget,
                                      param))

            # Add Label and Widget to the form
            if (widget and label):
                self.win.settingsContainer.layout().addRow(label, widget)
            elif (label):
                self.win.settingsContainer.layout().addRow(label)

        # Enable interface
        self.enable_interface()

        # Init slider values
        self.init_slider_values()
Esempio n. 54
0
 def onBlenderVersionError(self, version):
     log.info('onBlenderVersionError')
     self.error_with_blender(version)
Esempio n. 55
0
 def dropdown_index_changed(self, widget, param, index):
     value = widget.itemData(index)
     self.params[param["name"]] = value
     log.info(value)
Esempio n. 56
0
 def onCloseWindow(self):
     log.info('onCloseWindow')
     self.close()
Esempio n. 57
0
 def log_message(self, msg_format, *args):
     """ Log message from HTTPServer """
     log.info(msg_format % args)
Esempio n. 58
0
    def close_window(self):
        log.info("CLOSING WINDOW")

        # Close window
        self.close()
Esempio n. 59
0
 def kill(self):
     self.running = False
     log.info('Shutting down thumbnail server: %s' %
              str(self.server_address))
     self.thumbServer.shutdown()
Esempio n. 60
0
 def spinner_value_changed(self, param, value):
     self.params[param["name"]] = value
     log.info(value)