Created
August 16, 2021 17:03
-
-
Save alexjercan/2b0dceaaf61923d80be3018178255873 to your computer and use it in GitHub Desktop.
Python script that uses the Blender Video Editor to automate image sequence plus audio into video file
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
import os | |
import re | |
import sys | |
import bpy | |
import argparse | |
from pathlib import Path | |
def atoi(text): | |
return int(text) if text.isdigit() else text | |
def natural_keys(paths): | |
return [ atoi(c) for c in re.split(r'(\d+)', str(paths)) ] | |
def image_strip_add(sequence_editor, files): | |
filepath, filename = str(files[0]), files[0].name | |
imstrip = sequence_editor.sequences.new_image(filename, filepath=filepath, channel=1, frame_start=0) | |
for file in files[1:]: | |
imstrip.elements.append(file.name) | |
imstrip.frame_final_duration = len(files) | |
imstrip.update() | |
def sound_strip_add(sequence_editor, file): | |
sequence_editor.sequences.new_sound(file, filepath=file, channel=1, frame_start=0) | |
if __name__ == "__main__": | |
AUDIO_DEFAULT_PATH = os.path.abspath(os.path.join("..", "resources", "Sigma Male Theme Song.mp3")) | |
IMAGES_DEFAULT_ROOT_PATH = os.path.abspath(os.path.join("..", "yt-comments-to-pngs", "out")) | |
OUTPUT_DEFAULT_ROOT_PATH = os.path.abspath(os.path.join("..", "out")) | |
parser = argparse.ArgumentParser(description='Generate video with bpy editor') | |
parser.add_argument("--audio", type=str, default=AUDIO_DEFAULT_PATH, help="Path to music file") | |
parser.add_argument("--imgs_dir", type=str, default=IMAGES_DEFAULT_ROOT_PATH, help="Path to images root dir") | |
parser.add_argument("--out_dir", type=str, default=OUTPUT_DEFAULT_ROOT_PATH, help="Path to output root dir") | |
args = sys.argv[sys.argv.index("--") + 1:] | |
args = parser.parse_args(args) | |
print(args) | |
## SCENE SETUP ## | |
bpy.context.scene.view_settings.view_transform = 'Standard' | |
bpy.context.scene.frame_start = 0 | |
bpy.context.scene.frame_end = 34 | |
bpy.context.scene.frame_step = 1 | |
bpy.context.scene.render.fps = 1 | |
bpy.context.scene.render.fps_base = 8 | |
bpy.context.scene.render.image_settings.file_format = 'FFMPEG' | |
bpy.context.scene.render.ffmpeg.constant_rate_factor = 'PERC_LOSSLESS' | |
bpy.context.scene.render.ffmpeg.ffmpeg_preset = 'BEST' | |
bpy.context.scene.render.ffmpeg.gopsize = 1 | |
bpy.context.scene.render.ffmpeg.audio_codec = 'MP3' | |
## Load images ## | |
image_filepaths = list(sorted(Path(args.imgs_dir).glob("*.png"), key=natural_keys)) | |
n_images = len(image_filepaths) | |
frame_step = 35 | |
for index, frame_start in enumerate(range(0, n_images, frame_step)): | |
bpy.context.scene.render.filepath = os.path.join(args.out_dir, "part%d_" % index) | |
## Create editor ## | |
bpy.context.scene.sequence_editor_clear() | |
sequence_editor = bpy.context.scene.sequence_editor_create() | |
## Load audio ## | |
sound_strip_add(sequence_editor, args.audio) | |
current_filepaths = image_filepaths[frame_start:frame_start+frame_step] | |
image_strip_add(sequence_editor, current_filepaths) | |
## Render ## | |
bpy.ops.render.render(animation=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment