feat(remotion): FlexStory scene engine — ordered editable scene-blocks (Phase 1)

Turns a template into an ordered list of editable scene blocks instead of one
monolithic composition — the foundation for the scene-based template engine
(all Renderforest-style types, per-scene editable duration, add/duplicate/
delete/reorder). Render-side only; backend wiring is Phase 2.

- src/scenes/types.ts: SceneInstance/BlockProps/SceneBlock + withDefaults/clamp.
- src/scenes/chrome.tsx: shared 2.5D Three.js backdrop (parallax camera, blobs,
  particles, optional 3D confetti) + grain/vignette/progress/kicker/transition.
- src/scenes/blocks/*: Core 6 blocks — TitleCard, CharacterScene (full room +
  vendored CC0 character behind a desk), ImageCaption, KineticQuote, Slideshow,
  OutroCTA — each with editable fields + its own duration range.
- src/scenes/registry.ts: the block registry (blockId -> block).
- src/compositions/FlexStory.tsx: the sequencer — stacks blocks in <Sequence>,
  clamps per-scene duration, and computes composition length dynamically via
  calculateMetadata (so add/delete/reorder/duration all flow to the render).
- StoryScenes.tsx: the 2.5D story proof this productizes; docs/TEMPLATE_BRIEF.md:
  the guided creator flow + Template Spec.

Verified: all 6 blocks render via FlexStory in 16:9/1:1/9:16; a custom props
override (reordered scenes, custom characters/durations/colors) renders correctly
and the total length tracks Σ per-scene durations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-23 07:45:57 +03:30
parent fd364209e7
commit d830c56ea0
13 changed files with 1069 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
import type { SceneBlock } from "./types";
import { TitleCardBlock } from "./blocks/TitleCard";
import { CharacterSceneBlock } from "./blocks/CharacterScene";
import { ImageCaptionBlock } from "./blocks/ImageCaption";
import { KineticQuoteBlock } from "./blocks/KineticQuote";
import { SlideshowBlock } from "./blocks/Slideshow";
import { OutroCTABlock } from "./blocks/OutroCTA";
/**
* The scene-block registry. A FlexStory template is an ordered list of these
* blocks; new template types = new blocks. Each block declares its editable
* fields + duration range (so the studio can clamp per-block, not globally).
*/
export const SCENE_BLOCKS: Record<string, SceneBlock> = {
[TitleCardBlock.id]: TitleCardBlock,
[CharacterSceneBlock.id]: CharacterSceneBlock,
[ImageCaptionBlock.id]: ImageCaptionBlock,
[KineticQuoteBlock.id]: KineticQuoteBlock,
[SlideshowBlock.id]: SlideshowBlock,
[OutroCTABlock.id]: OutroCTABlock,
};
export const BLOCK_LIST = Object.values(SCENE_BLOCKS);
export const getBlock = (id: string): SceneBlock | undefined => SCENE_BLOCKS[id];