---
title: Finish an AI clip from Higgsfield, Runway or Magnific
description: Turn an AI-generated clip into a finished video: cuts, captions or subtitles, music, sound effects, text, an upscale and an MP4 export.
---
You get a finished video from a clip you made in Higgsfield, Runway, Magnific or any other AI video tool. The raw clip gets cuts, sound effects matched to the picture, music, captions or subtitles if someone speaks, your text, and a sharper upscale when you need one. You download an MP4 you can post.

Use invideo for this when the generator gave you a silent or rough clip: your agent adds the sound, the words and the cuts on an editable timeline, and you change any of it after without making the clip again.

Finishing your own AI clips is ordinary video work, and the agent does it. You choose where the video goes and you post it. The agent never publishes it.

## Quickest path

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

```text
Finish my Runway clip ./city-night.mp4. Cut the first second where it
warps, add sound effects that match the picture, a low synth music bed,
and the title "Neon Hours" for 2 seconds. Vertical 9:16. Tell me the
price before you generate any sound.
```

In a chat app, you drag the MP4 into the project in invideo, or paste the clip's public link. In a terminal, you name the file and the agent uploads it.

## What you need

Download the clip from the generator first, at its best quality.

- **The clip.** An MP4 or MOV from Higgsfield, Runway, Magnific or another tool. Several clips work too.
- **The shape.** The clip's own shape, or 9:16, 1:1 or 16:9 for the platform.
- **The sound you want.** Sound effects matched to the picture, music, a voice, or the clip's own sound.
- **The words.** A title, a caption style, or a call to action.
- **The size.** 1080p for social. For 4K, the agent exports at 1080p, then upscales the file.

## Steps

The agent looks at and listens to the clip before it edits.

<Steps>
<Step title="Bring the clip in">
The agent makes a project with `new_project`, a timeline with `new_timeline`, and a branch with `timeline_history`. It uploads the clip with `start_upload` and `add_media`, or passes a public link as `media_url`. Expected result: a sequence URL for the clip.
</Step>
<Step title="Look at it and listen to it">
The agent runs `media` `metadata` for the size, the length and whether there is sound. It runs `video.frames` to see the shots, and `audio.content` to find speech, music or silence. Expected result: a note of the bad frames to cut and whether anyone speaks.
</Step>
<Step title="Cut the bad frames">
The agent places the clip with `place_media`, then cuts warped or broken frames with `split_clip` and `delete_clip`. For several clips, it splits each one with `media` `video.sceneSplit` first. Expected result: only the frames you want, in order.
</Step>
<Step title="Add captions if someone speaks">
If `audio.content` shows speech, the agent prices `audio.transcript` on the clip's sequence URL with `dry_run`, starts it with `max_credits` set to the price it told you, and calls again after `retry_after_s` for the words. Then it adds captions with `add_captions`, one slide per line and the words with their times. Expected result: captions that follow the speech.
</Step>
<Step title="Add sound and music">
For sound effects matched to the picture, the agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `mmaudio_v2.mmaudio_v2_video_to_audio`. It calls `generate` with `dry_run: true`, the clip's sequence URL as `video` and a `prompt` for the sound, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It reads the new sequence URL with `read`, places that clip with its new sound in place of the silent one, adds music from `search_library` in `stock_music`, and sets the levels with `set_audio_gain`. Expected result: a sequence URL for the clip with sound, and music under it.
</Step>
<Step title="Add text and set the shape">
The agent adds the title and any call to action with `add_text`. For a new shape, it sets the timeline size with `set_timeline_settings` and fills the frame with `fill_frame`. Expected result: text on screen and the shape you asked for.
</Step>
<Step title="Check, export and upscale">
The agent runs `capture` at each cut and each text, and `check_timeline`. It runs `export` with `format` video, which stops at 1080p. For a sharper or 4K copy, it runs `media` `video.upscale` on the export card's URL, `dry_run` first, then with `max_credits` and an `idempotency_key`. The card is a sequence, so no re-upload is needed. Expected result: an export card with status `completed`, and an upscaled sequence if you asked for one.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Neon Hours"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Neon 9x16" --width 1080 --height 1920
invideo asset upload <edit-url> ./city-night.mp4
invideo media metadata <sequence-url>
invideo media audio.content <sequence-url>
invideo media video.frames <sequence-url> --at 0,0.5,1,3,6
invideo gen models <project-url> --query "sound effects for a video clip"
invideo gen model <project-url> --model mmaudio_v2.mmaudio_v2_video_to_audio
invideo gen run <page-url> \
  --model mmaudio_v2.mmaudio_v2_video_to_audio \
  --dry-run -i video=<sequence-url> -i prompt="rain, distant traffic, neon hum"
invideo gen run <page-url> \
  --model mmaudio_v2.mmaudio_v2_video_to_audio \
  --max-credits <price> --idempotency-key neon-sound-v1 \
  -i video=<sequence-url> -i prompt="rain, distant traffic, neon hum"
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name finish-v1 --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @finish.json
invideo edit capture <branch-url> --at 0.5,2,5,8 --out ./frames
invideo edit check <branch-url>
invideo edit export <branch-url> --format video --quality 1080 --json
invideo status <card-url> --wait
invideo media video.upscale <card-url> --dry-run
invideo notebook show <card-url> --out ./out
```

Where the values come from:

- `<project-url>` comes from `invideo project new`, and `<edit-url>` from `invideo edit new`. `<name>` is the name you choose in `invideo agent register`. `<page-url>` is a notebook page from `invideo notebook show <project-url>`.
- `<sequence-url>` is the clip's URL from `invideo asset upload`. `<price>` is the dry run's `.estimated_credits`.
- `<state_token>` comes from `invideo edit show <edit-url>`, and on the branch from `invideo edit show <branch-url>`; the main token is stale there. `<branch-url>` is the `.branch_url` that `invideo branch new` returns.
- `<card-url>` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves the file as `./out/export.mp4`.
- The file `./finish.json` holds a bare list of operations: the `operations` list of the MCP call below.

The upscale's paid run adds `--max-credits` with its dry run price and an `--idempotency-key`. The key MCP call cuts the warped first second and adds the title. `<branch-url>` is the branch's URL from `timeline_history`, and `<state_token>` comes from `get_timeline`. At 30 frames a second, frame 30 is the one second mark.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "split_clip", "clip": "c1", "at_f": 30 },
    { "op": "delete_clip", "clip": "c1", "mode": "close_gap",
      "linked": true },
    { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 60,
      "text": "Neon Hours",
      "style": { "font_size": 96, "align": "center", "color": "#ffffff",
                 "shadow": true } }
  ]
}
```

After `split_clip`, the left half keeps the id `c1` and the right half is a new clip, so `delete_clip` on `c1` removes the first second.

## 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 looks and sound reads, the cuts, captions you place, text and the export.
- **Costs credits:** the transcript, generated sound and music, stock music, a reframe model and the upscale. The upscale charges by each second of the video.

Finishing one clip takes a few minutes. Generated sound and an upscale add the time those models take. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are a clip with no sound stream, or a warp the agent missed.

| 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. |
| You want a generated music bed | Make it with `elevenlabs_music_v2_5_instrumental` the same way as the sound: `find_models`, `get_model`, a dry run, then `generate` with `max_credits` and an `idempotency_key`. |
| A crop to the new shape loses too much | Generate fill with `ltx_2_3_pro.reframe` the same way, with the shot's sequence URL as `video` and the new `aspect_ratio`. |
| The clip has no audio at all | That is normal for many generators. Add sound with `mmaudio_v2.mmaudio_v2_video_to_audio` or music. |
| `audio.transcript` returns no words | No one speaks. Skip captions, or add a voice with `elevenlabs_text_to_speech.elevenlabs_tts_v4`. |
| A warp shows mid-clip | Look at more frames with `media` `video.frames`, then cut it with `split_clip` and `delete_clip`. |
| `add_media` from a link is refused | The link must be public. Download the file and upload it with `start_upload`. |
| The upscale looks waxy on faces | Try another model from the `video.upscale` list, such as `topaz_proteus_natural`. |
| `timeout` on a generation | Do not generate again. `read` the thread URL or call `status`. |
| CLI exit 3 on the branch | The token is from main. Run `invideo edit show <branch-url>` and use its `state_token`. |
| The `./out` folder is empty after `status` | `status` waits and does not download. Run `invideo notebook show <card-url> --out ./out`. |
| Avoid: the agent edits the clip without looking | Instead: it reads frames and sound with `media` first. |

## Prompts to try

Each prompt is a real variation of the job.

```text
I have 6 Higgsfield clips in ./shots. Put them in order, cut each to
its best 2 seconds on the beat of an upbeat track, and add a logo end card.
```

```text
My Magnific clip has a person talking. Add word-by-word captions in
yellow, keep the original sound, and export 1:1 and 9:16.
```

```text
Upscale my finished Runway video to 4K and tell me the price first.
```

## When to use something else

To change what happens inside a shot, go back to the generator and make a new take. invideo edits, sounds and finishes the clip you have.

For the tools' own steps, see [Use Higgsfield with invideo](/integrations/higgsfield), [Use Runway with invideo](/integrations/runway) and [Use Magnific with invideo](/integrations/magnific).

## Related

- [Use Higgsfield with invideo](/integrations/higgsfield)
- [Use Runway with invideo](/integrations/runway)
- [Use Magnific with invideo](/integrations/magnific)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)
- [Add word-by-word captions](/how-to/creators/word-by-word-captions)
- [Check your video before you say it is done](/how-to/check-your-video)