Skip to content

Studio Editor & Timeline

The Studio editor is the main authoring surface — a live Remotion editor bound to a single canonical ResolvedIR. It is the application's home route (/): the editor is the dashboard.

Entry: web/src/app/page.tsxweb/src/components/StudioV2.tsx Document model: web/remotion/document/ir.ts (ResolvedIR) + web/src/document/irStore.ts (Zustand store)

Layout

┌──────────────────────────────────────────────────────────────┐
│  Top bar:  title · phase tabs · "New ▾" (blueprint) · Generate · Export · nav │
├───────────────┬──────────────────────────────┬───────────────┤
│  Inspector    │  Player (live Remotion)      │  Chat          │
│  (scene/doc)  │                              │  (AI edits)    │
│               ├──────────────────────────────┤               │
│               │  Timeline (TimelineV2)       │               │
└───────────────┴──────────────────────────────┴───────────────┘

Side panels are resizable (drag divider) and collapsible. The preview uses @remotion/player and tracks the current frame for the timeline playhead.

Three phases

The top bar switches between three phases of work:

Phase Component Purpose
Edit StudioV2 (inspector + player + timeline + chat) Free-form editing of the document
Review ReviewPanel.tsx A QA pass — per-scene validity, duration, voiceover, aspect support (no LLM, no render)
Deliver DeliverPanel.tsx Render + export to MP4, with aspect variants and a render history

Review and Deliver are covered in Review & Export.

Starting a document

Three ways to begin:

  1. Generate — open the Director (DirectorPanel) to create a document from a brief
  2. New ▾ — pick a blueprint starter (one of ~68 whole-video blueprints or a single-scene starter)
  3. Open — reload a previously saved document from the library

The document model

Everything is a ResolvedIR (see Architecture):

ResolvedIR
├── meta { id, title }
├── dimensions { fps: 30, width, height }   # from aspect 16:9 | 9:16 | 1:1
├── theme { accent, bg, fontFamily, … }
├── scenes: ResolvedScene[]
│   ├── templateId        → one of 216 modules
│   ├── props             → validated against the module's Zod schema
│   ├── durationInFrames
│   ├── transitionOut?    → fade | slide | wipe | cut
│   ├── background?
│   └── voiceover?        → { src, volume, text, envelope }
├── background? · music? · logo? · voice?

Editing capabilities

  • Inspector — precise per-scene and per-document controls (AI-Assisted Editing)
  • Chat — edit by conversation, with undo/redo (AI-Assisted Editing)
  • Timeline — select scenes, scrub, see transitions and volume envelopes (AI-Assisted Editing)
  • Add / remove / duplicate scenes, swap templates, reorder
  • Live preview — the Remotion <Player /> re-renders on every IR change
  • Backgrounds, music, logo overlay, theme tokens at the document level

How the editor renders

The editor mounts one generic component — web/remotion/document/VideoDocument.tsx — which interprets any ResolvedIR:

  • Scenes become a TransitionSeries of SceneShell wrappers + data-driven transitions
  • SceneShell applies the scene background + theme context, then instantiates the template module via requireModule(templateId) with validated props
  • Document-level background, music, and logo overlay are composed on top
  • Voiceover audio plays per scene with envelope automation

This is the same component used by the headless renderer, so the preview is an exact match for the exported MP4. See Review & Export.

Voiceover timing

web/remotion/document/timing.ts (resolveVoTimings) measures each scene's narration audio and resolves "auto" scene durations to the real narration length. It runs on Player mount and before export, so the timeline length always reflects the actual audio.

Media resolution

Asset src values in the IR are logical paths (e.g. voiceover/s1.mp3). web/remotion/document/assets.tsx resolves them through an AssetBaseContext:

  • In the browser the base is "" → fetched via Next.js /api/media
  • During a headless render the base is ASSET_BASE_URL (http://127.0.0.1:3000) so the render's Chromium can fetch the same files

Persistence

The store auto-persists to localStorage; explicit saves go to the server document store via /api/director/docs (see Library & Media). The Director's HANDOFF writes finished documents there automatically.