0
$\begingroup$

I am unable to include the composite node effects when rendering an animation as video file from Python/ Blender CLI.

I have a Python Script that dynamically build my Blender 3.6 scene with meshes, textures, camera animation etc. I use it to render these animations as short video files calling a headless Blender instance through the CLI (blender --background --python myScript.py). This works as intended.

Recently I added a Compositing node setup through the script to render a watermark image on top of the scene / video. When I call the script and manually check/render the Blender file everything works as intended. But (!) calling the script from the CLI "background" Blender it will not include compositing effects in the output video file. Maybe I need to call bpy.ops.renderer.render(animation=True, write_still=False) with different arguments to include compositing?

What am I doing wrong? Thanks for the help.


My render function:

def render_animation(output_path: Path, resolution: Tuple[int, int]):
    renderer = bpy.context.scene.render

    renderer.render.use_compositing = True
    bpy.context.scene.use_nodes = True

    # Configure rendering settings
    renderer.use_file_extension = False
    renderer.filepath = str(output_path)
    renderer.engine = "BLENDER_EEVEE"
    renderer.resolution_x = resolution[0]
    renderer.resolution_y = resolution[1]

    # Render animation as video through ffmpeg (built-in)
    renderer.image_settings.file_format = "FFMPEG"
    renderer.ffmpeg.format = "MPEG4"
    renderer.ffmpeg.codec = "H264"

    # Start rendering
    bpy.ops.renderer.render(animation=True, write_still=False)

My code for setting up the composite nodes (manually confirmed to work in Blender):

def add_watermark(texture_image_file: Path):
    bpy.context.scene.use_nodes = True

    node_tree = bpy.context.scene.node_tree
    composite_node = node_tree.nodes[0]
    render_scene_node = node_tree.nodes[1]

    # Load WK logo as input
    logo_input_node = node_tree.nodes.new(type="CompositorNodeImage")
    webknossos_logo_image = bpy.data.images.load(str(texture_image_file), check_existing=True)
    logo_input_node.image = webknossos_logo_image

    # Scale WK logo
    logo_scale_node = node_tree.nodes.new(type="CompositorNodeScale")
    logo_scale_node.inputs["X"].default_value = 0.3
    logo_scale_node.inputs["Y"].default_value = 0.3

    # Translate WK logo to lower right corner of the scene
    logo_translate_node = node_tree.nodes.new(type="CompositorNodeTranslate")
    logo_translate_node.inputs["X"].default_value = 600
    logo_translate_node.inputs["Y"].default_value = -450

    # Use an AlphaOver node to combine the rendered scene with watermark image
    alpha_over_node = node_tree.nodes.new(type="CompositorNodeAlphaOver")

    # Add a View node for debugging within Blender
    viewer_node = node_tree.nodes.new(type="CompositorNodeViewer")

    # Connect all nodes
    links = node_tree.links
    links.new(logo_input_node.outputs["Image"], logo_scale_node.inputs["Image"])
    links.new(logo_scale_node.outputs["Image"], logo_translate_node.inputs["Image"])
    links.new(render_scene_node.outputs["Image"], alpha_over_node.inputs["Image"])
    links.new(logo_translate_node.outputs["Image"], alpha_over_node.inputs[2])
    links.new(alpha_over_node.outputs["Image"], composite_node.inputs["Image"])
    links.new(alpha_over_node.outputs["Image"], viewer_node.inputs["Image"])

Composite nodes setup as produced by the Python script for reference:

Composite nodes setup as produced by the Python script for reference

$\endgroup$

1 Answer 1

0
$\begingroup$

After lots of trial and error I realized that my Python code was indeed correct and produced a valid video file including all the composition effects. It turns out that my Blendre composition pipeline was faulty after all. A Translate node would move the overlaid image out of the frame / outside the rendered area if the scene resolution was too small. For regular FullHD everything was fine, but it did not scale for smaller resolutions.

The fix was to first scale the watermark image to the render size using another Scale node with the argument "Render Size" and to do "relative" offsets in the Translate node as shown below.

enter image description here

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .