Compose a NARRATED, MULTI-SHOT video from a script — NOT a single ~5s clip. Use this when you need a coherent minute-ish demo / explainer with voiceover: it synthesizes the narration, storyboards it into beats, generates a continuity-chained shot per beat, and renders with transitions + Ken-Burns + captions via Remotion. (For a single short clip, use `lamina_generate_video`.)
WORKFLOW: (1) `lamina_compose_video({ script })` → dispatch, get `runId`. (2) `lamina_compose_video({ runId, wait: true })` → block until done; or poll `{ runId }`. Composition takes minutes.
INPUTS:
• `script` (required to start): the narration to speak (a hook + one insight + a CTA; ≤~90s). The transcript/chapters derive from this, so the video stays coherent with its text.
• `title` / `generationBrief` (optional): title + a one-paragraph visual brief for the shots.
• `direction` (optional): free-text creative direction ("open on the product, fast cuts, end on the logo") — steer the render WITHOUT naming models.
• `sections` (optional): structured per-span hints `[{ text?, hint, mustShow? }]` for a prescriptive storyboard.
• `format` / `inputs` (optional): pick a format (else auto-routed); `inputs` supplies a format's required assets (e.g. `{ presenterImage }`).
• `aspectRatio` (optional): `16:9` | `9:16` | `1:1` | `4:5` | `4:3` (default 16:9).
• `voiceId` (optional): ElevenLabs voice id. Omit and the narration director picks a voice whose tone fits the script.
• `expressive` (optional): true → adds v3 audio tags for stronger, more human inflection. (Prosody/pacing is always applied.)
• `idempotencyKey` (optional): dedupe retries — the same key returns the same run (no double charge).
• `runId` (+ optional `wait`): pass a prior runId to poll instead of starting a new run.
TIP: call `lamina_compose_plan({ script })` first to preview the format + cost + storyboard for free before committing.
RESPONSE: dispatch → `{ runId, status: "running" }`. Poll → `{ status, progress: { stage, current?, total? } }`. Terminal → `{ status: "completed", result: { videoUrl, durationSeconds, shotCount } }` or `{ status: "failed", error }`. Invalid input → an error with a machine-readable `reason` (e.g. `MISSING_REQUIRED_INPUT`, `SCRIPT_TOO_LONG`).