2
$\begingroup$

I am trying to batch render few sequence like 1 to 10 and then 30 to 50 but rendering stops after completing one sequence.

def execute(self, context): batcher = bpy.context.scene.batch_render sce = bpy.context.scene rd = sce.render batch_count = 0 for it in batcher.frame_ranges: batch_count += 1 print("***********") if (it.end_frame < it.start_frame): print("Skipped batch " + str(it.start_frame) + " - " + str(it.end_frame) + ": Start frame greater than end frame") continue sce.frame_start = it.start_frame sce.frame_end = it.end_frame sce.render.filepath = it.filepath bpy.ops.render.render('INVOKE_DEFAULT',animation = True) sum = 0 for it in batcher.frame_ranges: if (it.end_frame >= it.start_frame): sum += (it.end_frame - it.start_frame) print("Rendered " + str(len(batcher.frame_ranges)) + " batches containing " + str(sum) + " frames") return {'FINISHED'} 

if I put this line:

bpy.ops.render.render('INVOKE_DEFAULT',animation = True) 

then it renders only one batch

if I put this line :

bpy.ops.render.render(animation = True) 

it renders all batch without any issue .. but it freeze blender and doesn't show render progress bar.

I want to see progress bar and do batch rendering.

$\endgroup$

1 Answer 1

3
$\begingroup$

I'd suggest using handlers for this task. Below is a script that adds a full set of render handlers, and prints the current frame (if possible) and name of the handler when that handler fires.

import bpy frame_handlers = [name for name in dir(bpy.app.handlers) ] def handler_function(name): def handler(scene): print(f"{getattr(scene, 'frame_current', 'N/A')} : {name}") return handler for name in frame_handlers: handler = getattr(bpy.app.handlers, name, None) if isinstance(handler, list): handler.clear() # clear first for testing handler.append(handler_function(name)) 

System console output for a 2 frame animation render, must have started render with current frame set at 0. (v 2.91)

0 : render_init 1 : render_pre 1 : frame_change_pre 1 : frame_change_post Saved: '/tmp/0001.png' Time: 00:00.47N/A : render_stats (Saving: 00:00.03) 1 : render_post 1 : render_write 2 : render_pre 2 : frame_change_pre 2 : frame_change_post Saved: '/tmp/0002.png' Time: 00:00.38N/A : render_stats (Saving: 00:00.02) 2 : render_post 2 : render_write 0 : render_complete 0 : frame_change_pre 0 : frame_change_post 

Experiment and see the order the handers are called firing "render_init"... etc until, "render_compete"

Setting it up

In Operator execute, set the scene settings to first batch, call the render op and add the render_complete handler.

# add the handler. bpy.app.handlers.render_complete.append(render_complete) 

The render complete handler

change scene settings to the next batch item and call render op again

You will need to keep tabs on which batch is rendered with an active_index property (or similar), (also handy for displaying the items in a UIList widget) Please note this is just code typed into answer and not tested.

def render_complete(scene): batches = scene.frame_ranges i = batches.active_index if i < len(batches) - 1: batch = batches(i+1) # set up scene bpy.ops.render.render('INVOKE_DEFAUT', animation=True) else: #clear this hander bpy.app.handers.render_complete.remove(render_complete) 

Experiment...

$\endgroup$
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.