---
title: Edit a podcast episode and pull clips from it
description: Your podcast episode edited, with dead air and rough sound fixed, plus vertical clips with captions of the best moments, all on one timeline.
---
You get a cleaned-up podcast episode and a set of short clips, also called podcast clips, highlights or audiograms. Long pauses, false starts and "um" moments come out of the episode. The best moments become vertical clips with captions for Reels, Shorts and TikTok.

Use invideo for this when you want every cut to stay editable: your agent reads the transcript, makes the cuts on a timeline, and you can undo or move any cut after.

## Quickest path

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

```text
Edit my podcast episode in ./episode-42. There are two speakers.
Cut the long pauses and the false starts, clean my mic, then find the
five best moments and make each one a vertical clip with captions.
Work on a branch and show me the moments before you export.
```

In a chat app, you drag the episode files 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

One recording per camera or mic is fine. The agent lines them up on the timeline.

- **The episode.** A video file (MP4 or MOV) or an audio file (WAV or MP3). Separate files per speaker also work.
- **The speaker names.** So the agent can tell you who said what.
- **What makes a good moment.** A strong opinion, a story, a laugh, a tip. Name the topics you want, or let the agent pick.
- **The shape of the clips.** 9:16 for Reels, Shorts and TikTok, 1:1 for a feed. The full episode stays 16:9.
- **Your caption style.** Font, color, and where the words sit.

## Steps

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

### Edit the episode

The agent cleans up the full episode first.

<Steps>
<Step title="Bring in the episode">
The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. For a big local file, it calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id` and the timeline URL. Expected result: a sequence URL and a media bin id for each file.
</Step>
<Step title="Get the transcript">
The agent runs `media` with `audio.transcript` on the episode's sequence URL from `add_media`, with `dry_run` first, and tells you the price. For a price of 1 credit or more it waits for your yes. Then it starts the transcript with `max_credits` set to that price, and calls again after `retry_after_s` for the words. Expected result: every word with its time and its speaker.
</Step>
<Step title="Find the silence">
The agent runs `media` with `audio.content`. It returns spans of speech, music, effects and silence, and turns each silent span into frames: seconds times the frame rate. Expected result: a list of silent spans.
</Step>
<Step title="Cut the dead air and false starts">
The agent removes each long pause with `edit_time_range` and mode `close_gap`, so every track moves together. For a false start, it reads the transcript, then cuts with `split_clip` and `delete_clip`. It sends all the cuts in one `edit_timeline` call. Expected result: a new `state_token` and a shorter episode.
</Step>
<Step title="Clean a rough mic">
For a mic with hum or room echo, the agent runs `media` with `audio.clean` on that file's sequence URL, with `dry_run` first, then with `max_credits` and an `idempotency_key`. The `model` is `clean_voice.clean_audio`, or `clean_voice.clean_video` for a video file. This makes a new, cleaned file. The original stays. The agent places the clean file on its own track and mutes the old one with `set_audio_muted`, so you can compare. Expected result: a new sequence with the cleaned voice.
</Step>
</Steps>

### Pull the clips

Then the agent cuts vertical clips from the edited episode.

<Steps>
<Step title="Pick the moments">
The agent reads the transcript and picks the moments that stand on their own: a clear start, one idea, a strong last line. It marks each one with `add_marker` and a note, and tells you the timecodes. Expected result: markers on the timeline. You approve or change the list.
</Step>
<Step title="Make each clip vertical with captions">
For each moment, the agent copies the timeline with `duplicate_timeline`. On the copy, it sets the shape to 9:16 with `set_timeline_settings`, keeps only the moment with `edit_time_range`, and fills the frame with `fill_frame`. It adds the words with `add_captions`, with slides and word times from the transcript. Expected result: one timeline per clip, each with its own `timeline_id`.
</Step>
<Step title="Check each clip before export">
The agent runs `capture` on each clip at the start, the middle and the end, and `check_timeline`. Expected result: the speaker's face in frame and the captions above the app buttons.
</Step>
<Step title="Export the episode and the clips">
The agent runs `export` with the `timeline_id` of the episode and of each clip. Expected result: one export card per timeline, each with status `completed`.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Episode 42"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Episode 42 edit"
invideo asset upload <edit-url> ./episode-42/*
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name episode-cut --token <state_token>
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> --max-credits <price>
invideo media audio.content <sequence-url>
invideo media audio.clean <sequence-url> --model clean_voice.clean_audio \
  --dry-run
invideo media audio.clean <sequence-url> --model clean_voice.clean_audio \
  --max-credits <price> --idempotency-key ep42-clean
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 \
  --token <state_token> --operations @cuts.json
invideo edit capture <branch-url> --timeline T2 \
  --at 0,15,29 --out ./frames
invideo edit check <branch-url>
invideo edit export <branch-url> --format video --quality 1080 \
  --timeline T2 --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./clips/clip-1
```

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 <edit-url>` returns for each file, a `…/notebook/seq-N.M` URL. A transcript and a clean refuse a bin `--asset`.
- `<price>` is each dry run's `.estimated_credits`.
- `<state_token>` comes from `invideo edit show`: on `<edit-url>` for the branch, then on `<branch-url>` for the cuts. The main token is stale on the branch. `<branch-url>` is the `.branch_url` that `invideo branch new` returns.
- `@cuts.json` reads a bare JSON list of ops, the `operations` list of the call below.
- `T2` is the first clip's timeline id, which `invideo edit show <branch-url>` lists after `duplicate_timeline`. Each clip has its own id.
- `<card-url>` is `.sequences[0]` of each export result. `invideo status` waits but saves nothing. `invideo notebook show` saves each clip in its own folder, like `./clips/clip-1/export.mp4`, and the agent renames it.

The key MCP call, shown as the full call, cuts two pauses on every track and marks a moment. `<branch-url>` is the branch URL `timeline_history` returns, and `<state_token>` comes from `get_timeline` on it. At 30 fps, 61.2 seconds is frame 1836.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "edit_time_range", "timeline": "T1",
      "start_f": 3690, "end_f": 3780, "mode": "close_gap" },
    { "op": "edit_time_range", "timeline": "T1",
      "start_f": 1836, "end_f": 1911, "mode": "close_gap" },
    { "op": "add_marker", "at_f": 5400, "duration_f": 900,
      "name": "Clip 1", "note": "The pricing story, ends on the laugh" }
  ]
}
```

The agent sends the later cut first. Then the earlier cut does not move the frames of the later one.

## 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:** the transcript with `audio.transcript`, and the cleaned voice with `audio.clean`.
- **Free:** uploads, the cuts, the markers, the captions, frame checks and every export.
- **Tool ops:** `audio.content`. The dry run shows its price before anything starts.

The transcript of a long episode takes a few minutes. The cuts and the clips take the agent a few minutes more. Picking the moments with you takes the longest. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems come from cuts that land mid-word, or a clip that starts without context.

| 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` or `audio.clean` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the file'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>`. |
| A cut clips the first or last word | Move the cut a few frames out with `trim_clip`, then listen again. |
| The transcript call returns status running | Call `audio.transcript` again with the same file after `retry_after_s`. Only the first call costs credits. |
| Two speakers have the same label | Tell the agent who speaks first. It renames the speakers in its notes. |
| `edit_timeline` refused with an old token | Someone edited first. Read with `get_timeline`, then rebuild the ops. |
| CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild. |
| CLI exit 5 | A limit on credits or quota. Check the balance before the transcript. |
| The face is cut off in the vertical clip | Move the picture with `set_position`, then `capture` again. |
| Avoid: deleting the original noisy track | Instead: mute it with `set_audio_muted`. The clean file is a new file, and the original stays. |
| Avoid: editing main | Instead: work on a branch from `timeline_history`, and you accept the change. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Cut every pause longer than a breath from this interview, keep the
laughs, and give me a clean episode plus an audio-only export.
```

```text
Find three moments where my guest tells a story. Make each a 9:16 clip
with word-by-word captions and the guest's name at the top.
```

```text
My mic has a hum. Clean only my track, keep the guest's track as it is,
and let me hear both before you mute the old one.
```

## When to use something else

invideo does not publish to podcast hosts like Spotify for Podcasters or Apple Podcasts. Export the audio with `export` mode `audio`, then upload it to your host.

For a live show with many cameras switched on the fly, record in a tool built for live switching, like OBS Studio or Riverside. Then bring the recordings in for the edit.

## Related

- [Cut ums, pauses and retakes, as reversible timeline edits](/how-to/creators/cut-ums-and-retakes)
- [Add word-by-word captions](/how-to/creators/word-by-word-captions)
- [Make Reels and Shorts from your footage: hook, captions, transitions, sound effects](/how-to/creators/reels-and-shorts-from-your-footage)
- [Repurpose one video for every platform](/how-to/creators/repurpose-for-every-platform)
- [Check your video before you say it is done](/how-to/check-your-video)