Skip to content

feat(animated-shorts): Three.js + Remotion shorts pipeline w/ local & router render modes#19

Open
ninan-versioning wants to merge 2 commits into
mainfrom
jared-shoploop/animated-shorts
Open

feat(animated-shorts): Three.js + Remotion shorts pipeline w/ local & router render modes#19
ninan-versioning wants to merge 2 commits into
mainfrom
jared-shoploop/animated-shorts

Conversation

@ninan-versioning

Copy link
Copy Markdown
Owner

Summary

@shoploop/animated-shorts — deterministic vertical ad shorts (9:16, 1080×1920, 6s/9s/15s) for Varitea, built from the same USD product twins the live web renderer uses. Three.js scenes are embedded in Remotion compositions and driven entirely off Remotion's frame counter — frame-accurate, no requestAnimationFrame, no drift. The same storyboard renders the same bytes every time.

USD twin (.usda) → composed scene → Three.js animated capture (Remotion) → encoded MP4 → Creative Pack

A short emits the identical creative_pack.v1 shape a still does, so the Thompson Sampling bandit joins shorts and stills by (twin_handle × preset) without caring which pipeline produced them.

The five primitives

# Primitive File
1 Storyboard DSL (+ storyboard.v1.json) src/dsl/storyboard.ts
2 Remotion composer src/composer/Short.tsx
3 Three.js bridge (imperative camera/variant/material handles, auto-rotate OFF) src/three/ThreeCanvas.tsx
4 Render orchestrator (local + open-imagine) src/render/orchestrator.ts
5 Bandit feedback bridge (RenderProvenanceBANDIT_QUEUE_PATH) src/feedback/observation.ts

The Three.js scene comes from the SAME parser + scene builder as @shoploop/twin-renderer (re-exported as namespaces in this PR, not duplicated), so offline shorts and the live web twin stay pixel-for-pixel in agreement.

Render modes — one output

  • local (default, dev, $0): @remotion/renderer headless capture (gl: angle, software GL so it runs in CI/containers without a GPU).
  • open-imagine: dispatches to the GPU router (POST /v1/render → poll GET /v1/jobs/:id). The router's blender_cpu stub keeps this path at $0 in this PR.

Both return the same Creative Pack — callers and the bandit never branch on where a short was rendered.

Kinfolk gating at compose time

brand_rules.json is enforced before the render. The orchestrator composes the scene for every variant the storyboard visits and scores it (palette / finish / camera); a storyboard that would emit an off-brand frame is refused with BrandRulesViolation and its reasons — never silently shipped.

Storyboards

  • storyboards/varitea_jasmine_hero_6s.json — 6s hero, orbit camera, single lower-third overlay at 2s.
  • storyboards/varitea_flavors_lifestyle_15s.json — 15s lifestyle, dolly-in, flavor flip at 5s & 10s (jasmine → hibiscus → genmaicha), centered end card.

Cost

~$0/mo — local mode renders on-machine; router stub is CPU/$0.

Acceptance

shoploop-shorts render --storyboard storyboards/varitea_jasmine_hero_6s.json
# → var/shorts/varitea_jasmine_hero_6s.mp4  (verified 1080×1920, 6.0s, H.264 CRF 18)

Test plan

  • pnpm test — dsl schema · composer 1-frame · local MP4 render (>0 bytes) · router mock (POST body + polling) · Kinfolk refusal — 16 passed
  • pnpm typecheck clean
  • Existing @shoploop/twin-renderer tests stay green (14 passed)
  • Acceptance command produces a 1080×1920 6.0s MP4 locally

🤖 Generated with Claude Code

ninan-versioning and others added 2 commits June 25, 2026 03:40
Browser-side renderer consuming product_twin.usda from
@shoploop/connector-shopify. Minimal USDA->scene-graph parser, r3f
scene builder with procedural placeholder + external GLB/USDZ refs,
ProductTwin/VariantSelector/Stage components, and a Varitea demo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… router render modes

Deterministic vertical ad shorts (9:16, 1080x1920) built from the same USD
product twins as the live web renderer. Three.js scenes are embedded in Remotion
compositions and driven entirely off the frame counter — frame-accurate, no drift.

- Re-export parser + scene namespaces from @shoploop/twin-renderer (not duplicated)
- Storyboard DSL + JSON schema, Remotion composer, ThreeCanvas bridge,
  local/open-imagine orchestrator, bandit RenderProvenance feedback
- Kinfolk brand gating at compose time (refuses off-brand renders)
- shoploop-shorts CLI + two checked-in Varitea storyboards

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant