---
title: Make a wedding video from guest clips
description: A wedding highlight video, or wedding film, from the clips your guests filmed, with the vows, the speeches, music and a new branch for each round of changes.
---
You get a wedding highlight video, also called a wedding film or wedding recap, from the clips your guests filmed on their phones. Your agent finds the vows and the best lines of the speeches in a transcript, picks the cheers and the first dance by their sound, cuts them to music, and keeps each round of your changes on its own branch.

Use invideo for this when the footage is many large files from many phones: your agent uploads them straight to your project, reads every word said, and you can ask for "shorter speeches" or "more of Grandma" without losing the cut before.

## Quickest path

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

```text
Make a 4 minute wedding highlight video from the guest clips in
./wedding. Find our vows and the best lines from the speeches, keep
the first kiss and the first dance, and add soft music under the rest.
16:9. Tell me the price of the transcripts first, and show me frames
before you export.
```

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

## What you need

Collect every guest clip in one folder first, from a shared album or a drive.

- **The clips.** MP4 or MOV from phones and cameras, any size, any shape.
- **The moments that must be in.** The vows, the kiss, the first dance, a speech, a name.
- **The names.** Who gave which speech, so the agent can find them.
- **The length.** A highlight of a few minutes, or a longer film.
- **The music mood.** Romantic, upbeat, acoustic, or your own licensed song.
- **The shape.** 16:9 for a TV, 9:16 for a phone teaser.

## Steps

Your agent edits on a branch and starts a new branch for each round of changes.

<Steps>
<Step title="Upload every clip">
The agent makes a project with `new_project`. For each file, it calls `start_upload`, PUTs the bytes to the `upload_url`, then calls `add_media` with the `upload_id`. Large files upload this way with no link needed. Expected result: a sequence URL per clip.
</Step>
<Step title="Price and start the transcripts">
The agent prices `audio.transcript` with `dry_run` on each clip with speech and tells you the total. It starts each one with `max_credits`, and calls again after `retry_after_s` for the words. Only the first call spends credits. Expected result: every word said, with its time and speaker.
</Step>
<Step title="Find the moments and look at them">
The agent reads the transcripts for the vows and the best speech lines, and runs `media` `audio.content`, `audio.onsets` and `video.sceneSplit` to find cheers, claps, the glass clink and the cuts. It runs `video.frames` at each pick to check the picture: eyes open, not shaky, people in frame. Expected result: a shot list with clip, start and end, which the agent shows you.
</Step>
<Step title="Clean a noisy clip, if you need to">
For a vow clip with wind or crowd noise, the agent runs `find_models` with the job in words, like "clean the voice in a video", and `get_model` on its pick. A good pick is `clean_voice.clean_video`. Your agent can search for others with `find_models`. It calls `generate` with `video` set to the clip's sequence URL, `keep_music` true and `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`. The original stays. Expected result: a sequence URL for a new, cleaner video, which the agent reads with `read`, never with a second `generate`.
</Step>
<Step title="Cut the highlight">
The agent makes a timeline with `new_timeline` and creates a branch with `timeline_history`. It places each pick with `place_media`, the source range from the shot list, and `linked_audio` true for the vows and speeches. Vertical guest clips get the `fit_with_blur` effect. Expected result: a first cut on its own branch.
</Step>
<Step title="Add music and titles">
The agent adds music from `stock_music` with `search_library` and `add_media`, with the `ducker` audio effect on the music track, so the music drops under speech. A new timeline ducks under `A1` by default. The agent sets `set_sidechain_source` only when the speech is on another track. It adds your names and the date with `add_text`. Expected result: music under the cut and quiet under every line.
</Step>
<Step title="Check and export">
The agent runs `capture` at the vows, each speech, the kiss and the end, and `check_timeline`. It checks loudness with `media` `audio.loudness` on the speech clips. Then it runs `export` with `format` video and `target_lufs`. In a terminal, it saves the file with `invideo notebook show` on the card's URL. Expected result: an export card with status `completed`.
</Step>
</Steps>

For each round of changes you ask for, the agent saves a checkpoint with `timeline_history` and creates a new branch, like "round-2-shorter-speeches". You compare the branches in the editor, and the earlier round stays untouched.

The same job from a terminal. `asset upload` sends each local file for you.

```bash
invideo project new --title "Sara and Tom wedding"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Highlight"
invideo asset upload <edit-url> ./wedding/*
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> --max-credits <price>
invideo media audio.transcript <sequence-url>
invideo media audio.content <sequence-url>
invideo media audio.onsets <sequence-url>
invideo media video.frames <sequence-url> --at 312,318,325 --out ./frames
invideo gen models <project-url> --query "clean the voice in a video"
invideo gen model <project-url> --model clean_voice.clean_video
invideo gen run <page-url> --model clean_voice.clean_video --dry-run \
  -i video=<sequence-url> -i keep_music=true
invideo gen run <page-url> --model clean_voice.clean_video \
  --max-credits <price> --idempotency-key vows-clean-1 \
  -i video=<sequence-url> -i keep_music=true
invideo edit show <edit-url>
invideo branch new <edit-url> --name round-1 --token <state_token>
invideo edit show <branch-url>
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @ops.json
invideo edit capture <branch-url> --at 10,60,120,230 --out ./frames
invideo edit export <branch-url> --format video --quality 1080 \
  --target-lufs -14 --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 `invideo asset upload` returns for each clip. The third `audio.transcript` line is the call again after `retry_after_s`.
- `<page-url>` is a notebook page; `invideo notebook show <project-url>` lists them. Each `<price>` is the `.estimated_credits` of the dry run before it.
- `<state_token>` comes from `invideo edit show <edit-url>` for `branch new`, and from `invideo edit show <branch-url>` for every command on the branch; the main token is stale there. `<branch-url>` is the `.branch_url` that `branch new` returns.
- `ops.json` holds a bare list of operations, like the `operations` list in the call below.
- `<card-url>` is `.sequences[0]` of the export result. `invideo status` waits and saves nothing. `invideo notebook show` saves the file as `./out/export.mp4`.

The key MCP call is the full call. It places the vows from one guest clip with its sound, and the kiss from another. Source times are seconds from the transcript. `<branch-url>` is the `branch_url` that `timeline_history` returns. The `<state_token>` and the bin ids, like `m3`, come from `get_timeline`.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "place_media", "asset": "m3", "track": "V1", "at_f": 0,
      "source_start_seconds": 312.4, "source_end_seconds": 341.0,
      "mode": "append", "linked_audio": true },
    { "op": "place_media", "asset": "m7", "track": "V1", "at_f": 0,
      "source_start_seconds": 88.2, "source_end_seconds": 94.5,
      "mode": "append", "linked_audio": true }
  ]
}
```

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

- **Costs credits:** `audio.transcript` on each clip, `clean_voice.clean_video` on a noisy clip, and paid stock music. The agent transcribes only the clips with speech you want.
- **Free:** uploads, every cut, the branches and the export.
- **Tool ops:** `audio.content`, `audio.onsets`, `video.sceneSplit`, `video.frames`, `audio.loudness` and `audio.clean`. The dry run shows its price before anything starts.

Uploads take as long as your connection needs. Transcripts take a few minutes. The first cut takes from a few minutes to under an hour, by the number of clips. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are uploads, quiet speeches, or wind noise on a phone mic.

| 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. |
| A direct link download is refused | Use `start_upload` and `add_media` with the `upload_id`. Large files and private drives go that way. |
| The transcript call returns a status, not words | It is still running. Call it again after `retry_after_s`. Only the first call spends credits. |
| An upload breaks | The agent starts a new `start_upload` for that file only. |
| A speech is too quiet | Raise it with `set_audio_gain` on its audio clip, and add the `compressor` audio effect. |
| Wind or crowd noise over the vows | Run `media` `audio.clean` on that clip, priced first. The original stays. |
| A guest clip is sideways | The agent turns it with `set_rotation` and fills the frame. |
| CLI exit 7 | Nothing ran. Run the same command again. |
| Avoid: transcribing every clip | Instead: run `audio.content` first, and transcribe only clips with speech. |
| Avoid: changing the approved cut in place | Instead: a new branch for each round from `timeline_history`. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a 60 second vertical wedding teaser for Instagram from the
highlight branch. The kiss, the first dance and the loudest cheer,
cut on the beat.
```

```text
Make a 20 minute wedding film from ./wedding. Full vows, full speeches
from the best man and the bride's mother, and the first dance. Name
each speaker on screen.
```

```text
Round 3: cut the best man's speech to his three best lines, add more
of Grandma dancing, and keep the rest as it is. New branch.
```

## When to use something else

invideo does not sync many cameras into one multicam edit. For a full ceremony from several pro cameras, use a desktop editor with multicam, like Premiere Pro or DaVinci Resolve. Your agent can export the cut as a project file for that editor with `export` and `format` `premiere`, `davinci` or `final_cut`.

For a shared album where guests upload their own clips, use a photo sharing app. Then download the folder and bring it in.

## Related

- [Make a sports highlight reel, including college recruiting videos](/how-to/personal/sports-highlight-reel)
- [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow)
- [Add word-by-word captions](/how-to/creators/word-by-word-captions)
- [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut)
- [Know the cost before you spend](/how-to/cost-before-you-spend)