Skip to content

Review & Export

Nothing renders until a human has approved it. The platform has two human-in-the-loop gates during generation, a QA review pass in the editor, and an on-demand render/export step. This page covers the review process and the rendering capabilities.

Human-in-the-loop gates

The Director workflow suspends for human approval twice. The UI for both lives in web/src/components/DirectorPanel.tsx.

Gate 1 — Storyboard

After ANALYZE, the run suspends and the proposed storyboard is shown:

  • What's shown: scene count, the narrative, the anchor blueprint, and a runner badge (llm or stub) so you know whether AI or the deterministic stub produced it
  • What you can do:
  • Edit any scene's intent (free text)
  • Swap a scene's template (SceneTypePicker) and see its beat badge
  • Remove a scene
  • Add notes and Regenerate (re-run ANALYZE with your feedback)
  • Approve / Build to proceed
  • Dirty tracking: editing flips the action to "Build edited storyboard"

The decision is sent via POST /api/director/:runId/resolve:

Decision Effect
approve WRITE → ASSEMBLE → returns the ResolvedIR
edit Adopt the edited storyboard, then proceed as approve
reject Re-ANALYZE with notes → revised storyboard

Gate 2 — Content

After ASSEMBLE, the document opens in a content review:

  • Per-scene: edit template params (via PropEditor) and the voiceover (editable script text + Regenerate audio)
  • Edits update the ResolvedIR immediately
  • Actions: Regenerate from brief (fresh content from the same intake), New brief, or Approve & open in editor

Review phase (QA pass)

In the editor, the Review tab (web/src/components/ReviewPanel.tsx) is a deterministic QA report — no LLM, no render. For every scene it checks:

  • Template validityrequireModule(templateId).schema.safeParse(props) (are the props valid for the template?)
  • Duration — is the scene length sane?
  • Voiceover — is narration present where expected?
  • Aspect support — does the template support the document's aspect?

It rolls these into a readiness summary; clicking a scene jumps back to Edit to fix it. This is the last check before delivery.

Deliver phase (render & export)

The Deliver tab (web/src/components/DeliverPanel.tsx) renders the document to MP4:

  • Live progress on the document's native aspect (16:9 / 9:16 / 1:1)
  • One-click aspect variants — render the same document in other supported aspects
  • Session render history with download links

How rendering works

Export is in-process, via @remotion/renderer in web/src/app/api/director/export/route.ts:

sequenceDiagram
    participant UI as DeliverPanel
    participant API as /api/director/export
    participant R as Remotion renderer
    UI->>API: POST { ir }  → jobId
    API->>R: ensureBrowser() + selectComposition("StudioDoc") + renderMedia({ inputProps: ir })
    R->>R: headless Chromium renders VideoDocument(ir) → MP4
    R-->>API: write storage/renders/<id>.mp4
    UI->>API: GET ?jobId  (poll)
    API-->>UI: { progress } … then { url }
  • Composition: the generic StudioDoc composition (registered in web/remotion/Root.tsx) renders the live document; inputProps carry the ResolvedIR
  • Same component as preview: renderMedia renders the same VideoDocument.tsx the editor previews — preview and export cannot drift
  • Asset access: the render's Chromium fetches logical asset paths from /api/media using ASSET_BASE_URL (default http://127.0.0.1:3000); the render bundle is served on REMOTION_RENDER_PORT (default 3333, must differ from Next's 3000)
  • Asset pruning: missing audio/image/video src values are dropped so a placeholder doesn't break the render
  • Job model: an in-memory job map tracks progress; the client polls GET ?jobId. (Jobs are per-process — a restart clears in-flight jobs; finished MP4s persist on disk.)
  • Output: MP4 under storage/renders/, downloadable via /api/media

Render settings

  • fps: 30 (from the document dimensions)
  • Resolution: from aspect — 1920×1080 (16:9), 1080×1920 (9:16), 1080×1080 (1:1)
  • Codec: H.264 MP4 (Remotion default)

Saving the project

Independently of rendering, the document itself can be saved to the server document store via POST /api/director/docs and reloaded later — so a video can be revisited and re-exported without regenerating. See Library & Media.