# Plan: Cinematic Highlight Render ## Context Add a new render type: a 20-second cinematic product highlight video with procedural multi-shot camera animation. Unlike turntable (constant orbit), this has varying camera distances, focal lengths, elevations, and bezier-eased transitions between 4 segments. ## Tasks ### [ ] Task 1: Cinematic Blender script - **File**: `render-worker/scripts/cinematic_render.py` (new) - **What**: Blender Python script that: 1. Imports product geometry (GLB or USD, same as turntable_render.py) 2. Applies materials (same pipeline as turntable) 3. Computes bounding sphere from imported meshes 4. Creates a procedural 4-segment camera animation (480 frames @ 24fps = 20s): - Segment 1 (0-120): Establishing — slow 45° orbit + push-in, 50mm lens - Segment 2 (121-240): Detail sweep — low-angle close arc, 85mm lens, shallow DOF - Segment 3 (241-360): Crane up — rising from 30° to 60° elevation, 35mm wide - Segment 4 (361-480): Hero close — slow push-in, 65mm, ease-out to still 5. Each segment: camera position from spherical coords (azimuth, elevation, distance), bezier interpolation 6. Depth of field enabled (f-stop scales with product size) 7. Renders all frames as PNG to temp directory 8. FFmpeg assembles frames → MP4 (H.264, yuv420p, 24fps) CLI args (same pattern as turntable_render.py): ``` blender --background --python cinematic_render.py -- \ \ \ \ \ \ [--usd-path ...] [--focal-length ...] [--material-override ...] ``` - **Acceptance gate**: Script renders a 20s MP4 from a STEP file - **Dependencies**: None ### [ ] Task 2: Render service function - **File**: `backend/app/services/render_blender.py` - **What**: Add `render_cinematic_to_file()` function with same signature as `render_turntable_to_file()` but: - Calls `cinematic_render.py` instead of `turntable_render.py` - Fixed 24fps, 480 frames (20s) - Output format: mp4 - Passes all the same material/template/position args - **Acceptance gate**: Function callable, builds correct subprocess command - **Dependencies**: Task 1 ### [ ] Task 3: Pipeline integration - **File**: `backend/app/domains/pipeline/tasks/render_order_line.py` - **What**: In the render task, detect when output type has a cinematic flag. Add a check: - If `output_type.render_settings.get("cinematic")` is True → call `render_cinematic_to_file()` instead of `render_turntable_to_file()` - OR: if output_type name contains "Cinematic" → route to cinematic - **Acceptance gate**: Order line with cinematic output type renders via the new script - **Dependencies**: Task 2 ### [ ] Task 4: Output type + test - **What**: Create the "Cinematic Highlight" output type via API: ```json { "name": "Cinematic Highlight", "renderer": "blender", "output_format": "mp4", "render_backend": "celery", "is_animation": true, "transparent_bg": false, "cycles_device": "gpu", "render_settings": { "width": 1920, "height": 1080, "engine": "cycles", "samples": 128, "cinematic": true, "fps": 24, "frame_count": 480 } } ``` Link to BlenderStudio template. Test with a real product. - **Acceptance gate**: A cinematic MP4 renders successfully for a TRB product - **Dependencies**: Task 3 ## Migration Check **No** — no DB changes needed.