---
title: Check your video before you say it is done
description: Your agent looks at frames and listens to the sound before it reports done, then exports a video that has no cropped faces or silent clips.
---
Your agent checks the video before it tells you the video is done. It looks at frames of the timeline, listens to the sound of each clip, and checks the timeline's structure. Then it exports. A cut that "should be fine" often has a cropped face, a caption off the edge of a phone, or a clip with no sound.

Use invideo for this when your agent edits on a timeline: it can render the timeline as it looks now and read every source file's sound, for free, before the export.

## Quickest path

Set up your agent first with [invideo for AI agents](/agents). Then add this line to any edit request:

```text
Before you say it is done, capture frames across the timeline, check the
sound of every clip, run check_timeline, and tell me what you found.
```

In a chat app, your agent shows you the frames it captured. In a terminal, it saves them to a folder with `--out`, and you open the folder.

## How it works

Three tools do the checking. None of them changes the timeline. `capture`, `check_timeline` and the `media` reads cost no credits.

- **`capture` looks at the timeline.** It renders frames of the timeline as it looks now, with every layer, effect and text, at the times in seconds you list in `at_seconds`. In the CLI it is `invideo edit capture` with `--at`.
- **`media` looks at and listens to one source file.** `video.frames` gives frames of the file. `metadata` gives its streams and duration. `audio.waveform` gives its levels, `audio.loudness` its integrated loudness, true peak and range, and `audio.content` where its sound is speech, music, effects or silence. `video.contactSheet` makes one image of frames across a video, in a grid.
- **`check_timeline` checks the structure.** It finds problems like a clip that points at something deleted, or a clip that ends before it starts. Each finding says what is wrong and how to fix it. In the CLI it is `invideo edit check`.

`check_timeline` does not judge the edit. A timeline can pass the check and still look wrong. That is why the agent also looks and listens.

The `media` sound reads work on one file, not on the live timeline. The agent checks each clip's source before the export, sets the loudness of the mix with `target_lufs` on `export`, then runs `audio.loudness` on the export card's URL to confirm the final mix. The card is a sequence, so `media` takes it as it is.

## Steps

The agent runs this checklist after the last edit and before the export. It fixes what it finds, then runs the checklist again.

<Steps>
<Step title="Check the structure">
The agent runs `check_timeline` on the timeline URL. It fixes each finding with `edit_timeline`, as the finding says. Expected result: no findings.
</Step>
<Step title="Capture the first and last frame">
The agent runs `capture` at `0` and at one frame before the end. Ranges are half-open, so the end time itself is past the last frame. Expected result: two frames that open and close the video the way you asked, with no black frame and no stray clip.
</Step>
<Step title="Capture frames across the cut">
The agent picks times at each cut, each text, and each caption, and runs `capture` with them. It looks for faces cut off at the edge, heads cut at the top, and text near the frame edge. Expected result: every face in frame.
</Step>
<Step title="Check text at phone size">
The agent looks at each captured frame with text as a person sees it on a phone. Text that is thin, small, or low in contrast fails this check. Expected result: you can read every line at a glance.
</Step>
<Step title="Check that every clip has sound">
The agent runs `media` with `metadata` on each source that should have sound, and checks it has an audio stream. Then it runs `audio.content` to see where the sound is speech, music, effects or silence. Expected result: sound on every clip that needs it, and silence only where you want a pause.
</Step>
<Step title="Check the loudness">
The agent runs `audio.loudness` on the voice and music sources, and `audio.waveform` where it needs the shape of the sound. It compares them with the target loudness for the platform. Expected result: every source in range. For the final mix, the agent sets `target_lufs` on the export to the platform's target.
</Step>
<Step title="Tell you what it found, then export">
The agent tells you what it checked, what it fixed, and what needs your eye, with timecodes and the timeline URL. Then it runs `export`. Expected result: an export card with status `completed`.
</Step>
</Steps>

The same checklist from a terminal:

```bash
invideo edit check <edit-url>
invideo edit capture <edit-url> --at 0,4.5,9,14.9 --out ./frames
invideo media metadata <sequence-url>
invideo media audio.content <sequence-url>
invideo media audio.loudness <sequence-url>
invideo media audio.waveform <sequence-url>
invideo media video.frames <sequence-url> --at 0,2,4 --out ./frames
invideo edit export <edit-url> --format video --quality 1080
```

Where each value comes from: `<edit-url>` from `invideo edit new`, and `<sequence-url>` from the URL `invideo asset upload` or `add_media` returns. For a read of a file in an edit's media bin, like `metadata` or `audio.loudness`, pass the edit's URL and `--asset` with the bin id from `invideo edit show`. Ops that make a file, like `video.contactSheet`, refuse `--asset`; pass the sequence URL.

The key MCP call is `capture`, with frames at the cuts and the last frame. `<edit-url>` is the timeline's URL, from `new_timeline` or `invideo edit new`.

```json
{
  "url": "<edit-url>",
  "at_seconds": [0, 4.5, 9, 14.9]
}
```

To see a whole source video in one image, the agent runs `media` with `video.contactSheet`. It needs all four of `columns`, `rows`, `resolution` and `style`, and `style` is `labeled` or `plain`. It takes the file's sequence URL, and it makes a new image beside the file. It is a tool op; the dry run shows its price before anything starts. Like every op that makes a file, it still takes `dry_run` and `idempotency_key`.

## What to check

This list is the minimum. Add your own checks to the project's rules in `invideo_rules.md`, and your agent reads them before it works.

| Check | Tool | Pass |
| --- | --- | --- |
| Structure | `check_timeline` | No findings |
| First and last frame | `capture` | Opens and closes as asked |
| Faces | `capture` | No face cut at an edge |
| Text | `capture` | Readable on a phone |
| Sound on each clip | `metadata`, `audio.content` | Sound where it is needed |
| Silence | `audio.content` | Silence only where planned |
| Loudness | `audio.loudness`, `audio.waveform` | In range for the platform |

## If something goes wrong

Most problems come from a stale read or from saying done too early.

| Symptom | Fix |
| --- | --- |
| `capture` returns `timeout` | Nothing changed. Run the same `capture` again. |
| `capture` returns `unavailable` | The timeline is starting. Retry the same call in a few seconds. |
| `check_timeline` is refused with an old `expected_state_token` | The timeline changed since that read. Read it again with `get_timeline`, then check again. |
| CLI exit 3 | The edit changed since your read. Run `invideo edit show` again. |
| CLI exit 7 | Nothing ran. Run the same command again. |
| A finding comes back after the fix | Read the timeline again with `get_timeline`, fix it once more, and tell the person if it stays. |
| A face is cropped in a capture | Move or zoom the clip with `set_position` or `set_zoom`, then capture again. |
| Text is hard to read at phone size | Change the text with `set_text_style`, then capture again. |
| A clip is silent | Check that its sound is on the timeline and not muted. |
| The export card status is `failed` | Read the card for the reason, and tell the person. |
| A frame looks wrong after a fix | Capture again. A capture is tied to a revision, so an old capture shows the old edit. |
| The export is too loud or too quiet | Export again with `target_lufs` set to the platform's target. |
| Avoid: saying done after `check_timeline` alone | Instead: capture frames and read the sound too. The check does not judge the edit. |
| Avoid: checking the sound of the export only | Instead: check each source with `media`, so you know which clip to fix. |

## Related

- [Know the cost before you spend](/how-to/cost-before-you-spend)
- [Run invideo in CI and on servers](/how-to/ci-and-servers)
- [Export to Premiere Pro, DaVinci Resolve or Final Cut Pro](/how-to/export-to-premiere-resolve-final-cut)
- [MCP tools reference](/reference/mcp-tools)
- [Export loudness, track volume and peak level](/guides/how-is-export-loudness-different-from-track-volume-and-peak-level)