Blender image sequences now generate a preview mp4 on completion

This commit is contained in:
Brett Williams
2023-05-27 16:01:54 -05:00
parent 55591c10e1
commit eaacbf4ec0
5 changed files with 28 additions and 5 deletions

View File

@@ -187,6 +187,10 @@ class BaseRenderWorker(object):
if not self.errors: if not self.errors:
self.errors = [self.last_output] self.errors = [self.last_output]
self.is_finished = True self.is_finished = True
self.post_processing()
def post_processing(self):
pass
def is_running(self): def is_running(self):
if self.__thread: if self.__thread:

View File

@@ -113,6 +113,24 @@ class BlenderRenderWorker(BaseRenderWorker):
total_percent = whole_frame_percent + adjusted_frame_percent total_percent = whole_frame_percent + adjusted_frame_percent
return max(total_percent, 0) return max(total_percent, 0)
def post_processing(self):
output_dir = os.listdir(os.path.dirname(self.output_path))
if self.render_all_frames and len(output_dir) > 1:
from ..utilities.ffmpeg_helper import image_sequence_to_video
logger.info("Generating preview for image sequence")
# get proper file extension
found_output = next(obj for obj in output_dir if os.path.basename(self.output_path) in obj)
glob_pattern = self.output_path + '%04d' + ('.' + found_output.split('.')[-1] if found_output else "")
try:
image_sequence_to_video(source_glob_pattern=glob_pattern,
output_path=self.output_path + '_preview.mp4',
framerate=self.scene_info['fps'])
logger.info('Successfully generated preview image sequence')
except Exception as e:
logger.error('Error generating image sequence')
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -269,7 +269,7 @@ def add_job_handler():
job['input_path'] = uploaded_file_local_path job['input_path'] = uploaded_file_local_path
output_dir = os.path.join(job_dir, job.get('name', None) or 'output') output_dir = os.path.join(job_dir, job.get('name', None) or 'output')
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
job['output_path'] = os.path.join(output_dir, os.path.basename(job['output_path'])) job['output_path'] = os.path.join(output_dir, os.path.basename(job.get('name', job['output_path'])))
remove_job_dir = len(jobs_list) == 1 and uploaded_file_local_path # remove failed job dir for single file uploads only remove_job_dir = len(jobs_list) == 1 and uploaded_file_local_path # remove failed job dir for single file uploads only
add_result = add_job(job, remove_job_dir_on_failure=remove_job_dir) add_result = add_job(job, remove_job_dir_on_failure=remove_job_dir)
results.append(add_result) results.append(add_result)

View File

@@ -1,5 +1,6 @@
import subprocess import subprocess
import ffmpeg # todo: remove all references to ffmpeg library and instead use direct subprocesses import ffmpeg # todo: remove all references to ffmpeg library and instead use direct subprocesses
from ..render_engines.ffmpeg_engine import FFMPEG
def file_info(path): def file_info(path):
@@ -10,9 +11,9 @@ def file_info(path):
return None return None
def image_sequence_to_video(source_glob_pattern, output_path, framerate="24", encoder="libx264"): def image_sequence_to_video(source_glob_pattern, output_path, framerate="24", encoder="libx264", pix_fmt="yuv420p"):
subprocess.run(['ffmpeg', "-y", "-framerate", framerate, "-pattern_type", "glob", "-i", f"{source_glob_pattern}", subprocess.run([FFMPEG.renderer_path(), "-framerate", str(framerate), "-i", f"{source_glob_pattern}",
"-c:v", encoder, output_path]) "-c:v", encoder, "-pix_fmt", pix_fmt, output_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def save_first_frame(source_path, dest_path, max_width=1280, run_async=False): def save_first_frame(source_path, dest_path, max_width=1280, run_async=False):

View File

@@ -214,7 +214,7 @@ class ScheduleJob(Frame):
self.output_entry.delete(0, END) self.output_entry.delete(0, END)
if self.chosen_file: if self.chosen_file:
# Generate a default output name # Generate a default output name
output_name = os.path.basename(self.chosen_file).split('.')[0] + '-output' output_name = os.path.basename(self.chosen_file).split('.')[0]
self.output_entry.insert(0, os.path.basename(output_name)) self.output_entry.insert(0, os.path.basename(output_name))
# Try to determine file type # Try to determine file type
extension = self.chosen_file.split('.')[-1] # not the best way to do this extension = self.chosen_file.split('.')[-1] # not the best way to do this