---
title: Make a sports highlight reel, including college recruiting videos
description: A sports highlight reel or college recruiting video from game footage: the best plays found by sound and by eye, a player spotlight, stats on screen and slow-motion replays.
---
You get a sports highlight reel, also called a highlight tape or a recruiting video, from your game footage. Your agent finds the big moments by the crowd, the whistle and the commentator, checks each one by eye, and cuts the best plays first. The reel opens with a title card of the player's name, position, jersey number, class year and stats, marks the player at the start of each play, and replays the best play in slow motion.

Use invideo for this when you have hours of game film and want the plays pulled for you: your agent reads the sound and the frames of every file, and you can reorder or swap any play on the timeline after.

## Quickest path

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

```text
Make a 3 minute recruiting video for my son Marcus Lee, #23, point
guard, class of 2028, from the game films in ./games. Best plays first.
Open with his name, position, number, height and stats, circle him at
the start of each play, and replay the best dunk in slow motion. 16:9.
Show me the plays you picked before you cut.
```

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

Coaches watch the first plays most, so know the best ones if you can.

- **Game footage.** MP4 or MOV from a phone, a camera or a team video service, full games or clips.
- **The player.** Name, jersey number, team colors, and where they are at the start of a play if the film is wide.
- **The title card facts.** Position, class year, height and weight, school, stats, GPA, contact email.
- **The plays you know are good.** A game and a rough time, if you have them.
- **The shape.** 16:9 for recruiting sites and YouTube, 9:16 for a social cut.

## Steps

Your agent edits on a branch and shows you its picks before it cuts.

<Steps>
<Step title="Upload the films">
The agent makes a project with `new_project` and uploads each file with `start_upload` and `add_media`. Large game files go this way. Expected result: a sequence URL per game.
</Step>
<Step title="Find the loud moments">
The agent runs `media` `audio.content` on each game for speech, music, effects and silence spans, and `audio.onsets` for whistles, buzzers and crowd spikes. Expected result: a list of candidate times in seconds.
</Step>
<Step title="Read the commentator, if there is one">
With a commentator or a PA announcer, the agent prices `media` `audio.transcript` with `dry_run` 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. It searches them for the player's name and calls like "three", "dunk" or "goal". Expected result: times where the player is named.
</Step>
<Step title="Split and look at each play">
The agent runs `media` `video.sceneSplit` on edited footage to find the cuts. It runs `video.frames` around each candidate time and looks for the player's number in the play. Expected result: a shot list with game, start and end, best first. The agent shows it to you before it cuts.
</Step>
<Step title="Cut the reel">
The agent makes a timeline with `new_timeline`, creates a branch with `timeline_history`, and places each play with `place_media` in `mode` append. It adds a title card with `add_text`: name, position, number, class year and stats. Expected result: the plays in order after the title card.
</Step>
<Step title="Mark the player and add the replay">
At the start of each play, the agent adds a ring around the player with `add_shape`, preset ellipse with a stroke and no fill, for about a second. For the best play, it copies the clip with `duplicate_clip` and slows the copy with `retime` `kind` section. Expected result: you can find the player at a glance, and the replay plays slow.
</Step>
<Step title="Check and export">
The agent runs `capture` at the title card, at each ring and in the replay, and `check_timeline`, and looks for the ring on the right player and readable text. Then it runs `export` with `format` video and reads the card. 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>

The same job from a terminal:

```bash
invideo project new --title "Marcus Lee recruiting"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Recruiting reel"
invideo asset upload <edit-url> ./games/*.mp4
invideo media audio.content <sequence-url>
invideo media audio.onsets <sequence-url>
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> --max-credits <price>
invideo media video.sceneSplit <sequence-url> --dry-run
invideo media video.sceneSplit <sequence-url> \
  --max-credits <price> --idempotency-key game1-scenes
invideo media video.frames <sequence-url> --at 1204,1206,1208 \
  --out ./frames
invideo edit show <edit-url>
invideo edit change <edit-url> --timeline T1 --token <state_token> \
  --operations @ops.json
invideo edit capture <edit-url> --at 2,12,30,95 --out ./frames
invideo edit export <edit-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 `invideo asset upload` returns for each game. The transcript and `video.sceneSplit` take that URL, not a media bin id.
- `<price>` is the `credits` value of the dry run before it. Run the transcript only on a game with a commentator.
- `<state_token>` comes from `invideo edit show`. `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 one play, rings the player, and adds the title card. The ring's `x` and `y` are pixels from the center of the canvas. `<branch-url>` is the `branch_url` that `timeline_history` returns. The `<state_token>` and the bin ids, like `m2`, come from `get_timeline`.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "add_text", "track": "V2", "start_f": 0, "end_f": 150,
      "text": "Marcus Lee  #23\nPoint guard, class of 2028\n18.4 PPG, 6.1 AST",
      "style": { "font_size": 64, "align": "center",
                 "background_color": "#000000aa" } },
    { "op": "place_media", "asset": "m2", "track": "V1", "at_f": 150,
      "source_start_seconds": 1203.5, "source_end_seconds": 1211.0,
      "mode": "append", "linked_audio": true },
    { "op": "add_shape", "track": "V3", "at_f": 150, "duration_f": 30,
      "preset": "ellipse", "width": 160, "height": 160,
      "x": 220, "y": 140, "fill": "#00000000",
      "stroke": { "color": "#ffd400", "width": 8 } }
  ]
}
```

The slow-motion replay is one more full call. The agent copies the play with `duplicate_clip` on its id, like `c5`, and slows the copy, like `c6`, with `retime`. A clip id made earlier in a call can be used later in the same call. The `<state_token>` is the new one from `get_timeline`:

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "duplicate_clip", "clip": "c5" },
    { "op": "retime", "clip": "c6", "kind": "section",
      "from_f": 900, "to_f": 1050, "speed": 0.5 }
  ]
}
```

## 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:** uploads, every cut, the rings, the replay and the export.
- **Tool ops:** `audio.content`, `audio.onsets`, `video.sceneSplit` and `video.frames`. The dry run shows its price before anything starts.
- **Costs credits:** `audio.transcript` for a commentator, and paid stock music if you add it. Most recruiting videos use no music.

Finding plays takes the agent a few minutes a game. Your review of its picks takes longer, and matters most. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are wrong picks, a wide film where the player is small, or a silent file.

| 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. |
| The film has no sound | The sound reads find nothing. The agent picks plays by `video.frames` alone, or uses the times you give. |
| The agent picked a play by another player | Give it the jersey number and team color. It checks the number in `video.frames` before it cuts. |
| The player is tiny in a wide shot | The agent zooms the play with `set_zoom` and `set_position`, and keeps the ring on the player. |
| The ring is on the wrong spot | Move it with `set_position`, then `capture` again. |
| `retime` refused on the replay | The clip may loop. The agent places it again without the loop. |
| CLI exit 3 | The timeline changed since your read. Run `invideo edit show` and rebuild the ops. |
| Avoid: cutting before you review the picks | Instead: the agent shows you the shot list first. |
| Avoid: the agent transcribes a game with no commentator | Instead: `audio.content` first; transcribe only files with speech. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a 90 second soccer highlight reel for Ana Ruiz, #9, striker, from
./season. Goals first, then assists. A slow-motion replay of each goal.
```

```text
The game film in ./final.mp4 has no sound. Find every play where #14
touches the ball, from the frames, and make a list with times.
```

```text
Make a 30 second vertical version of the reel on a new branch for
Instagram, with the three best plays and his handle at the end.
```

## When to use something else

A ring or arrow placed with `add_shape` sits where the player starts. For a mark that follows the player, the agent runs `object_track` or `sam_3_1_video` on the clip to get a mask that moves with them, then keys a highlight through it with `track_matte_key`. That is a mask, not a sports telestrator; for drawn plays and auto-detected jersey numbers, use a sports video tool.

Recruiting sites and team video services have their own upload pages and rules. Export the MP4 here, then upload it there.

## Related

- [Make a wedding video from guest clips](/how-to/personal/wedding-video)
- [Make a trend edit like CapCut: slow-mo, meme, freeze frame](/how-to/personal/trend-edit)
- [Make a gaming montage from your clips](/how-to/creators/gaming-montage)
- [Know the cost before you spend](/how-to/cost-before-you-spend)
- [Check your video before you say it is done](/how-to/check-your-video)