---
title: Make Reels and Shorts from your footage: hook, captions, transitions, sound effects
description: Turn your raw footage into vertical Reels, Shorts and TikToks with a strong hook, word-by-word captions, quick transitions and sound effects.
---
You turn your raw footage or a long video into short vertical clips (Reels, Shorts, TikToks) that open on a hook. The best line comes first, captions pop word by word, cuts land with a quick transition, and a whoosh or a pop marks each beat. Dead air, "um" and long pauses are gone.

Use invideo for this when you want your agent to pick the moments from what you said: it reads a transcript of your footage, finds the hook and the best lines, and builds each clip on a timeline you can still change.

## Quickest path

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

```text
Make three 9:16 Shorts from ./talk.mp4. Read the transcript, pick the
three strongest moments, and start each one with its best line as the
hook. Word-by-word captions, a quick transition and a whoosh on each
cut, no pauses. Price the transcript first, show me the picks and
frames before you export.
```

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

## What you need

Raw footage works best when you talk to the camera. The agent finds the moments in your words.

- **Your footage.** A talking-head video, a vlog, a podcast clip, a stream or a long YouTube video.
- **How many clips.** One, or a set of clips from one video.
- **The length.** Short and punchy, or a longer story.
- **The style.** Caption look, transitions, sound effects, music or none.
- **The platforms.** Reels, Shorts, TikTok, LinkedIn. The shape is 9:16 for all of them, or 1:1 or 4:5 for a feed.

## Steps

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

### Cut the clips

The agent finds the hook and cuts each clip first.

<Steps>
<Step title="Bring in the footage and make a vertical timeline">
The agent uploads the footage with `start_upload` and `add_media`. It makes a timeline with `new_timeline` at 9:16 and a branch with `timeline_history`. Expected result: a timeline URL and a media bin id for the footage.
</Step>
<Step title="Read the transcript">
The agent runs `media` `audio.transcript` on the footage's sequence URL from `add_media`, after a `dry_run` and the price told to you, then with `max_credits`. A transcript refuses a media bin `asset_id`. The agent calls again after `retry_after_s` for the words. Expected result: every word with its time.
</Step>
<Step title="Pick the hook and the moments">
The agent reads the transcript for lines that stand alone: a strong claim, a surprise, a question, a short story with an end. It picks the best line of each moment as the hook. It tells you its picks with timecodes before it edits. Expected result: a list of moments and hooks for you to approve.
</Step>
<Step title="Cut each clip">
The agent places the hook first and the rest of the moment after it, with `place_media` and the source start and end in seconds, with `linked_audio` true. Inside each part, it finds pauses with `audio.content` and the "um" and "uh" in the transcript, cuts them with `split_clip`, and removes them with `delete_clip` in `close_gap` mode. Expected result: a tight clip that opens on the hook.
</Step>
</Steps>

### Finish and export

Then the agent fills the frame, adds captions and sound, and checks each clip.

<Steps>
<Step title="Fill the vertical frame">
The agent runs `fill_frame` on each clip and moves it with `set_position` so your face stays in view. For a wide shot that loses too much, it runs `find_models` with "reframe to vertical". A good pick is `ltx_2_3_pro.reframe`. Your agent can search for others with `find_models`. The agent reads the pick's inputs with `get_model`, then calls `generate` with `dry_run: true`, the clip's sequence URL as `video` and `aspect_ratio` 9:16, 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`, and reads the new sequence URL with `read`. Expected result: your face in frame in every shot.
</Step>
<Step title="Add captions, transitions and sound">
The agent adds word-by-word captions with `add_captions`, using the transcript's word times, and styles them with `set_text_style`. It adds a short transition such as `slide_blur`, `shake_zoom` or `flash` at each cut with `add_transition`. For a whoosh or a pop, it runs `find_models` with "whoosh sound effect". A good pick is `elevenlabs_sfx`, which the agent reads with `get_model`. It calls `generate` with `dry_run: true`, a `prompt` and a short `duration` within the range `get_model` gives, 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 new sequence URL with `read`, and places it at each cut with `insert_media`. For music, it adds the `ducker` to the music track with `add_audio_effect`. A new timeline ducks under `A1` by default, so the agent sets `set_sidechain_source` only when your voice is on another track. Expected result: captions on every word, a sound on each cut, and music that dips when you talk.
</Step>
<Step title="Check before export">
The agent runs `capture` at the hook, each cut and the end, and runs `check_timeline`. It checks that the captions sit above the app's buttons. Expected result: the hook shows in the first frames, and the captions are readable.
</Step>
<Step title="Export">
The agent runs `export` with `format` video, one call per clip with `start` and `end`, or one timeline per clip. It reads each card until its status is `completed`. Expected result: one 1080p MP4 per clip.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Shorts from the talk"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Short 1" --width 1080 \
  --height 1920
invideo asset upload <edit-url> ./talk.mp4
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> \
  --max-credits <price>
invideo media audio.content <edit-url> --asset m1
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="short fast whoosh" -i duration=3
invideo gen run <page-url> --model elevenlabs_sfx --max-credits <price> \
  --idempotency-key whoosh-1 -i prompt="short fast whoosh" -i duration=3
invideo status <thread-url> --wait
invideo notebook show <thread-url>
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name short-1 --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.5,8,20 --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`.
- `<sequence-url>` is the `url` that `invideo asset upload` returns, and `m1` is the bin id in the same result. Reads like `audio.content` take `--asset m1`. A transcript refuses it.
- `<price>` is each dry run's `.estimated_credits`. `<page-url>` is a notebook page of the project, listed by `invideo notebook show <project-url>`. `<thread-url>` is the `url` the paid `gen run` returns, and `invideo notebook show` on it lists the sound's sequence URL.
- `<state_token>` comes from `invideo edit show`: on `<edit-url>` for the branch, then on `<branch-url>` for the change. `<branch-url>` is the `.branch_url` that `invideo branch new` returns.
- `@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, shown as the full call, places the hook, then the moment. `<branch-url>` is the branch URL `timeline_history` returns, and `<state_token>` comes from `get_timeline` on it. `m1` is the footage's bin id from `add_media`. The hook is 312.4 to 316.0 seconds in the source. The moment runs from 290.0 to 312.0 seconds.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 0,
      "source_start_seconds": 312.4, "source_end_seconds": 316.0,
      "mode": "append", "linked_audio": true },
    { "op": "place_media", "asset": "m1", "track": "V1", "at_f": 108,
      "source_start_seconds": 290.0, "source_end_seconds": 312.0,
      "mode": "append", "linked_audio": true }
  ]
}
```

The agent also sends `fill_frame` on each clip, `add_transition` with `left_clip`, `right_clip`, `type`, `in_f` and `out_f`, and `add_captions` with the slides and words. These can go later in the same call, with the clip ids the call makes, or in a second call after `get_timeline`.

## 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.

- **Tool ops:** `audio.content`. The dry run shows its price before anything starts.
- **Free:** the upload, the cuts, the reframe by hand, the captions, the transitions, the checks and the exports.
- **Costs credits:** the transcript, once per file, the sound effects from `elevenlabs_sfx`, paid stock music, and any shot run through `ltx_2_3_pro.reframe`.

A set of clips from one video takes the agent a few minutes once the transcript is back. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems come from a weak hook, captions under the app's buttons, or a cut in the middle of a word.

| 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. |
| `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the footage's sequence URL from `add_media` or `invideo asset upload`. |
| `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show <card-url> --out <dir>`. |
| The hook is weak | Ask for three hook options. The agent puts each on its own branch so you can compare. |
| A cut lands in the middle of a word | The agent moves the cut to the word's end time in the transcript with `trim_clip`. |
| Captions are behind the app's buttons | Move the caption clip up with `set_position`. Add safe-zone guides with `create_guide`. |
| A face is cut off | Move the clip with `set_position`, or zoom out with `set_zoom`. |
| `audio.transcript` returns a status, not words | It is still working. Call it again after `retry_after_s`. Only the first call costs credits. |
| The transition feels slow | Shorten it with `resize_transition`, or use `cut`. |
| CLI exit 7 | Nothing ran. Run the same command again. |
| Avoid: transcribing the file again for each clip | Instead: the transcript is kept on the file. Call `audio.transcript` again for the words. Only the first call spends credits. |
| Avoid: saying done without looking | Instead: `capture` the first frames, where the hook is. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make one LinkedIn clip from my webinar recording ./webinar.mp4: 1:1,
the single best tip, a clear title card on top, clean captions, no
sound effects. Professional, not flashy.
```

```text
Make five TikToks from my podcast episode. Each one opens on a question
someone asks. Big yellow captions, a pop on each caption change, and
a light leak transition between parts.
```

```text
Cut my vlog ./day.mp4 into one 9:16 Short. Start with the funniest
line, cut every pause longer than half a second, add a whoosh on each
cut and upbeat stock music ducked under my voice.
```

## When to use something else

invideo does not post or schedule. Upload each clip in the app, or use a scheduler such as Buffer or Later. invideo does not score clips for "virality". The agent picks moments by reading what you said. For an automatic score, a clip tool such as OpusClip does that.

## Related

- [Add word-by-word captions](/how-to/creators/word-by-word-captions)
- [Cut ums, pauses and retakes](/how-to/creators/cut-ums-and-retakes)
- [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform)
- [Edit a podcast episode and pull clips from it](/how-to/creators/podcast-edit-and-clips)
- [When to use OpusClip or Descript vs invideo](/compare/opusclip-descript)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)