From 1f2f9ccc8eddc2421a2e917601ac8c30f0d4b5b5 Mon Sep 17 00:00:00 2001 From: cheriech <58997764+Cherie-Chen@users.noreply.github.com> Date: Mon, 23 Feb 2026 19:31:21 +0000 Subject: [PATCH 1/3] chore: convert sample job templates to use task chunking for After Effects, Blender, Houdini and KeyShot Signed-off-by: cheriech <58997764+Cherie-Chen@users.noreply.github.com> --- job_bundles/afterfx_render_one_task/README.md | 70 ++++++++---- .../afterfx_render_one_task/template.yaml | 82 ++++++++------ job_bundles/blender_render/README.md | 46 ++++++++ job_bundles/blender_render/template.yaml | 101 ++++++++++++------ job_bundles/houdini_husk_usd_render/README.md | 28 ++++- .../houdini_husk_usd_render/template.yaml | 79 ++++++++------ job_bundles/keyshot_standalone/README.md | 79 +++++++++----- job_bundles/keyshot_standalone/template.yaml | 83 ++++++++++---- 8 files changed, 403 insertions(+), 165 deletions(-) create mode 100644 job_bundles/blender_render/README.md diff --git a/job_bundles/afterfx_render_one_task/README.md b/job_bundles/afterfx_render_one_task/README.md index de004b20..8ef2b0b6 100644 --- a/job_bundles/afterfx_render_one_task/README.md +++ b/job_bundles/afterfx_render_one_task/README.md @@ -1,21 +1,49 @@ -# After Effects Render - one task - -## Use case for this job - -This is an After Effects job bundle that allows the user -to submit a job that uses aerender to render a frame range -as a single task. This means the entire workload will render -on one worker as one command. - -It accepts the following job parameters that modify the render: -* Project file -* Comp name -* Input directory -* Output directory -* Start frame -* End frame - -This job bundle expects a user to specify an input directory that -contains all the file references that are required to render. -Generally, the project file should be within this directory to -ensure relative paths are preserved. +# After Effects Render with Contiguous Chunks + +This job bundle renders After Effects compositions using aerender with the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension for efficient parallel rendering. + +## Features + +- **Task Chunking**: Uses `CHUNK[INT]` with contiguous frame ranges for parallel rendering across multiple workers +- **Adaptive Chunking**: Optional target runtime allows the scheduler to adjust chunk sizes dynamically + +## Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| Project file | After Effects project file (.aep, .aepx) | - | +| Comp name | Composition to render | - | +| Input directory | Directory containing input files | - | +| Output directory | Render output directory | - | +| Frames | Frame range (e.g., `0-100`) | `0-50` | +| Chunk Size | Number of frames per chunk | `10` | +| Target Runtime | Target seconds per chunk (0 to disable) | `180` | + +## Task Chunking + +This template uses the `TASK_CHUNKING` extension: + +```yaml +extensions: + - TASK_CHUNKING + +steps: +- name: RenderComp + parameterSpace: + taskParameterDefinitions: + - name: Frame + type: CHUNK[INT] + range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + rangeConstraint: CONTIGUOUS +``` + +Each chunk expands to a contiguous range like `"0-9"` or `"10-19"`, which maps directly to aerender's `-s` (start) and `-e` (end) arguments. + +Reference: [After Effects Automated Rendering](https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html) + +## Usage + +This job bundle expects a user to specify an input directory that contains all the file references required to render. Generally, the project file should be within this directory to ensure relative paths are preserved. diff --git a/job_bundles/afterfx_render_one_task/template.yaml b/job_bundles/afterfx_render_one_task/template.yaml index 7c517a4a..e8ae3674 100644 --- a/job_bundles/afterfx_render_one_task/template.yaml +++ b/job_bundles/afterfx_render_one_task/template.yaml @@ -1,8 +1,10 @@ specificationVersion: jobtemplate-2023-09 -name: After Effects Render - one task +extensions: + - TASK_CHUNKING +name: After Effects Render with Contiguous Chunks description: > - A simple job bundle that allows a user to select - a project file and enter a comp to render with aerender. + A job bundle that renders an After Effects composition using aerender + with task chunking for efficient parallel rendering. parameterDefinitions: @@ -55,32 +57,39 @@ parameterDefinitions: control: CHOOSE_DIRECTORY label: Output directory groupLabel: Inputs/outputs - description: The render output directory + description: The render output directory. # Frame range -- name: StartFrame +- name: Frames + type: STRING + userInterface: + control: LINE_EDIT + label: Frames + groupLabel: Frame range + default: "0-50" + description: The frame range to render (e.g., 0-100). +- name: ChunkSize type: INT userInterface: control: SPIN_BOX - label: Start Frame + label: Chunk Size groupLabel: Frame range - default: 0 - description: The first frame to render. -- name: EndFrame + default: 10 + minValue: 1 + description: Number of frames per chunk. +- name: TargetRuntime type: INT userInterface: control: SPIN_BOX - label: End Frame + label: Target Runtime (Seconds) groupLabel: Frame range - default: 50 - description: The last frame to render. + default: 300 + description: Target runtime per chunk (0 to disable adaptive chunking). # Software Environment - name: CondaPackages type: STRING userInterface: - # This parameter is for a queue environment, not used directly in the job, - # so leave the GUI for the queue environment to display. control: HIDDEN default: aftereffects description: > @@ -89,37 +98,48 @@ parameterDefinitions: steps: - name: RenderComp + parameterSpace: + taskParameterDefinitions: + - name: Frame + type: CHUNK[INT] + range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + # After Effects aerender uses -s (start) and -e (end) for frame ranges + # https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html + rangeConstraint: CONTIGUOUS script: actions: onRun: command: python args: - "{{Task.File.Run}}" - - "{{Param.OutputDirectory}}" - - "aerender" - - "-project" - - "{{Param.ProjectFile}}" - - "-comp" - - "{{Param.CompName}}" - - "-output" - - "{{Param.OutputDirectory}}/output_[####].png" - - "-s" - - "{{Param.StartFrame}}" - - "-e" - - "{{Param.EndFrame}}" embeddedFiles: - name: Run type: TEXT data: | import os - import sys import subprocess - # Ensure the output directory exists - os.makedirs(sys.argv[1], exist_ok=True) + # Parse contiguous chunk range (e.g., "0-50" or "10-10") + chunk = "{{Task.Param.Frame}}" + start_frame, end_frame = chunk.split("-") + + # Ensure the output directory exists (use raw string to avoid escape sequences) + os.makedirs(r"{{Param.OutputDirectory}}", exist_ok=True) - # Run the After Effects subprocess - subprocess.run(sys.argv[2:], check=True) + # Run aerender with the chunk's frame range + cmd = [ + "aerender", + "-project", r"{{Param.ProjectFile}}", + "-comp", "{{Param.CompName}}", + "-output", r"{{Param.OutputDirectory}}/output_[####].png", + "-s", start_frame, + "-e", end_frame + ] + print(f"Rendering frames {start_frame} to {end_frame}") + subprocess.run(cmd, check=True) hostRequirements: attributes: - name: attr.worker.os.family diff --git a/job_bundles/blender_render/README.md b/job_bundles/blender_render/README.md new file mode 100644 index 00000000..ad9f517c --- /dev/null +++ b/job_bundles/blender_render/README.md @@ -0,0 +1,46 @@ +# Blender Render + +This job bundle renders Blender scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with non-contiguous frame support for flexible parallel rendering. + +## Features + +- **Non-Contiguous Chunking**: Uses `CHUNK[INT]` with `rangeConstraint: NONCONTIGUOUS` for arbitrary frame sets +- **Adaptive Chunking**: Optional target runtime allows the scheduler to adjust chunk sizes dynamically +- **Flexible Frame Ranges**: Supports ranges, steps, and individual frames (e.g., `1-10,15,20-100:2`) + +## Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| Blender Scene File | Blender scene file (.blend) to render | - | +| Frames | Frame range (e.g., `1-10,15,20-100:2`) | `1-10,15,20-100:2` | +| Chunk Size | Number of frames per chunk | `5` | +| Target Runtime | Target seconds per chunk (0 to disable) | `180` | +| Output Directory | Render output directory | `./output` | +| Output File Pattern | Output filename pattern | `output_####` | +| Output File Format | Image format | `JPEG` | + +## Task Chunking + +This template uses the `TASK_CHUNKING` extension with `rangeConstraint: NONCONTIGUOUS`: + +```yaml +extensions: + - TASK_CHUNKING + +steps: +- name: RenderBlender + parameterSpace: + taskParameterDefinitions: + - name: Frame + type: CHUNK[INT] + range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + rangeConstraint: NONCONTIGUOUS +``` + +Each chunk expands to an arbitrary frame set like `"1-3,5,7-10:2"`. A Python script converts this to Blender's `--render-frame` format (e.g., `1,3,5,9..11,15`). + +Reference: [Blender Command Line Arguments](https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html) diff --git a/job_bundles/blender_render/template.yaml b/job_bundles/blender_render/template.yaml index 5e8dc1cb..a0d8f878 100644 --- a/job_bundles/blender_render/template.yaml +++ b/job_bundles/blender_render/template.yaml @@ -1,9 +1,9 @@ specificationVersion: 'jobtemplate-2023-09' -name: Blender Render +extensions: + - TASK_CHUNKING +name: Blender Render with Non-Contiguous Chunks parameterDefinitions: - -# Render Parameters - name: BlenderSceneFile type: PATH objectType: FILE @@ -11,22 +11,34 @@ parameterDefinitions: userInterface: control: CHOOSE_INPUT_FILE label: Blender Scene File - groupLabel: Render Parameters fileFilters: - label: Blender Scene Files patterns: ["*.blend"] - label: All Files patterns: ["*"] - description: > - Choose the Blender scene file you want to render. Use the 'Job Attachments' tab - to add textures and other files that the job needs. + description: Choose the Blender scene file you want to render. - name: Frames type: STRING userInterface: control: LINE_EDIT label: Frames - groupLabel: Render Parameters - default: 1-10 + default: "1-10,15,20-100:2" + description: "The frames to render. Supports ranges and steps, e.g. 1-10,15,20-100:2" +- name: ChunkSize + type: INT + userInterface: + control: SPIN_BOX + label: Chunk Size + default: 5 + minValue: 1 + description: Number of frames per chunk. +- name: TargetRuntime + type: INT + userInterface: + control: SPIN_BOX + label: Target Runtime (Seconds) + default: 600 + description: Enter the target runtime (0 to disable adaptive chunking). - name: OutputDir type: PATH objectType: DIRECTORY @@ -34,7 +46,6 @@ parameterDefinitions: userInterface: control: CHOOSE_DIRECTORY label: Output Directory - groupLabel: Render Parameters default: "./output" description: Choose the render output directory. - name: OutputPattern @@ -42,7 +53,6 @@ parameterDefinitions: userInterface: control: LINE_EDIT label: Output File Pattern - groupLabel: Render Parameters default: "output_####" description: Enter the output filename pattern (without extension). - name: Format @@ -50,56 +60,83 @@ parameterDefinitions: userInterface: control: DROPDOWN_LIST label: Output File Format - groupLabel: Render Parameters description: Choose the file format to render as. default: JPEG allowedValues: [TGA, RAWTGA, JPEG, IRIS, IRIZ, PNG, HDR, TIFF, OPEN_EXR, OPEN_EXR_MULTILAYER, CINEON, DPX, DDS, JP2, WEBP] - -# Software Environment - name: CondaPackages type: STRING userInterface: - # This parameter is for a queue environment, not used directly in the job, - # so leave the GUI for the queue environment to display. - control: HIDDEN - default: blender - description: > - If you have a Queue Environment that creates a Conda environment from a parameter called CondaPackages, this - will set the default packages to use for the job. -- name: RezPackages - type: STRING - userInterface: - # This parameter is for a queue environment, not used directly in the job, - # so leave the GUI for the queue environment to display. control: HIDDEN default: blender - description: > - If you have a Queue Environment that creates a Rez environment from a parameter called RezPackages, this will - tell it to install blender. + description: Conda packages to install. Requires a Queue Environment to create the Conda Environment. steps: - name: RenderBlender parameterSpace: taskParameterDefinitions: - name: Frame - type: INT + type: CHUNK[INT] range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + rangeConstraint: NONCONTIGUOUS script: actions: onRun: command: bash args: ['{{Task.File.Run}}'] embeddedFiles: + - name: Frames2Blender + type: TEXT + filename: frames_2_blender.py + data: | + """ + Converts an Open Job Description range expression into a --render-frame option for the Blender CLI. + + $ FRAMES=$(python frames_2_blender.py "1-5:2,9-11,15") + $ echo $FRAMES + 1,3,5,9..11,15 + + * https://github.com/OpenJobDescription/openjd-specifications/wiki/2023-09-Template-Schemas#34111-intrangeexpr + * https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html + """ + + import sys, re + + def range_expr_to_blender(range_expr): + # Regex that matches "", "-", or "-:" + int_pat = r"\s*(-?[0-9]+)\s*" + part_re = re.compile(f"^{int_pat}(?:-{int_pat}(?::{int_pat})?)?$") + blender_parts = [] + for part in range_expr.split(","): + if m := part_re.match(part): + start, end, step = m.groups() + if step is not None: + # Linear sequence "3-7:2" means the values [3, 5, 7]. + blender_parts.extend(range(int(start), int(end) + (int(step)//abs(int(step))), int(step))) + elif end is not None: + # Interval "3-6" means the values [3, 4, 5, 6]. + blender_parts.append(f"{start}..{end}") + else: + # Integer "3" means the values [3]. + blender_parts.append(start) + else: + raise ValueError(f"Invalid frame range expression: {range_expr}") + return ",".join(str(part) for part in blender_parts) + + print(range_expr_to_blender(sys.argv[1])) - name: Run type: TEXT data: | - # Configure the task to fail if any individual command fails. set -xeuo pipefail mkdir -p '{{Param.OutputDir}}' + FRAMES="$(python '{{Task.File.Frames2Blender}}' '{{Task.Param.Frame}}')" + blender --background '{{Param.BlenderSceneFile}}' \ --render-output '{{Param.OutputDir}}/{{Param.OutputPattern}}' \ --render-format {{Param.Format}} \ --use-extension 1 \ - --render-frame {{Task.Param.Frame}} + --render-frame "$FRAMES" diff --git a/job_bundles/houdini_husk_usd_render/README.md b/job_bundles/houdini_husk_usd_render/README.md index 97c0548f..b11f29b8 100644 --- a/job_bundles/houdini_husk_usd_render/README.md +++ b/job_bundles/houdini_husk_usd_render/README.md @@ -2,9 +2,33 @@ ## Background -Husk is a CLI application provided with SideFX Houdini that renders Universal Scene Description(USD) files. -By default Husk renders using the Houdini Karma renderer but Husk supports any Hydra-compatible USD render delegate. +Husk is a CLI application provided with SideFX Houdini that renders Universal Scene Description (USD) files. +By default Husk renders using the Houdini Karma renderer but Husk supports any Hydra-compatible USD render delegate. +## Task Chunking + +This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient parallel rendering. + +```yaml +extensions: + - TASK_CHUNKING + +steps: +- name: HuskRender + parameterSpace: + taskParameterDefinitions: + - name: Frame + type: CHUNK[INT] + range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + rangeConstraint: CONTIGUOUS|NONCONTIGUOUS +``` + +Each chunk expands to a contiguous range like `"1-5"` or `"6-10"`, which maps to Husk's `-f` (start frame) and `-n` (frame count) arguments. + +Reference: [Husk Documentation](https://www.sidefx.com/docs/houdini/ref/utils/husk.html) ## Job Summary diff --git a/job_bundles/houdini_husk_usd_render/template.yaml b/job_bundles/houdini_husk_usd_render/template.yaml index 103a32e6..c18eb0ec 100644 --- a/job_bundles/houdini_husk_usd_render/template.yaml +++ b/job_bundles/houdini_husk_usd_render/template.yaml @@ -1,8 +1,9 @@ specificationVersion: 'jobtemplate-2023-09' -name: Husk USD Render +extensions: + - TASK_CHUNKING +name: Husk USD Render with Contiguous Chunks parameterDefinitions: -# Render Parameters - name: USDSceneFile type: PATH default: "sample.usda" @@ -11,22 +12,34 @@ parameterDefinitions: userInterface: control: CHOOSE_INPUT_FILE label: USD Scene File - groupLabel: Render Parameters fileFilters: - label: USD Scene Files patterns: ["*.usd", "*.usdc", "*.usda", "*.usdz"] - label: All Files patterns: ["*"] - description: > - Choose the USD scene file you want to render. Use the 'Job Attachments' tab - to add textures and other files that the job needs. + description: Choose the USD scene file you want to render. - name: Frames type: STRING userInterface: control: LINE_EDIT label: Frames - groupLabel: Render Parameters - default: "1" + default: "1-100" + description: The frame range to render (e.g., 1-100). +- name: ChunkSize + type: INT + userInterface: + control: SPIN_BOX + label: Chunk Size + default: 5 + minValue: 1 + description: Number of frames per chunk. +- name: TargetRuntime + type: INT + userInterface: + control: SPIN_BOX + label: Target Runtime (Seconds) + default: 600 + description: Target runtime per chunk (0 to disable adaptive chunking). - name: OutputDir type: PATH default: output/ @@ -35,14 +48,12 @@ parameterDefinitions: userInterface: control: CHOOSE_DIRECTORY label: Output Directory - groupLabel: Render Parameters description: Choose the render output directory. - name: OutputPattern type: STRING userInterface: control: LINE_EDIT label: Output File Pattern - groupLabel: Render Parameters default: "output_$F4" # Husk Documentation: https://www.sidefx.com/docs/houdini/ref/utils/husk.html#:~:text=Current%20frame%20number%20with%20fixed%20number%20of description: Enter the output filename pattern (without extension). Please see the Husk documentation for formatting @@ -51,7 +62,6 @@ parameterDefinitions: userInterface: control: DROPDOWN_LIST label: Output File Format - groupLabel: Render Parameters description: Choose the file format for the output render. default: exr allowedValues: ["exr"] @@ -60,27 +70,22 @@ parameterDefinitions: userInterface: control: LINE_EDIT label: Resolution Width - groupLabel: Render Parameters + description: Enter the resolution width in pixels. The default is 1024. default: "1024" - description: > - Enter the resolution width in pixels. The default is 1024. - name: ResolutionY type: STRING userInterface: control: LINE_EDIT label: Resolution Height - groupLabel: Render Parameters default: "768" - description: > - Enter the resolution height in pixels. The default is 768. + description: Enter the resolution height in pixels. The default is 768. - name: Renderer type: STRING userInterface: control: DROPDOWN_LIST label: Husk Render Delegate - groupLabel: Render Parameters - description: Choose the renderer you wish to use. BRAY_HdKarma uses the CPU while BRAY_HdKarmaXPU requires a GPU fleet. If you select BRAY_HdKarmaXPU your queue must be associated with a GPU fleet. default: BRAY_HdKarma + description: Choose the renderer you wish to use. BRAY_HdKarma uses the CPU while BRAY_HdKarmaXPU requires a GPU fleet. If you select BRAY_HdKarmaXPU your queue must be associated with a GPU fleet. allowedValues: [BRAY_HdKarma, BRAY_HdKarmaXPU, HdVRayRendererPlugin, HdRedshiftRendererPlugin] - name: CondaPackages type: STRING @@ -89,15 +94,20 @@ parameterDefinitions: # so leave the GUI for the queue environment to display. control: HIDDEN default: "houdini=20.5" - description: > - This parameter provides a default value Conda environment, specifying Houdini 20.5 to provide the husk executable. + description: This parameter provides a default value Conda environment, specifying Houdini 20.5 to provide the husk executable. steps: - name: HuskRender parameterSpace: taskParameterDefinitions: - name: Frame - type: INT + type: CHUNK[INT] range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + # Husk uses -f (start frame) and -n (frame count) for contiguous ranges + # https://www.sidefx.com/docs/houdini/ref/utils/husk.html + rangeConstraint: CONTIGUOUS script: actions: onRun: @@ -109,19 +119,24 @@ steps: data: | set -xeuo pipefail mkdir -p '{{Param.OutputDir}}' - # The 'husk' executable exists on the path when using a Deadline Cloud-provided Houdini conda package + + # Parse contiguous chunk range (e.g., "1-10" or "5-5") + START_FRAME="$(echo '{{Task.Param.Frame}}' | cut -d- -f1)" + END_FRAME="$(echo '{{Task.Param.Frame}}' | cut -d- -f2)" + FRAME_COUNT=$((END_FRAME - START_FRAME + 1)) + + echo "Rendering frames $START_FRAME to $END_FRAME ($FRAME_COUNT frames)" + + # Husk uses -f for start frame and -n for frame count + # https://www.sidefx.com/docs/houdini/ref/utils/husk.html husk -r {{Param.ResolutionX}} {{Param.ResolutionY}} \ - -R {{Param.Renderer}} \ - -f {{Task.Param.Frame}} \ - '{{Param.USDSceneFile}}' \ - -o '{{Param.OutputDir}}/{{Param.OutputPattern}}.{{Param.Format}}' + -R {{Param.Renderer}} \ + -f "$START_FRAME" \ + -n "$FRAME_COUNT" \ + '{{Param.USDSceneFile}}' \ + -o '{{Param.OutputDir}}/{{Param.OutputPattern}}.{{Param.Format}}' hostRequirements: - # Add this requirement when rendering with the GPU to ensure the job is only scheduled on GPU-enabled fleets. - # amounts: - # - name: amount.worker.gpu - # min: 1 attributes: - # The Houdini package is currently only availabling on Linux in Deadline Cloud SMF - name: attr.worker.os.family anyOf: - linux diff --git a/job_bundles/keyshot_standalone/README.md b/job_bundles/keyshot_standalone/README.md index 2855f484..f8f97d22 100644 --- a/job_bundles/keyshot_standalone/README.md +++ b/job_bundles/keyshot_standalone/README.md @@ -1,35 +1,62 @@ -# KeyShot Standalone +# KeyShot Standalone with Non-Contiguous Chunks -## Use case for this job +This is a Windows KeyShot job bundle that renders scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension for efficient parallel rendering. -This is a Windows KeyShot job bundle that allows the user to render a scene with -each frame as a separate task. +## Task Chunking -The bundle accepts the following job parameters that modify the render: -* KeyShotFile -* Frames -* OutputName -* OutputDirectoryPath -* OutputFormat +This template uses `rangeConstraint: NONCONTIGUOUS` to support arbitrary frame sets: -The output file paths for the rendered frames will be constructed like the following: - `/..` +```yaml +extensions: + - TASK_CHUNKING -All other render settings are taken from what is set in the scene file itself. +steps: +- name: Render + parameterSpace: + taskParameterDefinitions: + - name: Frame + type: CHUNK[INT] + range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + rangeConstraint: NONCONTIGUOUS +``` -This job bundle expects **one** of the following: +Each chunk expands to an arbitrary frame set like `"1-3,5,7-10:2"`. The Python script parses this and renders each frame using `lux.setAnimationFrame()`. + +## Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| KeyShotFile | KeyShot scene file (.bip) | - | +| Frames | Frame range (e.g., `1-3,8,11-100:2`) | `1-3,8,11-100:2` | +| ChunkSize | Number of frames per chunk | `5` | +| TargetRuntime | Target seconds per chunk (0 to disable) | `180` | +| OutputName | Output file name prefix | `KeyShotOutput` | +| OutputDirectoryPath | Render output directory | - | +| OutputFormat | Output format (PNG, JPEG, EXR, etc.) | `PNG` | + +## Output -* The user to specify an input directory that contains any file references that -are required to render that will be uploaded using job attachments. - * With KeyShot the easiest way to get the input directory is to save - the entire scene and all external files out as a KeyShot package(ksp). - Saving a scene to a ksp bundles all of the external files referenced - into a single directory and changes the paths to be relative to the new - saved scene. You can then open the ksp up and submit the entire unpacked - directory as the input directory and use the modified scene within as the - input KeyShot file. +Output file paths are constructed as: +``` +/.. +``` + +All other render settings are taken from the scene file. + +## Input Files + +This job bundle expects **one** of the following: -**OR** +1. **Job Attachments**: Specify an input directory containing all referenced files. + With KeyShot the easiest way to get the input directory is to save + the entire scene and all external files out as a KeyShot package(ksp). + Saving a scene to a ksp bundles all of the external files referenced + into a single directory and changes the paths to be relative to the new + saved scene. You can then open the ksp up and submit the entire unpacked + directory as the input directory and use the modified scene within as the + input KeyShot file. -* All files referenced in the scene to be available through network storage or -some other method that isn't job attachments for the workers. +2. **Network Storage**: All referenced files available via network storage or other method accessible to workers. diff --git a/job_bundles/keyshot_standalone/template.yaml b/job_bundles/keyshot_standalone/template.yaml index e5a5ef2c..e75cf68b 100644 --- a/job_bundles/keyshot_standalone/template.yaml +++ b/job_bundles/keyshot_standalone/template.yaml @@ -1,9 +1,10 @@ specificationVersion: 'jobtemplate-2023-09' -name: KeyShot Standalone +extensions: + - TASK_CHUNKING +name: KeyShot Standalone with Non-Contiguous Chunks description: | - A simple job bundle that allows the user to select a KeyShot scene file, the - frames to render, the output file path and render via the keyshot_headless - command on Windows. + A job bundle that renders KeyShot scenes with task chunking support. + Uses keyshot_headless command on Windows with non-contiguous frame ranges. parameterDefinitions: @@ -16,7 +17,6 @@ parameterDefinitions: userInterface: control: CHOOSE_INPUT_FILE label: KeyShot Scene File - groupLabel: KeyShot Scene Settings fileFilters: - label: KeyShot Scene Files patterns: @@ -25,13 +25,28 @@ parameterDefinitions: patterns: - '*' - name: Frames - description: The frames to render. E.g. 1-3,8,11-15 + description: The frames to render. E.g. 1-3,8,11-100:2 type: STRING userInterface: control: LINE_EDIT label: Frames - groupLabel: KeyShot Scene Settings + default: "1-3,8,11-100:2" minLength: 1 +- name: ChunkSize + description: Number of frames per chunk. + type: INT + userInterface: + control: SPIN_BOX + label: Chunk Size + default: 5 + minValue: 1 +- name: TargetRuntime + description: Target runtime per chunk in seconds (0 to disable adaptive chunking). + type: INT + userInterface: + control: SPIN_BOX + label: Target Runtime (Seconds) + default: 300 # KeyShot Output Settings - name: OutputName @@ -40,7 +55,6 @@ parameterDefinitions: userInterface: control: LINE_EDIT label: Output File Name - groupLabel: KeyShot Output Settings default: KeyShotOutput - name: OutputDirectoryPath description: The render output directory @@ -50,7 +64,6 @@ parameterDefinitions: userInterface: control: CHOOSE_DIRECTORY label: Output Directory Path - groupLabel: KeyShot Output Settings - name: OutputFormat description: The render output format type: STRING @@ -69,27 +82,27 @@ parameterDefinitions: userInterface: control: DROPDOWN_LIST label: Output Format - groupLabel: KeyShot Output Settings # Software Environment - name: CondaPackages type: STRING userInterface: - # This parameter is for a queue environment, not used directly in the job, - # so leave the GUI for the queue environment to display. control: HIDDEN default: keyshot - description: > - If you have a Queue Environment that creates a Conda environment from a parameter called CondaPackages, this - will set the default packages to use for the job. + description: Conda packages to install. Requires a Queue Environment to create the Conda Environment. steps: - name: Render parameterSpace: taskParameterDefinitions: - name: Frame - type: INT + type: CHUNK[INT] range: "{{Param.Frames}}" + chunks: + defaultTaskCount: "{{Param.ChunkSize}}" + targetRuntimeSeconds: "{{Param.TargetRuntime}}" + # KeyShot renders frames via Python script, supports any frame list + rangeConstraint: NONCONTIGUOUS script: actions: onRun: @@ -106,6 +119,28 @@ steps: filename: KeyShotScript.py type: TEXT data: | + import re + + def parse_frame_range(range_expr): + """Parse OpenJD range expression into list of frames.""" + int_pat = r"\s*(-?[0-9]+)\s*" + part_re = re.compile(f"^{int_pat}(?:-{int_pat}(?::{int_pat})?)?$") + frames = [] + for part in range_expr.split(","): + m = part_re.match(part) + if m: + start, end, step = m.groups() + if step is not None: + step = int(step) + frames.extend(range(int(start), int(end) + (step // abs(step)), step)) + elif end is not None: + frames.extend(range(int(start), int(end) + 1)) + else: + frames.append(int(start)) + else: + raise ValueError(f"Invalid frame range: {range_expr}") + return frames + match "{{Param.OutputFormat}}": case "JPEG": extension = ".jpg" @@ -120,12 +155,18 @@ steps: opts = lux.getRenderOptions() opts.setAddToQueue(False) - lux.setAnimationFrame(int("{{Task.Param.Frame}}")) - output_path = os.path.join(r"{{Param.OutputDirectoryPath}}", "{{Param.OutputName}}.{{Task.Param.Frame}}" + extension) output_format_code = lux.RENDER_OUTPUT_{{Param.OutputFormat}} - print(f"Output Path: {output_path}") - print(f"Output Format: {output_format_code}") - lux.renderImage(path=output_path, opts=opts, format=output_format_code) + + # Parse non-contiguous chunk and render each frame + frames = parse_frame_range("{{Task.Param.Frame}}") + print(f"Rendering {len(frames)} frames: {frames}") + + for frame in frames: + lux.setAnimationFrame(frame) + output_path = os.path.join(r"{{Param.OutputDirectoryPath}}", f"{{Param.OutputName}}.{frame}" + extension) + print(f"Rendering frame {frame} to {output_path}") + lux.renderImage(path=output_path, opts=opts, format=output_format_code) + print("Finished Rendering") hostRequirements: attributes: From b1624d3f787444095c1a70931e74422a45a6bd81 Mon Sep 17 00:00:00 2001 From: cheriech <58997764+Cherie-Chen@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:17:51 +0000 Subject: [PATCH 2/3] Address feedbacks Signed-off-by: cheriech <58997764+Cherie-Chen@users.noreply.github.com> --- job_bundles/afterfx_render_one_task/README.md | 2 +- job_bundles/afterfx_render_one_task/template.yaml | 2 +- job_bundles/blender_render/README.md | 3 +-- job_bundles/keyshot_standalone/README.md | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/job_bundles/afterfx_render_one_task/README.md b/job_bundles/afterfx_render_one_task/README.md index 8ef2b0b6..be55f774 100644 --- a/job_bundles/afterfx_render_one_task/README.md +++ b/job_bundles/afterfx_render_one_task/README.md @@ -17,7 +17,7 @@ This job bundle renders After Effects compositions using aerender with the [Task | Output directory | Render output directory | - | | Frames | Frame range (e.g., `0-100`) | `0-50` | | Chunk Size | Number of frames per chunk | `10` | -| Target Runtime | Target seconds per chunk (0 to disable) | `180` | +| Target Runtime | Target seconds per chunk (0 to disable) | `300` | ## Task Chunking diff --git a/job_bundles/afterfx_render_one_task/template.yaml b/job_bundles/afterfx_render_one_task/template.yaml index e8ae3674..c3d40946 100644 --- a/job_bundles/afterfx_render_one_task/template.yaml +++ b/job_bundles/afterfx_render_one_task/template.yaml @@ -67,7 +67,7 @@ parameterDefinitions: label: Frames groupLabel: Frame range default: "0-50" - description: The frame range to render (e.g., 0-100). + description: The frame range to render (e.g., 0-50). - name: ChunkSize type: INT userInterface: diff --git a/job_bundles/blender_render/README.md b/job_bundles/blender_render/README.md index ad9f517c..2fe19e7a 100644 --- a/job_bundles/blender_render/README.md +++ b/job_bundles/blender_render/README.md @@ -6,7 +6,6 @@ This job bundle renders Blender scenes using the [Task Chunking](https://github. - **Non-Contiguous Chunking**: Uses `CHUNK[INT]` with `rangeConstraint: NONCONTIGUOUS` for arbitrary frame sets - **Adaptive Chunking**: Optional target runtime allows the scheduler to adjust chunk sizes dynamically -- **Flexible Frame Ranges**: Supports ranges, steps, and individual frames (e.g., `1-10,15,20-100:2`) ## Parameters @@ -15,7 +14,7 @@ This job bundle renders Blender scenes using the [Task Chunking](https://github. | Blender Scene File | Blender scene file (.blend) to render | - | | Frames | Frame range (e.g., `1-10,15,20-100:2`) | `1-10,15,20-100:2` | | Chunk Size | Number of frames per chunk | `5` | -| Target Runtime | Target seconds per chunk (0 to disable) | `180` | +| Target Runtime | Target seconds per chunk (0 to disable) | `600` | | Output Directory | Render output directory | `./output` | | Output File Pattern | Output filename pattern | `output_####` | | Output File Format | Image format | `JPEG` | diff --git a/job_bundles/keyshot_standalone/README.md b/job_bundles/keyshot_standalone/README.md index f8f97d22..d808ca52 100644 --- a/job_bundles/keyshot_standalone/README.md +++ b/job_bundles/keyshot_standalone/README.md @@ -32,7 +32,7 @@ Each chunk expands to an arbitrary frame set like `"1-3,5,7-10:2"`. The Python s | KeyShotFile | KeyShot scene file (.bip) | - | | Frames | Frame range (e.g., `1-3,8,11-100:2`) | `1-3,8,11-100:2` | | ChunkSize | Number of frames per chunk | `5` | -| TargetRuntime | Target seconds per chunk (0 to disable) | `180` | +| TargetRuntime | Target seconds per chunk (0 to disable) | `300` | | OutputName | Output file name prefix | `KeyShotOutput` | | OutputDirectoryPath | Render output directory | - | | OutputFormat | Output format (PNG, JPEG, EXR, etc.) | `PNG` | From 9779a94911432ae0c10a303d47af107b0c28e615 Mon Sep 17 00:00:00 2001 From: cheriech <58997764+Cherie-Chen@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:02:18 +0000 Subject: [PATCH 3/3] update doc for task chunking Signed-off-by: cheriech <58997764+Cherie-Chen@users.noreply.github.com> --- job_bundles/afterfx_render_one_task/README.md | 7 +++---- job_bundles/afterfx_render_one_task/template.yaml | 2 +- job_bundles/blender_render/README.md | 7 +++---- job_bundles/houdini_husk_usd_render/README.md | 2 +- job_bundles/keyshot_standalone/README.md | 4 ++-- job_bundles/task_chunking/README.md | 4 +++- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/job_bundles/afterfx_render_one_task/README.md b/job_bundles/afterfx_render_one_task/README.md index be55f774..876c3210 100644 --- a/job_bundles/afterfx_render_one_task/README.md +++ b/job_bundles/afterfx_render_one_task/README.md @@ -1,11 +1,10 @@ # After Effects Render with Contiguous Chunks -This job bundle renders After Effects compositions using aerender with the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension for efficient parallel rendering. +This job bundle renders After Effects compositions using aerender with the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension. -## Features +## Task Chunking -- **Task Chunking**: Uses `CHUNK[INT]` with contiguous frame ranges for parallel rendering across multiple workers -- **Adaptive Chunking**: Optional target runtime allows the scheduler to adjust chunk sizes dynamically +This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient rendering. Chunking reduces scheduling overhead by grouping frames together, and the single `Frames` parameter accepts ranges (`1-50`), individual frames (`5,7,32`), stepped ranges (`1-100:2`), or combinations (`1-10,15,20-30:2`). ## Parameters diff --git a/job_bundles/afterfx_render_one_task/template.yaml b/job_bundles/afterfx_render_one_task/template.yaml index c3d40946..4cd3bca9 100644 --- a/job_bundles/afterfx_render_one_task/template.yaml +++ b/job_bundles/afterfx_render_one_task/template.yaml @@ -4,7 +4,7 @@ extensions: name: After Effects Render with Contiguous Chunks description: > A job bundle that renders an After Effects composition using aerender - with task chunking for efficient parallel rendering. + with task chunking. parameterDefinitions: diff --git a/job_bundles/blender_render/README.md b/job_bundles/blender_render/README.md index 2fe19e7a..2144f7d6 100644 --- a/job_bundles/blender_render/README.md +++ b/job_bundles/blender_render/README.md @@ -1,11 +1,10 @@ # Blender Render -This job bundle renders Blender scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with non-contiguous frame support for flexible parallel rendering. +This job bundle renders Blender scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension. -## Features +## Task Chunking -- **Non-Contiguous Chunking**: Uses `CHUNK[INT]` with `rangeConstraint: NONCONTIGUOUS` for arbitrary frame sets -- **Adaptive Chunking**: Optional target runtime allows the scheduler to adjust chunk sizes dynamically +This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient rendering. Chunking reduces scheduling overhead by grouping frames together, and the single `Frames` parameter accepts ranges (`1-50`), individual frames (`5,7,32`), stepped ranges (`1-100:2`), or combinations (`1-10,15,20-30:2`). ## Parameters diff --git a/job_bundles/houdini_husk_usd_render/README.md b/job_bundles/houdini_husk_usd_render/README.md index b11f29b8..397c5cc5 100644 --- a/job_bundles/houdini_husk_usd_render/README.md +++ b/job_bundles/houdini_husk_usd_render/README.md @@ -7,7 +7,7 @@ By default Husk renders using the Houdini Karma renderer but Husk supports any H ## Task Chunking -This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient parallel rendering. +This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient rendering. Chunking reduces scheduling overhead by grouping frames together, and the single `Frames` parameter accepts ranges (`1-50`), individual frames (`5,7,32`), stepped ranges (`1-100:2`), or combinations (`1-10,15,20-30:2`). ```yaml extensions: diff --git a/job_bundles/keyshot_standalone/README.md b/job_bundles/keyshot_standalone/README.md index d808ca52..1ef25501 100644 --- a/job_bundles/keyshot_standalone/README.md +++ b/job_bundles/keyshot_standalone/README.md @@ -1,10 +1,10 @@ # KeyShot Standalone with Non-Contiguous Chunks -This is a Windows KeyShot job bundle that renders scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension for efficient parallel rendering. +This is a Windows KeyShot job bundle that renders scenes using the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension. ## Task Chunking -This template uses `rangeConstraint: NONCONTIGUOUS` to support arbitrary frame sets: +This job bundle uses the [Task Chunking](https://github.com/OpenJobDescription/openjd-specifications/blob/mainline/rfcs/0001-task-chunking.md) extension with `rangeConstraint: CONTIGUOUS` for efficient rendering. Chunking reduces scheduling overhead by grouping frames together, and the single `Frames` parameter accepts ranges (`1-50`), individual frames (`5,7,32`), stepped ranges (`1-100:2`), or combinations (`1-10,15,20-30:2`). ```yaml extensions: diff --git a/job_bundles/task_chunking/README.md b/job_bundles/task_chunking/README.md index 8cfa92cc..9c4cf83e 100644 --- a/job_bundles/task_chunking/README.md +++ b/job_bundles/task_chunking/README.md @@ -4,7 +4,9 @@ These samples demonstrate the [Task Chunking](https://github.com/OpenJobDescript ## Why Use Task Chunking? -Render jobs often spend significant time loading applications and scene files before rendering each frame. Chunking amortizes this overhead by processing multiple frames or tasks per chunk, reducing total job runtime. +- **Reduced Scheduling Overhead**: Grouping short-running frames into chunks can reduce the overhead of scheduling each frame individually +- **Efficient Load Balancing**: Adaptive chunking mode automatically adjusts chunk sizes based on target runtime for optimal resource utilization +- **Flexible Frame Specification**: A single `Frames` parameter accepts ranges (`1-50`), individual frames (`5,7,32`), stepped ranges (`1-100:2`), or combinations (`1-10,15,20-30:2`). Users can specify frames in any format regardless of DCC limitations and let the AWS Deadline Cloud submitter, scheduler and adaptor render the specified frames ## Samples