mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 07:29:49 +00:00
Export videos with audio
Only works with mp3 for now
This commit is contained in:
parent
963eef4124
commit
47fb74b268
|
@ -427,7 +427,7 @@ func export_processed_images(
|
|||
|
||||
if is_single_file_format(project):
|
||||
if is_using_ffmpeg(project.file_format):
|
||||
var video_exported := export_video(export_paths)
|
||||
var video_exported := export_video(export_paths, project)
|
||||
if not video_exported:
|
||||
Global.popup_error(
|
||||
tr("Video failed to export. Ensure that FFMPEG is installed correctly.")
|
||||
|
@ -505,8 +505,9 @@ func export_processed_images(
|
|||
|
||||
|
||||
## Uses FFMPEG to export a video
|
||||
func export_video(export_paths: PackedStringArray) -> bool:
|
||||
func export_video(export_paths: PackedStringArray, project: Project) -> bool:
|
||||
DirAccess.make_dir_absolute(TEMP_PATH)
|
||||
var video_duration := 0
|
||||
var temp_path_real := ProjectSettings.globalize_path(TEMP_PATH)
|
||||
var input_file_path := temp_path_real.path_join("input.txt")
|
||||
var input_file := FileAccess.open(input_file_path, FileAccess.WRITE)
|
||||
|
@ -516,25 +517,65 @@ func export_video(export_paths: PackedStringArray) -> bool:
|
|||
processed_images[i].image.save_png(temp_file_path)
|
||||
input_file.store_line("file '" + temp_file_name + "'")
|
||||
input_file.store_line("duration %s" % processed_images[i].duration)
|
||||
video_duration += processed_images[i].duration
|
||||
input_file.close()
|
||||
|
||||
# ffmpeg -y -f concat -i input.txt output_path
|
||||
var ffmpeg_execute: PackedStringArray = [
|
||||
"-y", "-f", "concat", "-i", input_file_path, export_paths[0]
|
||||
]
|
||||
var output := []
|
||||
var success := OS.execute(Global.ffmpeg_path, ffmpeg_execute, output, true)
|
||||
print(output)
|
||||
var temp_dir := DirAccess.open(TEMP_PATH)
|
||||
for file in temp_dir.get_files():
|
||||
temp_dir.remove(file)
|
||||
DirAccess.remove_absolute(TEMP_PATH)
|
||||
var success := OS.execute(Global.ffmpeg_path, ffmpeg_execute, [], true)
|
||||
if success < 0 or success > 1:
|
||||
var fail_text := """Video failed to export. Make sure you have FFMPEG installed
|
||||
and have set the correct path in the preferences."""
|
||||
Global.popup_error(tr(fail_text))
|
||||
_clear_temp_folder()
|
||||
return false
|
||||
# ffmpeg -i input1 -i input2 ... -i inputn -filter_complex amix=inputs=n output_path
|
||||
var ffmpeg_combine_audio: PackedStringArray = ["-y"]
|
||||
var audio_layer_count := 0
|
||||
var max_audio_duration := 0
|
||||
for layer in project.layers:
|
||||
if layer is AudioLayer and layer.audio is AudioStreamMP3:
|
||||
var temp_file_name := str(audio_layer_count + 1).pad_zeros(number_of_digits) + ".mp3"
|
||||
var temp_file_path := temp_path_real.path_join(temp_file_name)
|
||||
var temp_audio_file := FileAccess.open(temp_file_path, FileAccess.WRITE)
|
||||
temp_audio_file.store_buffer(layer.audio.data)
|
||||
audio_layer_count += 1
|
||||
ffmpeg_combine_audio.append("-i")
|
||||
ffmpeg_combine_audio.append(temp_file_path)
|
||||
if layer.audio.get_length() >= max_audio_duration:
|
||||
max_audio_duration = layer.audio.get_length()
|
||||
if audio_layer_count > 0:
|
||||
var amix_inputs_string := "amix=inputs=%s" % audio_layer_count
|
||||
var audio_file_path := temp_path_real.path_join("audio.mp3")
|
||||
ffmpeg_combine_audio.append_array(
|
||||
PackedStringArray(["-filter_complex", amix_inputs_string, audio_file_path])
|
||||
)
|
||||
OS.execute(Global.ffmpeg_path, ffmpeg_combine_audio, [], true)
|
||||
var copied_video := temp_path_real.path_join("video." + export_paths[0].get_extension())
|
||||
DirAccess.copy_absolute(export_paths[0], copied_video)
|
||||
# ffmpeg -y -i video_file -i input_audio -c:v copy -map 0:v:0 -map 1:a:0 video_file
|
||||
var ffmpeg_final_video: PackedStringArray = [
|
||||
"-y", "-i", copied_video, "-i", audio_file_path
|
||||
]
|
||||
if max_audio_duration > video_duration:
|
||||
ffmpeg_final_video.append("-shortest")
|
||||
ffmpeg_final_video.append_array(
|
||||
["-c:v", "copy", "-map", "0:v:0", "-map", "1:a:0", export_paths[0]]
|
||||
)
|
||||
OS.execute(Global.ffmpeg_path, ffmpeg_final_video, [], true)
|
||||
_clear_temp_folder()
|
||||
return true
|
||||
|
||||
|
||||
func _clear_temp_folder() -> void:
|
||||
var temp_dir := DirAccess.open(TEMP_PATH)
|
||||
for file in temp_dir.get_files():
|
||||
temp_dir.remove(file)
|
||||
DirAccess.remove_absolute(TEMP_PATH)
|
||||
|
||||
|
||||
func export_animated(args: Dictionary) -> void:
|
||||
var project: Project = args["project"]
|
||||
var exporter: AImgIOBaseExporter = args["exporter"]
|
||||
|
|
Loading…
Reference in a new issue