1
$\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$
2
$\begingroup$

I'd suggest using handlers for this task. Below is a script that adds a full set of render handlers, and prints the name of the handler when that event happens.

import bpy

frame_handlers = [name for name in dir(bpy.app.handlers)
                  if name.startswith("render")]

def handler_function(name):
    def handler(scene):
        print(name)

    return handler

for name in frame_handlers:
    handler = getattr(bpy.app.handlers, name, None)
    if handler is not None:
        handler.append(handler_function(name))

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...

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.