---
title: Use Remotion with invideo
description: Bring a Remotion composition into invideo as an MP4, or have your agent rebuild it as an editable timeline, then finish it with voice, music and captions.
---
It depends on who edits the video after the code. Remotion makes video from React code, rendered by you or your coding agent; invideo is where that video meets footage, voice, music and captions on a timeline a person can review and change without touching the code. Your agent brings the composition in as a rendered MP4, or rebuilds its elements on the timeline from the source.

## When to use both

Use both when the Remotion render is one part of a finished video. The animated parts come from code. The edit around them happens in invideo.

- **Data and motion inside a real edit.** A chart, a map route or a product callout from Remotion sits between interview clips or b-roll.
- **The voice and music come later.** You add and mix them on a timeline, not in code.
- **A person reviews the cut.** Someone without a code editor watches the timeline in the browser and asks for changes.
- **Variants.** Several hooks or end cards on branches, around the same render.

## Hand-off: from Remotion into invideo

There are two paths in. The render comes in as footage, or your agent rebuilds the composition as clips, text and keyframes.

### Bring the render in as footage

Remotion renders a composition by its id:

```bash
npx remotion render MyComposition out/intro.mp4
```

Without `--codec`, Remotion uses the H.264 encoder, and without an output path it writes to the `out` folder. You can also render from Remotion Studio with the **Render video** button. Your agent knows these steps from the Remotion skills, installed with `npx skills add remotion-dev/skills`, such as `/remotion-render` and `/remotion-docs`. Remotion has no hosted MCP server. It points agents at the `/remotion-docs` skill.

Then your agent brings the MP4 into invideo:

- **A public link.** `add_media` with `media_url`.
- **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload <project-url> <file>`.
- **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`.

Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin.

The MP4 becomes a clip like any other. It is footage, so the text and shapes inside it are pixels, not editable layers. To keep them editable, take the second path.

### Rebuild the composition on a timeline

The second path keeps each element editable. Your agent reads the React component: its `<Composition>` size and `fps`, each `<Sequence>` with `from` and `durationInFrames`, and the values that `interpolate` and `spring` animate and rebuilds each element with edit operations, on a branch. [Rebuild a Remotion, HyperFrames or Tesseract composition as an editable timeline](/how-to/developers/composition-to-timeline) gives the steps. The mapping in short:

- **Size and timing.** `set_timeline_settings` with the composition's size and `fps`. With the same `fps`, Remotion frame numbers copy over as they are.
- **Text.** `add_text`, `set_text_style` and `style_text_range`, with fonts uploaded through `add_media`.
- **Images and video.** `add_media`, then `insert_media` or `place_media`, with `set_position` and `set_zoom`.
- **Motion.** `add_keyframe_lane` and `add_keyframes` for position and zoom, `set_keyframes` for opacity and rotation.
- **Layers with no op.** Canvas, WebGL or a third-party component: render that layer alone in Remotion and place it as a clip.

### The finish

On either path, the agent finishes the video:

- **Footage and b-roll** placed around the render with `place_media`, from your files or `search_library`.
- **Voice** from `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `generate`, or your own recording.
- **Music** from `search_library` in `stock_music`, mixed with `set_audio_gain` and `set_audio_fades`.
- **Captions** with `media` `audio.transcript` on the voice, then `add_captions`.

### Text animation without Remotion

For animated text on a clip inside invideo, your agent has three routes. `add_text` with `set_keyframes` animates text on the timeline, and edits are free. The models `dynamic_text.diy` and `dynamic_text.styles` make animated text. The model `uc_remotion_text` burns exact text onto a video as a single-font animated overlay. The models cost credits, so the agent prices them with `dry_run` first.

## Hand-off: from invideo to Remotion

The way back is an MP4. `export` with `format` `video` renders the timeline, and a Remotion composition plays it with the `<OffthreadVideo>` component, from a URL or a local file. For an editor, `export` with `format` `premiere`, `davinci` or `final_cut` makes a project file for Premiere Pro, DaVinci Resolve or Final Cut Pro.

## Steps

Your agent sets up with [invideo for AI agents](/agents) first. These steps follow the render path. For the rebuild, your agent follows the steps on the rebuild page.

Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything.

Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost.

<Steps>
<Step title="Render in Remotion">
The agent runs `npx remotion render` with the composition id and an output path. Expected result: an MP4 on disk.
</Step>
<Step title="Bring the render in">
The agent calls `start_upload`, puts the bytes, then `add_media` on the timeline URL. Expected result: a sequence URL and a media bin id.
</Step>
<Step title="Build the cut on a branch">
The agent creates a branch with `timeline_history` and places the render, footage and music with `edit_timeline`. Expected result: a new `state_token`.
</Step>
<Step title="Pick and price the voice">
If you have no recording, the agent runs `find_models` with the voice-over in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`. The agent can search for others with `find_models`. It picks a `voice_id` with `search_library`, calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge.
</Step>
<Step title="Make the voice">
The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check.
</Step>
<Step title="Caption the voice">
The agent prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a caption clip.
</Step>
<Step title="Check and export">
The agent calls `capture` at the joins between the render and the footage, and `check_timeline`. Then it calls `export`. Expected result: an export card with status `completed`.
</Step>
</Steps>

The voice from a terminal:

```bash
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo gen models <project-url> --query "voice-over from a script"
invideo gen model <project-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4
invideo library search <project-url> \
  --library elevenlabs_text_to_speech_voices --query "calm"
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  -i prompt=@script.txt -i voice_id=<voice-id> \
  --max-credits <price> --idempotency-key voice-1
```

`<project-url>` comes from `invideo project new` or `list_projects`. `<name>` is the name you choose in `invideo agent register`. `<page-url>` is a page that `invideo notebook show <project-url>` lists. `<price>` is the price the dry run returns. `<voice-id>` is an `id` that `invideo library search` returns.

## When to stay in Remotion

Stay in Remotion when the video is data-driven and made from code end to end, such as one render per user or per row. Stay there too for what invideo's `export` does not make, such as other codecs like ProRes or an image sequence. For a change to a rendered animation, change the code and render again, then swap the clip in invideo with `place_media` mode `replace`. After a rebuild, change the element on the timeline instead.

## If something goes wrong

| Symptom | Fix |
| --- | --- |
| `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. |
| Remotion shows a composition picker, and the render waits | Name the composition id in `npx remotion render`. |
| `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. |
| Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. |

## Related

- [When to use Remotion vs invideo](/compare/remotion)
- [Use HyperFrames with invideo](/integrations/hyperframes)
- [CSV to videos](/how-to/developers/csv-to-videos)
- [Rebuild a composition as an editable timeline](/how-to/developers/composition-to-timeline)
- [Intro, outro and logo animation](/how-to/creators/intro-outro-logo-animation)
- [Check your video before you say it is done](/how-to/check-your-video)

<Collapse title="Does invideo open a Remotion composition as layers?">
Not as a file. Your agent reads the React source and rebuilds the elements as clips, text and keyframes you can edit. A rendered MP4 stays one clip: its text, shapes and timing are part of the picture, so a change to it means a new render in Remotion.
</Collapse>

<Collapse title="Can I keep the render's sound?">
Yes. When the render has sound, your agent places it with `place_media` and `linked_audio` set to true. The sound then moves with the picture on the timeline.
</Collapse>