Files
Hartmut f22b963be9 feat: cinematic highlight render — 20s procedural camera animation
New render type: 4-segment cinematic camera animation (480 frames @ 24fps)
for professional product highlight videos.

Camera sequence:
1. Establishing (5s): slow 45° orbit + push-in, 50mm lens
2. Detail sweep (5s): low-angle close arc, 85mm telephoto, shallow DOF
3. Crane up (5s): rising 30°→60°, 35mm wide reveal, pull-back
4. Hero close (5s): push-in to beauty angle, 65mm, smooth ease-out

Technical:
- cinematic_render.py: procedural camera from bounding sphere, cubic easing,
  per-frame keyframes (location, rotation, focal length, DOF)
- render_cinematic_to_file(): service function (same pattern as turntable)
- Pipeline routing: render_settings.cinematic flag → cinematic path
- Depth of field enabled (f-stop scales with product size)
- use_persistent_data for BVH caching between frames
- Same material/template/USD pipeline as turntable

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:25:56 +01:00

3.6 KiB

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 -- \
      <glb_path> <output_mp4> <width> <height> <engine> <samples> \
      <smooth_angle> <cycles_device> <transparent_bg> <template_path> \
      <target_collection> <material_library_path> <material_map_json> \
      <part_names_ordered_json> <lighting_only> <shadow_catcher> \
      <rotation_x> <rotation_y> <rotation_z> \
      [--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:
    {
      "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.