Shot Sequence (voiceover-paced motion graphics)

Author a narrated motion-graphics video whose on-screen text and shapes are revealed in sync with the voiceover — each visual appears the moment the narration speaks its matching phrase. Three tools form the pipeline; an LLM (or you) authors a brief, and the server bakes word timings into exact frames.

Flow

  1. generate_speech(script) → a narration MP3 (job; read audioUrl from the job output).
  2. forced_alignment(audio_url, transcript) → per-word timings (job; read output_data.alignment). The transcript MUST be the exact narration script. Costs 3 credits.
  3. resolve_shot_sequence(brief, audio_url, alignment) → a render-ready plan (synchronous; returns the plan inline + any warnings). No credits.
  4. render_shot_sequence(plan) → an MP4 (job; progress + result render in the tool card, and it lands in your library). Costs 5 credits (standard render fee).

Authoring a brief

A brief has a narration (script + cues), and scenes → shots → reveals. A cue is a contiguous phrase of the script; a reveal anchors an element to a cue:

{
  "fps": 30, "width": 1920, "height": 1080, "backgroundColor": "#0b0b0f",
  "narration": {
    "script": "Ship faster. Nodaro turns your idea into video.",
    "cues": [
      { "id": "c_ship", "text": "Ship faster" },
      { "id": "c_idea", "text": "your idea into video" }
    ]
  },
  "scenes": [
    {
      "id": "scene_hook",
      "shots": [{
        "id": "shot_1",
        "reveals": [
          {
            "id": "rv_title",
            "element": { "id": "t1", "type": "text", "text": "Ship faster", "fontFamily": "Inter", "fontSize": 120, "fontWeight": 900, "color": "#ffffff", "x": 200, "y": 450 },
            "revealAt": { "kind": "cue", "cueId": "c_ship", "edge": "start" },
            "enter": { "motion": "slide-up", "durationFrames": 12, "easing": "easeOut" }
          }
        ]
      }]
    }
  ]
}

Anchors

Element lifetime

An element unmounts at its scene’s content end — if you want it to persist visibly through the rest of the scene, set hold (frames to keep it on-screen after the entrance finishes) and/or exit (an exit motion that plays after hold).

Rules that keep it deterministic

Blueprint catalog

A catalog of parameterised shot-shapes (“blueprints”) covers the most common beat roles (15 at the time of writing — list_shot_shapes always returns the live set). Use list_shot_shapes to browse the catalog and get_shot_shape to inspect a blueprint’s exact param contract before writing a blueprint reveal in a brief.

Blueprints are declarative shot-shapes — most are text/shape only, and two (device-surface-showcase, cursor-ui-demo) take your own uploaded screenshot images as params. Either way they carry no pricing or credit information: the standard render-video credit (5 credits) applies to the overall render_shot_sequence call, not to individual blueprints.

Id Roles Default duration (frames) What it does
comparison-split feature_showcase 180 Two labeled panels slide in from opposite sides and hold with a center divider; optional badges pop near the end.
constellation-hub hook, social_proof 180 Labeled nodes spring into a ring around a center hub, then the shot resolves on the core — camera push-in or orbiting badges.
cta-morph-press cta 150 A CTA button appears centered; a cursor decelerates in and presses it.
cursor-ui-demo feature_showcase, product_intro 210 A brand cursor drives a screenshot UI through clicks while the viewport chases each target; screens swap per beat.
dataviz-countup pain_point 240 A big number counts up to a value with a label; numbers are the hero.
device-surface-showcase product_intro, feature_showcase 240 A device mockup holds as hero while its screens cycle through a real flow (camera-static static-tour); side headlines swap in sync.
grid-card-assemble feature_showcase, benefit_highlight, social_proof 180 N text cards cascade-assemble into a grid with a staggered entrance.
kinetic-type-beats hook 150 1–4 statement lines swap in by hard-cut/scale-pop; final line spring-pops on an accent.
logo-assemble-lockup product_intro, branding 180 Brand word’s letters cascade/assemble into a centered lockup (+ optional tagline).
overwhelm-surround pain_point 210 Tool cards assemble, density chips scatter in, the center morphs to reveal the viewer, then demand bubbles close in from all sides.
spatial-pan-stations hook, pain_point 240 Labeled stations on one oversized canvas, traversed by ease-in-out camera pans that pop a callout at each stop.
ticker-takeover hook, branding 180 A typed lead-in with an accent word cycling options, then the hero crashes in and shoves the text aside.
titlecard-reveal benefit_highlight, social_proof 120 One clean title (+ optional subtitle) revealed with one restrained move, then held.
typewriter-reveal hook, branding 180 Text types in character-by-character with a blinking caret; optional sublabel fades up after typing finishes.
waterfall-reveal hook, feature_showcase 150 Words of a line cut in one-by-one with a small horizontal slide, cascading left-to-right; optional sublabel fades up after the last word lands.

list_shot_shapes()

Returns the full blueprint catalog as a JSON array. Each entry:

Field Type Description
id string Blueprint identifier (kebab-case)
roles string[] Beat roles this blueprint suits (from the doctrine vocabulary)
description string One-line description
defaultDurationFrames number Default scene duration at 30 fps

No inputs, no scope gate, no credits.


get_shot_shape(id)

Returns detailed information for one blueprint.

Inputs:

Field Type Notes
id string Blueprint id, e.g. "titlecard-reveal". Call list_shot_shapes to browse all ids.

Returns (JSON):

Field Type Description
id string Blueprint id
roles string[] Beat roles
description string Description
defaultDurationFrames number Default duration
paramSchema object JSON Schema (OpenAPI 3) for the blueprint’s params object
example object Filled worked-params example ready to paste into a blueprint reveal

Unknown id → error result (isError: true) with the list of known ids.

No scope gate, no credits.


Tool reference

forced_alignment(audio_url?, audio_asset_id?, transcript)

Returns a job_id; in hosts with interactive tool cards (claude.ai), the alignment JSON renders inline in the tool card as it completes. Clients without card support poll get_job; when complete, the alignment is in output_data.alignment — an array of [{ word, start, end }] objects with timings in seconds. Costs 3 credits.

Inputs:

Field Type Notes
audio_url string (URL) HTTPS URL to the narration audio. Either audio_url or audio_asset_id is required.
audio_asset_id string (UUID) Asset ID of an existing audio file. Either audio_url or audio_asset_id is required.
transcript string The exact narration script; must match the audio word-for-word.

Returns: { job_id: string }


resolve_shot_sequence(brief, audio_url, alignment)

Pure function (synchronous). Resolves the brief into a render-ready plan by:

No credits.

Inputs:

Field Type Notes
brief object The ShotSequenceBrief — narration, scenes, shots, reveals
audio_url string (URL) HTTPS URL to the narration audio (for reference; not re-fetched)
alignment array The [{ word, start, end }] array from forced_alignment output_data

Returns:

{
  "plan": { ... },
  "warnings": [
    "Cue 'c_id' not found in transcript; reveals fall back to proportional timing"
  ]
}

If scenes interleave in time, returns HTTP 422 scene_overlap.


render_shot_sequence(plan)

Renders the resolved plan into an MP4 video. Returns a job_id; in hosts with interactive tool cards (claude.ai), progress and the finished video render inline in the tool card. The MP4 is also saved to your Nodaro library. Costs 5 credits (the standard render fee for Remotion videos).

Inputs:

Field Type Notes
plan object The resolved plan from resolve_shot_sequence

Returns: { job_id: string }


Example workflow

1. Author a narration script and brief
   "Ship faster. Nodaro turns your idea into video."
   (declare cues, scenes, shots, reveals, fonts, motions)

2. Call generate_speech(script) → get audioUrl
   Wait for job to complete

3. Call forced_alignment(audioUrl, script) → get alignment
   Wait for job; extract output_data.alignment

4. Call resolve_shot_sequence(brief, audioUrl, alignment) → get plan
   Returns immediately; check warnings

5. Call render_shot_sequence(plan) → render
   Wait for job; download MP4 from library