Created
July 13, 2023 18:33
-
-
Save ZachAR3/d119e69f219b5a052bfdf7d1766725e5 to your computer and use it in GitHub Desktop.
FFMPEG Encoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example code from https://github.com/OpenShot/openshot-qt/blob/develop/src/windows/export.py | |
# 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")), | |
video_settings.get("interlace"), | |
video_settings.get("topfirst"), | |
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 available | |
if export_type in [_("Audio Only")]: | |
# Muxing options for mp4/mov | |
w.SetOption(openshot.AUDIO_STREAM, "muxing_preset", "mp4_faststart") | |
else: | |
# Muxing options for mp4/mov | |
w.SetOption(openshot.VIDEO_STREAM, "muxing_preset", "mp4_faststart") | |
# Set the quality in case crf, cqp or qp was selected | |
if "crf" in self.txtVideoBitRate.text(): | |
w.SetOption(openshot.VIDEO_STREAM, "crf", str(int(video_settings.get("video_bitrate"))) ) | |
elif "cqp" in self.txtVideoBitRate.text(): | |
w.SetOption(openshot.VIDEO_STREAM, "cqp", str(int(video_settings.get("video_bitrate"))) ) | |
elif "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 = "" | |
self.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") | |
last_exported_time = time.time() | |
last_displayed_exported_portion = 0.0 | |
# 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) | |
end_time_export = time.time() | |
if ((frame % progressstep) == 0) or ((end_time_export - last_exported_time) > 1): | |
current_exported_portion = (frame - start_frame_export) * 1.0 / (end_frame_export - start_frame_export) | |
if ((current_exported_portion - last_displayed_exported_portion) > 0.0): | |
# the log10 of the difference of the fraction of the completed frames is the negativ | |
# number of digits after the decimal point after which the first digit is not 0 | |
digits_after_decimalpoint = math.ceil( -2.0 - math.log10( current_exported_portion - last_displayed_exported_portion )) | |
else: | |
digits_after_decimalpoint = 1 | |
if digits_after_decimalpoint < 1: | |
# We want at least 1 digit after the decimal point | |
digits_after_decimalpoint = 1 | |
if digits_after_decimalpoint > 5: | |
# We don't want not more than 5 digits after the decimal point | |
digits_after_decimalpoint = 5 | |
last_displayed_exported_portion = current_exported_portion | |
format_of_progress_string = "%4." + str(digits_after_decimalpoint) + "f%% " | |
last_exported_time = 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)) | |
if frame == end_frame_export: | |
title_message = _("Finalizing video export, please wait...") | |
else: | |
title_message = titlestring(seconds_left, fps_encode, "Remaining") | |
# Emit frame exported | |
self.ExportFrame.emit( | |
title_message, | |
video_settings.get("start_frame"), | |
video_settings.get("end_frame"), | |
frame, | |
format_of_progress_string | |
) | |
# Process events (to show the progress bar moving) | |
QCoreApplication.processEvents() | |
# track largest frame processed | |
max_frame = frame | |
# 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 = titlestring(seconds_run, fps_encode, "Elapsed") | |
self.ExportFrame.emit( | |
title_message, | |
video_settings.get("start_frame"), | |
video_settings.get("end_frame"), | |
max_frame, | |
format_of_progress_string | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment