def export(self): # $ dpkg -L openshot-qt | grep export # /usr/lib/python3/dist-packages/openshot_qt/windows/export.py # /usr/lib/python3/dist-packages/openshot_qt/windows/ui/export.ui # 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(250) self.timeline.SetCache(export_cache_object) export_file_path = THE_EXPORT_FILE_PATH #print(self.timeline.Json()) #sys.exit(0) # /usr/share/doc/libopenshot-doc/html/classopenshot_1_1FFmpegWriter.html try: w = openshot.FFmpegWriter(export_file_path) w.SetVideoOptions(True, "libvpx", openshot.Fraction(24, 1), 720, 480, openshot.Fraction(1, 1), False, False, 300000) w.SetAudioOptions(True, "libvorbis", 44100, 2, 3, 128000) # Open the writer w.Open() #240 = 24fps x 10s; #300 = 30fps x 10s; for frame in range(1, 240): w.WriteFrame(self.timeline.GetFrame(frame)) # Close writer w.Close() except Exception as e: print(e)
def export(self, filename, audio_options, video_options, start_frame, last_frame, view): """ Writes the video to the disk. @param filename: name of the file in which the video is saved @param audio_options: list of audio options @param video_options: list of video options @param last_frame: number of the last frame that's exported """ self.timeline.Open() # create writer w = openshot.FFmpegWriter(filename) # set options w.SetAudioOptions(*audio_options) w.SetVideoOptions(*video_options) w.Open() bar = view.export_progress step = int((last_frame - start_frame) / 100) # export video for frame_number in range(start_frame, last_frame): if view.canceled: break QApplication.processEvents() w.WriteFrame(self.timeline.GetFrame(frame_number)) if frame_number % step == 0: bar.setValue(bar.value() + 1) print("finished export") w.Close()
def accept(self): """ Start exporting video """ # Disable controls self.txtFileName.setEnabled(False) self.txtExportFolder.setEnabled(False) self.tabWidget.setEnabled(False) self.export_button.setEnabled(False) self.exporting = True # Determine final exported file path file_name_with_ext = "%s.%s" % (self.txtFileName.text().strip(), self.txtVideoFormat.text().strip()) export_file_path = os.path.join(self.txtExportFolder.text().strip(), file_name_with_ext) log.info(export_file_path) # Translate object _ = get_app()._tr # Handle exception if os.path.exists(export_file_path): # File already exists! Prompt user ret = QMessageBox.question( self, _("Export Video"), _("%s already exists.\nDo you want to replace it?") % file_name_with_ext, QMessageBox.No | QMessageBox.Yes) if ret == QMessageBox.No: # Stop and don't do anything # Re-enable controls self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Init export settings video_settings = { "vformat": self.txtVideoFormat.text(), "vcodec": self.txtVideoCodec.text(), "fps": { "num": self.txtFrameRateNum.value(), "den": self.txtFrameRateDen.value() }, "width": self.txtWidth.value(), "height": self.txtHeight.value(), "pixel_ratio": { "num": self.txtPixelRatioNum.value(), "den": self.txtPixelRatioDen.value() }, "video_bitrate": int(self.convert_to_bytes(self.txtVideoBitRate.text())), "start_frame": self.txtStartFrame.value(), "end_frame": self.txtEndFrame.value() + 1 } audio_settings = { "acodec": self.txtAudioCodec.text(), "sample_rate": self.txtSampleRate.value(), "channels": self.txtChannels.value(), "channel_layout": self.cboChannelLayout.currentData(), "audio_bitrate": int(self.convert_to_bytes(self.txtAudioBitrate.text())) } # Set lossless cache settings (temporarily) export_cache_object = openshot.CacheMemory(250) self.timeline.SetCache(export_cache_object) # Create FFmpegWriter try: w = openshot.FFmpegWriter(export_file_path) # Set video options 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")) # Set audio options w.SetAudioOptions(True, audio_settings.get("acodec"), audio_settings.get("sample_rate"), audio_settings.get("channels"), audio_settings.get("channel_layout"), audio_settings.get("audio_bitrate")) # Open the writer w.Open() # Notify window of export started get_app().window.ExportStarted.emit( export_file_path, video_settings.get("start_frame"), 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")): # Update progress bar (emit signal to main window) get_app().window.ExportFrame.emit( export_file_path, 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() 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() _ = get_app()._tr 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 cache export_cache_object.Clear() # Accept dialog super(Export, self).accept()
def accept(self): """ Start exporting video, but don't close window """ # Get settings self.s = settings.get_settings() # Disable controls self.txtFileName.setEnabled(False) self.txtExportFolder.setEnabled(False) self.tabWidget.setEnabled(False) self.export_button.setEnabled(False) self.exporting = True # Test Succeeded # Determine final exported file path file_name_with_ext = "%s.%s" % (self.txtFileName.text().strip(), self.txtVideoFormat.text().strip()) export_file_path = os.path.join(self.txtExportFolder.text().strip(), file_name_with_ext) log.info(export_file_path) # Translate object _ = get_app()._tr # Handle exception if os.path.exists(export_file_path): # File already exists! Prompt user ret = QMessageBox.question(self, _("Export Video"), _("%s already exists.\nDo you want to replace it?") % file_name_with_ext, QMessageBox.No | QMessageBox.Yes) if ret == QMessageBox.No: # Stop and don't do anything # Re-enable controls self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Create FFmpegWriter try: w = openshot.FFmpegWriter(export_file_path) # Set video options w.SetVideoOptions(True, self.txtVideoCodec.text(), openshot.Fraction(self.txtFrameRateNum.value(), self.txtFrameRateDen.value()), self.txtWidth.value(), self.txtHeight.value(), openshot.Fraction(self.txtPixelRatioNum.value(), self.txtPixelRatioDen.value()), False, False, int(self.convert_to_bytes(self.txtVideoBitRate.text()))) # Set audio options w.SetAudioOptions(True, self.txtAudioCodec.text(), self.txtSampleRate.value(), self.txtChannels.value(), self.cboChannelLayout.currentData(), int(self.convert_to_bytes(self.txtAudioBitrate.text()))) # Open the writer w.Open() # Init progress bar self.progressExportVideo.setMinimum(self.txtStartFrame.value()) self.progressExportVideo.setMaximum(self.txtEndFrame.value()) # Write each frame in the selected range for frame in range(self.txtStartFrame.value(), self.txtEndFrame.value() + 1): # Update progress bar self.progressExportVideo.setValue(frame) # Process events (to show the progress bar moving) QCoreApplication.processEvents() # Write the frame object to the video w.WriteFrame(get_app().window.timeline_sync.timeline.GetFrame(frame)) # Check if we need to bail out if not self.exporting: break # Close writer w.Close() 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)" % (self.txtChannels.value())) track_metric_error("invalid-channels-%s-%s-%s-%s" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text(), self.txtChannels.value())) elif "InvalidSampleRate" in error_type_str: log.info("Error setting invalid sample rate (%s)" % (self.txtSampleRate.value())) track_metric_error("invalid-sample-rate-%s-%s-%s-%s" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text(), self.txtSampleRate.value())) elif "InvalidFormat" in error_type_str: log.info("Error setting invalid format (%s)" % (self.txtVideoFormat.text())) track_metric_error("invalid-format-%s" % (self.txtVideoFormat.text())) elif "InvalidCodec" in error_type_str: log.info("Error setting invalid codec (%s/%s/%s)" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text())) track_metric_error("invalid-codec-%s-%s-%s" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text())) elif "ErrorEncodingVideo" in error_type_str: log.info("Error encoding video frame (%s/%s/%s)" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text())) track_metric_error("video-encode-%s-%s-%s" % (self.txtVideoFormat.text(), self.txtVideoCodec.text(), self.txtAudioCodec.text())) # Show friendly error friendly_error = error_type_str.split("> ")[0].replace("<", "") # Prompt error message msg = QMessageBox() _ = get_app()._tr msg.setWindowTitle(_("Export Error")) msg.setText(_("Sorry, there was an error exporting your video: \n%s") % friendly_error) msg.exec_() # Accept dialog super(Export, self).accept() # Restore timeline settings self.restoreTimeline() log.info("End Accept")
def accept(self): """ Start exporting video """ # get translations app = get_app() _ = app._tr # Disable controls self.txtFileName.setEnabled(False) self.txtExportFolder.setEnabled(False) self.tabWidget.setEnabled(False) self.export_button.setEnabled(False) self.exporting = True # Determine type of export (video+audio, video, audio, image sequences) # _("Video & Audio"), _("Video Only"), _("Audio Only"), _("Image Sequence") export_type = self.cboExportTo.currentText() # Determine final exported file path if export_type != _("Image Sequence"): file_name_with_ext = "%s.%s" % (self.txtFileName.text().strip(), self.txtVideoFormat.text().strip()) else: file_name_with_ext = "%s%s" % (self.txtFileName.text().strip(), self.txtImageFormat.text().strip()) export_file_path = os.path.join(self.txtExportFolder.text().strip(), file_name_with_ext) log.info(export_file_path) # Translate object _ = get_app()._tr file = File.get(path=export_file_path) if file: ret = QMessageBox.question( self, _("Export Video"), _("%s is an input file.\nPlease choose a different name.") % file_name_with_ext, QMessageBox.Ok) self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Handle exception if os.path.exists(export_file_path) and export_type in [ _("Video & Audio"), _("Video Only"), _("Audio Only") ]: # File already exists! Prompt user ret = QMessageBox.question( self, _("Export Video"), _("%s already exists.\nDo you want to replace it?") % file_name_with_ext, QMessageBox.No | QMessageBox.Yes) if ret == QMessageBox.No: # Stop and don't do anything # Re-enable controls self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Init export settings video_settings = { "vformat": self.txtVideoFormat.text(), "vcodec": self.txtVideoCodec.text(), "fps": { "num": self.txtFrameRateNum.value(), "den": self.txtFrameRateDen.value() }, "width": self.txtWidth.value(), "height": self.txtHeight.value(), "pixel_ratio": { "num": self.txtPixelRatioNum.value(), "den": self.txtPixelRatioDen.value() }, "video_bitrate": int(self.convert_to_bytes(self.txtVideoBitRate.text())), "start_frame": self.txtStartFrame.value(), "end_frame": self.txtEndFrame.value() + 1 } audio_settings = { "acodec": self.txtAudioCodec.text(), "sample_rate": self.txtSampleRate.value(), "channels": self.txtChannels.value(), "channel_layout": self.cboChannelLayout.currentData(), "audio_bitrate": int(self.convert_to_bytes(self.txtAudioBitrate.text())) } # Override vcodec and format for Image Sequences if export_type == _("Image Sequence"): image_ext = os.path.splitext( self.txtImageFormat.text().strip())[1].replace(".", "") video_settings["vformat"] = image_ext if image_ext in ["jpg", "jpeg"]: video_settings["vcodec"] = "mjpeg" else: video_settings["vcodec"] = image_ext # 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(250) self.timeline.SetCache(export_cache_object) # 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")) # Set audio options if export_type in [_("Video & Audio"), _("Audio Only")]: w.SetAudioOptions(True, audio_settings.get("acodec"), audio_settings.get("sample_rate"), audio_settings.get("channels"), audio_settings.get("channel_layout"), audio_settings.get("audio_bitrate")) # Open the writer w.Open() # Notify window of export started export_file_path = "" 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")): # 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)) export_file_path = _( "%(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 } get_app().window.ExportFrame.emit( export_file_path, 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() 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() _ = get_app()._tr 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"): os.environ['OS2_OMP_THREADS'] = "1" else: os.environ['OS2_OMP_THREADS'] = "0" # Accept dialog super(Export, self).accept()
1280, # width 720, # height -16, # x offset -16, # y offset openshot.GRAVITY_BOTTOM_RIGHT, html_code, css_code, "#000000" # background color ) r.Open() # Open the reader r.DisplayInfo() # Display metadata # Set up Writer w = openshot.FFmpegWriter("pyHtmlExample.mp4") w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720, openshot.Fraction(1, 1), False, False, 3000000) w.info.metadata["title"] = "testtest" w.info.metadata["artist"] = "aaa" w.info.metadata["album"] = "bbb" w.info.metadata["year"] = "2015" w.info.metadata["description"] = "ddd" w.info.metadata["comment"] = "eee" w.info.metadata["comment"] = "comment" w.info.metadata["copyright"] = "copyright OpenShot!" # Open the Writer w.Open()
# This can be run against an uninstalled build of libopenshot, just set the # environment variable PYTHONPATH to the location of the Python bindings. # # For example: # $ PYTHONPATH=../../build/src/bindings/python python3 Example.py # import openshot # Create an FFmpegReader r = openshot.FFmpegReader("sintel_trailer-720p.mp4") r.Open() # Open the reader r.DisplayInfo() # Display metadata # Set up Writer w = openshot.FFmpegWriter("pythonExample.mp4") w.SetAudioOptions(True, "libmp3lame", r.info.sample_rate, r.info.channels, r.info.channel_layout, 128000) w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720, openshot.Fraction(1, 1), False, False, 3000000) w.info.metadata["title"] = "testtest" w.info.metadata["artist"] = "aaa" w.info.metadata["album"] = "bbb" w.info.metadata["year"] = "2015" w.info.metadata["description"] = "ddd" w.info.metadata["comment"] = "eee" w.info.metadata["comment"] = "comment" w.info.metadata["copyright"] = "copyright OpenShot!"
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_()
bitrate = int(sys.argv[9]) # Get audio params audio_codec = sys.argv[10] sample_rate = int(sys.argv[11]) channels = int(sys.argv[12]) channel_layout = int(sys.argv[13]) audio_bitrate = int(sys.argv[14]) # Determine final exported file path export_file_path = os.path.join(EXPORT_TESTS, "test.%s" % format) print("Test Export to %s" % export_file_path) # Create FFmpegWriter w = openshot.FFmpegWriter(export_file_path); # Set Audio & Video Options w.SetVideoOptions(True, codec, fps, width, height, pixel_ratio, False, False, bitrate); w.SetAudioOptions(True, audio_codec, sample_rate, channels, channel_layout, audio_bitrate); w.DisplayInfo() # Open the writer w.Open(); for frame_number in range(30): # Create empty frame f = openshot.Frame(frame_number, width, height, "#ffffff") f.AddColor(width, height, "#ffffff")
def accept(self): """ Start exporting video """ # get translations app = get_app() _ = app._tr # Disable controls self.txtFileName.setEnabled(False) self.txtExportFolder.setEnabled(False) self.tabWidget.setEnabled(False) self.export_button.setEnabled(False) self.exporting = True # Determine type of export (video+audio, video, audio, image sequences) # _("Video & Audio"), _("Video Only"), _("Audio Only"), _("Image Sequence") export_type = self.cboExportTo.currentText() # Determine final exported file path if export_type != _("Image Sequence"): file_name_with_ext = "%s.%s" % (self.txtFileName.text().strip(), self.txtVideoFormat.text().strip()) else: file_name_with_ext = "%s%s" % (self.txtFileName.text().strip(), self.txtImageFormat.text().strip()) export_file_path = os.path.join(self.txtExportFolder.text().strip(), file_name_with_ext) log.info(export_file_path) # Translate object _ = get_app()._tr file = File.get(path=export_file_path) if file: ret = QMessageBox.question( self, _("Export Video"), _("%s is an input file.\nPlease choose a different name.") % file_name_with_ext, QMessageBox.Ok) self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Handle exception if os.path.exists(export_file_path) and export_type in [ _("Video & Audio"), _("Video Only"), _("Audio Only") ]: # File already exists! Prompt user ret = QMessageBox.question( self, _("Export Video"), _("%s already exists.\nDo you want to replace it?") % file_name_with_ext, QMessageBox.No | QMessageBox.Yes) if ret == QMessageBox.No: # Stop and don't do anything # Re-enable controls self.txtFileName.setEnabled(True) self.txtExportFolder.setEnabled(True) self.tabWidget.setEnabled(True) self.export_button.setEnabled(True) self.exporting = False return # Init export settings video_settings = { "vformat": self.txtVideoFormat.text(), "vcodec": self.txtVideoCodec.text(), "fps": { "num": self.txtFrameRateNum.value(), "den": self.txtFrameRateDen.value() }, "width": self.txtWidth.value(), "height": self.txtHeight.value(), "pixel_ratio": { "num": self.txtPixelRatioNum.value(), "den": self.txtPixelRatioDen.value() }, "video_bitrate": int(self.convert_to_bytes(self.txtVideoBitRate.text())), "start_frame": self.txtStartFrame.value(), "end_frame": self.txtEndFrame.value() + 1 } audio_settings = { "acodec": self.txtAudioCodec.text(), "sample_rate": self.txtSampleRate.value(), "channels": self.txtChannels.value(), "channel_layout": self.cboChannelLayout.currentData(), "audio_bitrate": int(self.convert_to_bytes(self.txtAudioBitrate.text())) } # Override vcodec and format for Image Sequences if export_type == _("Image Sequence"): image_ext = os.path.splitext( self.txtImageFormat.text().strip())[1].replace(".", "") video_settings["vformat"] = image_ext if image_ext in ["jpg", "jpeg"]: video_settings["vcodec"] = "mjpeg" else: video_settings["vcodec"] = image_ext # 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(250) self.timeline.SetCache(export_cache_object) # Rescale all keyframes and reload project if self.export_fps_factor != 1.0: self.keyframes_rescaled = True get_app().project.rescale_keyframes(self.export_fps_factor) # Load the "export" Timeline reader with the JSON from the real timeline json_timeline = json.dumps(get_app().project._data) self.timeline.SetJson(json_timeline) # 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")) # Set audio options if export_type in [_("Video & Audio"), _("Audio Only")]: w.SetAudioOptions(True, audio_settings.get("acodec"), audio_settings.get("sample_rate"), audio_settings.get("channels"), audio_settings.get("channel_layout"), audio_settings.get("audio_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 avaliable # 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")))) # Open the writer w.Open() # Notify window of export started export_file_path = "" 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")): # 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)) export_file_path = _("%(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 } get_app().window.ExportFrame.emit(export_file_path, 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 ''' print("====cuts====", self.cuts) fps_num = float(video_settings.get("fps").get("num")) fps_den = float(video_settings.get("fps").get("den")) for cut in self.cuts: start_frame_export = round( float(cut["start"]) * fps_num / fps_den) - 1 end_frame_export = round( float(cut["end"]) * fps_num / fps_den) + 1 progressstep = max( 1, round(end_frame_export - start_frame_export) / 1000) start_time_export = time.time() # Write each frame in the selected range for frame in range(start_frame_export, end_frame_export + 1): print("---frame:", frame) # 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)) export_file_path = _( "%(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 } get_app().window.ExportFrame.emit( export_file_path, start_frame_export, end_frame_export, 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() 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() _ = get_app()._tr 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 # Return keyframes to preview scaling if self.keyframes_rescaled: get_app().project.rescale_keyframes(self.original_fps_factor) # Accept dialog super(Exportting, self).accept()