feat: BLENDER_CINEMATIC workflow graph node (M1)
Add StepName.BLENDER_CINEMATIC and full graph runtime support so cinematic output types can be promoted from legacy_only to graph/shadow rollout mode. - process_steps.py: add BLENDER_CINEMATIC = "blender_cinematic" enum value - workflow_executor.py: map to render_cinematic_task in STEP_TASK_MAP - workflow_node_registry.py: node definition with render/scene/camera fields (no animation params — cinematic is fixed at 250 frames @ 25fps) - workflow_graph_runtime.py: _ORDER_LINE_RENDER_STEPS, _CINEMATIC_TASK_KEYS, shadow queue routing, predict_render_output_artifact (mp4), _build_task_kwargs, _artifact_kind_override_for_step - tasks.py: _normalize_cinematic_params + render_cinematic_task Celery task (calls render_cinematic_to_file, publishes as turntable asset type since mp4) No DB migration needed: admins can now manually set cinematic output types to graph rollout mode via the admin panel and assign a workflow definition. docs: learnings erfasst — BLENDER_CINEMATIC workflow graph node M1 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,7 @@ class WorkflowGraphState:
|
||||
_ORDER_LINE_RENDER_STEPS = {
|
||||
StepName.BLENDER_STILL,
|
||||
StepName.BLENDER_TURNTABLE,
|
||||
StepName.BLENDER_CINEMATIC,
|
||||
StepName.EXPORT_BLEND,
|
||||
StepName.OUTPUT_SAVE,
|
||||
StepName.NOTIFY,
|
||||
@@ -133,6 +134,33 @@ _TURNTABLE_TASK_KEYS = {
|
||||
"duration_s",
|
||||
}
|
||||
|
||||
_CINEMATIC_TASK_KEYS = {
|
||||
"width",
|
||||
"height",
|
||||
"engine",
|
||||
"render_engine",
|
||||
"samples",
|
||||
"smooth_angle",
|
||||
"cycles_device",
|
||||
"transparent_bg",
|
||||
"part_colors",
|
||||
"template_path",
|
||||
"target_collection",
|
||||
"material_library_path",
|
||||
"material_map",
|
||||
"part_names_ordered",
|
||||
"lighting_only",
|
||||
"shadow_catcher",
|
||||
"rotation_x",
|
||||
"rotation_y",
|
||||
"rotation_z",
|
||||
"usd_path",
|
||||
"focal_length_mm",
|
||||
"sensor_width_mm",
|
||||
"material_override",
|
||||
"template_inputs",
|
||||
}
|
||||
|
||||
_THUMBNAIL_TASK_KEYS = {
|
||||
"renderer",
|
||||
"render_engine",
|
||||
@@ -232,6 +260,7 @@ def _resolve_shadow_render_queue(
|
||||
if node.step not in {
|
||||
StepName.BLENDER_STILL,
|
||||
StepName.BLENDER_TURNTABLE,
|
||||
StepName.BLENDER_CINEMATIC,
|
||||
StepName.EXPORT_BLEND,
|
||||
}:
|
||||
return None
|
||||
@@ -810,6 +839,27 @@ def _predict_task_output_metadata(
|
||||
"graph_notify_node_ids": list(task_kwargs.get("graph_notify_node_ids") or []),
|
||||
}
|
||||
|
||||
if node.step == StepName.BLENDER_CINEMATIC:
|
||||
output_name_suffix = task_kwargs.get("output_name_suffix")
|
||||
cinematic_filename = f"line_{order_line_id}_cinematic.mp4"
|
||||
if output_name_suffix:
|
||||
cinematic_filename = f"line_{order_line_id}_cinematic_{output_name_suffix}.mp4"
|
||||
predicted_output_path = str(
|
||||
build_order_line_step_render_path(step_path, order_line_id, cinematic_filename)
|
||||
)
|
||||
return {
|
||||
"artifact_role": "cinematic_output",
|
||||
"predicted_output_path": predicted_output_path,
|
||||
"predicted_asset_type": "turntable",
|
||||
"publish_asset_enabled": bool(task_kwargs.get("publish_asset_enabled", True)),
|
||||
"graph_authoritative_output_enabled": bool(
|
||||
task_kwargs.get("graph_authoritative_output_enabled", False)
|
||||
),
|
||||
"graph_output_node_ids": list(task_kwargs.get("graph_output_node_ids") or []),
|
||||
"notify_handoff_enabled": bool(task_kwargs.get("emit_legacy_notifications", False)),
|
||||
"graph_notify_node_ids": list(task_kwargs.get("graph_notify_node_ids") or []),
|
||||
}
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
@@ -963,6 +1013,16 @@ def _build_task_kwargs(
|
||||
"turntable.mp4",
|
||||
).parent
|
||||
)
|
||||
elif node.step == StepName.BLENDER_CINEMATIC:
|
||||
task_kwargs = _filter_graph_render_overrides(StepName.BLENDER_CINEMATIC, task_kwargs)
|
||||
task_kwargs = {
|
||||
key: value
|
||||
for key, value in {
|
||||
**render_defaults,
|
||||
**task_kwargs,
|
||||
}.items()
|
||||
if key in _CINEMATIC_TASK_KEYS
|
||||
}
|
||||
elif node.step == StepName.THUMBNAIL_SAVE:
|
||||
thumbnail_request = _resolve_thumbnail_request(workflow_context, state, node.id) or {}
|
||||
task_kwargs = {
|
||||
@@ -980,6 +1040,7 @@ def _build_task_kwargs(
|
||||
StepName.BLENDER_STILL,
|
||||
StepName.EXPORT_BLEND,
|
||||
StepName.BLENDER_TURNTABLE,
|
||||
StepName.BLENDER_CINEMATIC,
|
||||
}:
|
||||
connected_output_node_ids = _connected_node_ids_by_step(
|
||||
workflow_context,
|
||||
@@ -1015,6 +1076,8 @@ def _build_task_kwargs(
|
||||
def _artifact_kind_override_for_step(step: StepName) -> str | None:
|
||||
if step == StepName.BLENDER_TURNTABLE:
|
||||
return "turntable_video"
|
||||
if step == StepName.BLENDER_CINEMATIC:
|
||||
return "cinematic_video"
|
||||
if step == StepName.BLENDER_STILL:
|
||||
return "still_image"
|
||||
if step == StepName.EXPORT_BLEND:
|
||||
|
||||
Reference in New Issue
Block a user