---
title: Make an intro, welcome video, outro or logo animation for your channel or business
description: A short channel intro, welcome video, outro or logo animation, with your logo moving in, your name in animated text and a sound hit.
---
You get a channel intro, a welcome video, an outro or a logo animation (also called a logo sting or logo reveal). Your logo flies or fades in, your name appears in animated text, and a whoosh or a hit lands with it. The result is an MP4 you can put at the start or end of every video.

Use invideo for this when you want to change the intro later without starting over: every logo move, text line and sound sits on an editable timeline, so a new tagline is one edit, not a new order.

## Quickest path

Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt.

```text
Make a 5 second intro for my cooking channel "Maya Cooks". Use the logo
in ./brand/logo.png. Zoom the logo in from small, then show the channel
name under it in white. Add a soft whoosh when the logo lands. 16:9.
Price any generation first and show me frames before you export.
```

In a chat app, you drag the logo into the project's Media panel in invideo, then name it in the chat. In a terminal, you name the file and the agent uploads it.

## What you need

Have these ready before you start. The agent asks for anything that is missing.

- **Your logo.** A PNG, best with a transparent background. A JPG works too; the agent can remove a white box around it.
- **The text.** The channel or business name, and a tagline if you want one.
- **The length.** Intros are short. Give a number of seconds.
- **The shape.** 16:9 for YouTube, 9:16 for Shorts, Reels and TikTok, 1:1 for a feed.
- **The mood.** Clean, playful, glitchy or cinematic. This picks the motion, the effects and the sound.
- **Your font, if you have one.** A TTF, OTF, WOFF or WOFF2 file.

## Steps

Your agent edits on a branch and tells you what changed at each step.

<Steps>
<Step title="Make the timeline and a branch">
The agent makes a project with `new_project` and a timeline with `new_timeline` in the shape you asked for. It creates a branch with `timeline_history`. Expected result: a timeline URL on the new branch.
</Step>
<Step title="Bring in the logo and the font">
The agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the timeline URL. A font file goes in the same way, and its id is the `font` that `add_text` takes. For a logo with a white box around it, the agent runs `media` `image.removeBackground` on the logo's sequence URL from `add_media`, with `dry_run: true`, then with `max_credits` and an `idempotency_key`. Expected result: the logo and the font in the media bin.
</Step>
<Step title="Place and animate the logo">
The agent places the logo with `insert_media` and sets its length with `trim_clip`. For a fade or a spin, it uses `set_keyframes` on `opacity` or `rotation`. For a zoom or a fly-in, it adds a lane with `add_keyframe_lane` (`zoom_x` and `zoom_y`, or `position_x` and `position_y`) and fills it with `add_keyframes`. Expected result: the logo moves when you play the timeline.
</Step>
<Step title="Add the name in animated text">
The agent adds the name with `add_text` and styles it with `set_text_style`. It fades the text in with `set_keyframes` on `opacity`. For a more designed look, it runs `find_models` with "animated title" and reads its pick with `get_model`. A good pick is `dynamic_text.diy`, which makes a motion graphic from a `prompt`. For a styled text overlay on a clip, a good pick is `dynamic_text.styles`, which takes the clip as `video` and a style such as `text_style: "NEON_COUNTDOWN"`. Your agent can search for others with `find_models`. The agent calls `generate` with `dry_run: true` and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: the name appears after the logo lands, or a sequence URL for the motion graphic, which the agent reads with `read`.
</Step>
<Step title="Add effects and transitions">
The agent picks effects and transitions from `timeline_catalog` by name. It adds an effect such as `lens_flare` or `pixel_glitch` with `add_effect`, and a start or end from black with `add_edge_transition` and a type such as `fade`, `light_leak` or `glitch`. Expected result: the look you asked for.
</Step>
<Step title="Add the sound hit">
The agent runs `find_models` with "whoosh sound effect" and reads its pick with `get_model`: a `prompt` and a `duration` within the range `get_model` gives. A good pick is `elevenlabs_sfx`. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` for a whoosh, hit or chime, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`, reads the sequence URL with `read`, and places the sound with `insert_media` at the frame where the logo lands. Expected result: a sequence URL for the sound, and the sound lands with the logo.
</Step>
<Step title="Check, then export">
The agent runs `capture` at the start, the moment the logo lands, and the last frame, and runs `check_timeline`. Then it runs `export` with `format` video and reads the export card until its status is `completed`. For a 4K copy, it runs `media` `video.upscale` on the export card's URL, with `dry_run` first, then `max_credits` and an `idempotency_key`. Expected result: frames with the logo sharp and the text inside the frame, and a 1080p MP4.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Maya Cooks intro"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Intro" --width 1920 --height 1080
invideo asset upload <edit-url> ./brand/logo.png ./brand/font.otf
invideo gen models <project-url> --query "whoosh sound effect"
invideo gen model <project-url> --model elevenlabs_sfx
invideo gen run <page-url> --model elevenlabs_sfx --dry-run \
  -i prompt="soft whoosh into a warm hit" -i duration=3
invideo gen run <page-url> --model elevenlabs_sfx --max-credits <price> \
  --idempotency-key intro-hit -i prompt="soft whoosh into a warm hit" \
  -i duration=3
invideo status <thread-url> --wait
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name intro-v1 --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 \
  --token <state_token> --operations @ops.json
invideo edit capture <branch-url> --at 0,1,2.5,4.9 --out ./frames
invideo edit check <branch-url>
invideo edit export <branch-url> --format video --quality 1080 --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./out
```

Where each value comes from:

- `<name>` is the name you choose in `invideo agent register`. `INVIDEO_AS` passes it to every later command.
- `<project-url>` comes from `invideo project new`, and `<edit-url>` from `invideo edit new`.
- `<page-url>` is a notebook page of the project, listed by `invideo notebook show <project-url>`. `<price>` is the dry run's `.estimated_credits`. `<thread-url>` is the `url` the paid run returns.
- `<state_token>` comes from `invideo edit show <edit-url>` for the branch command. `<branch-url>` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `<state_token>` is read again with `invideo edit show <branch-url>`.
- `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below.
- `<card-url>` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it.

The key MCP call adds the name, spins the logo in, starts its zoom lane, adds a flare and fades the logo out. This is the full call. `<branch-url>` is the branch URL that `timeline_history` returns, and `<state_token>` comes from `get_timeline` on it. `c1` is the logo clip's id from `get_timeline`. At 30 fps, one second is 30 frames.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "set_keyframes", "clip": "c1", "property": "rotation",
      "points": [ { "at_f": 0, "value": -90, "ease": "ease_out" },
                  { "at_f": 20, "value": 0 } ] },
    { "op": "add_keyframe_lane", "parent": "c1",
      "parent_kind": "video_clip", "property": "zoom_x",
      "default_value": 1 },
    { "op": "add_effect", "clip": "c1", "effect": "lens_flare" },
    { "op": "add_text", "track": "V2", "start_f": 30, "end_f": 150,
      "text": "Maya Cooks",
      "style": { "font_size": 120, "font_weight": 700,
                 "align": "center", "color": "#ffffff" } },
    { "op": "add_edge_transition", "clip": "c1", "edge": "tail",
      "type": "fade", "in_f": 0, "out_f": 15 }
  ]
}
```

The lane id comes back from `add_keyframe_lane`. The agent sends `add_keyframes` with that `lane` in a second call, with points such as `time_seconds` 0 at `value` 0.2 and `time_seconds` 0.7 at `value` 1. It does the same for `zoom_y`, so the logo keeps its shape.

## Cost and time

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.

- **Free:** the upload, the logo motion, the text, the effects, the transitions, the checks and the 1080p export.
- **Costs credits:** a sound from `elevenlabs_sfx`, a motion graphic from `dynamic_text.diy` or `dynamic_text.styles`, and a 4K upscale with `video.upscale`. An upscale is priced per second of the source video.
- **Tool ops:** `image.removeBackground`. The dry run shows its price before anything starts.

An intro takes the agent a few minutes. A 4K upscale adds a few more. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems come from a logo that is blurry when it is large, or motion that is too fast.

| Symptom | Fix |
| --- | --- |
| `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. |
| Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status <url> --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. |
| `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show <card-url> --out <dir>`. |
| `image.removeBackground` or `video.upscale` refused with `code: "not_found"` | The call named a media bin asset. Pass the file's sequence URL, from `add_media` or the export card. |
| The logo looks soft at full size | Use a larger PNG, or an SVG turned into a large PNG. A zoom past the file's own size looks soft. |
| The logo has a white box | Run `media` `image.removeBackground` on it, then place the new image. |
| `set_keyframes` refused for zoom or position | It takes `opacity` and `rotation` only. Use `add_keyframe_lane` and `add_keyframes` for zoom and position. |
| The text is cut off at the edge | The agent moves it with `set_position`, then runs `capture` again. |
| The motion feels too fast | Ask for a longer move. The agent moves the last keyframe later. |
| The sound lands early or late | The agent moves the sound clip with `move_clip` to the frame where the logo lands. |
| `edit_timeline` refused as stale | Someone edited since the read. Read with `get_timeline` and send again with the new `state_token`. |
| CLI exit 5 | A limit: credits or quota. Lower the generation, or add credits, then run it again. |
| Avoid: generating the sound again to check on it | Instead: `read` the sequence URL, or run `invideo status --wait`. |
| Avoid: saying done without looking | Instead: `capture` frames at the start, the landing and the end. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make an outro for my channel: "Thanks for watching" with my logo in the
corner, room for two end-screen videos on the right, and a soft chime.
10 seconds, 16:9.
```

```text
Make a logo reveal for my bakery from ./logo.png. Glitch the logo in,
add a light leak, and a bass hit when it settles. Then make a 9:16
version on its own branch for Reels.
```

```text
Make a welcome video for my YouTube channel page. My logo, then three
lines: "New recipes every Friday", "Real kitchens", "Subscribe". Slow
fades, warm music from stock, 20 seconds.
```

## When to use something else

invideo exports MP4 at 1080p. For a 4K file, the agent exports, then upscales.

- **A GIF.** Convert the MP4 with <a href="https://ffmpeg.org" target="_blank">FFmpeg</a> or any GIF converter.
- **A transparent version.** An intro with a see-through background, to lay over other footage in another app, needs a tool that exports alpha, such as After Effects or DaVinci Resolve. invideo burns the logo and text into the video.
- **A template you bought.** An After Effects or CapCut template file does not open in invideo. The agent rebuilds the look on the timeline instead.

## Related

- [Make a lyric video or text animation for your song](/how-to/creators/lyric-video)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)
- [Repurpose one video for every platform, one branch each](/how-to/creators/repurpose-for-every-platform)
- [Customize a template you bought](/how-to/creators/customize-a-template-you-bought)
- [Check your video before you say it is done](/how-to/check-your-video)
- [Timeline edit operations](/reference/edit-operations)