---
title: Make a book trailer or a game trailer
description: A book trailer from generated scenes, text and music, or a game trailer cut from your gameplay's best moments, with title cards.
---
You get a trailer, also called a teaser or promo video, for a book or a game. A book trailer shows scenes from your story as generated shots, with short lines of text, music and a voice. A game trailer cuts your captured gameplay down to its best moments, with title cards and a hit on every cut.

Use invideo for this when you want a trailer you can keep changing: every shot, line and cut sits on a timeline, so a new tagline or a new build means a small edit, not a new video.

## Quickest path

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

```text
Make a book trailer for my fantasy novel. Read ./blurb.md, pick four
scenes, generate a shot for each, and put three short lines of text
between them. Dark orchestral music, a deep voice for the last line,
and the cover at the end. 16:9. Show me each shot before you use it.
```

```text
Make a game trailer from my gameplay in ./captures. Find the best
fights and the big moments, cut them on the music, and add title cards
with the game's name and "Wishlist on Steam". 16:9.
```

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

## What you need

The book trailer and the game trailer need different inputs.

- **For a book.** The blurb, three to five scenes in a sentence each, the cover image, and the look (dark, cozy, cinematic).
- **For a game.** Your gameplay recordings, the game's logo, and the store you send people to.
- **The text.** Short lines for the cards: a hook, a tagline, the title, the call to action.
- **The music.** A mood, a track from stock music, or your own file if you have the rights.
- **The shape.** 16:9 for YouTube and store pages, 9:16 for a Shorts version.

## Steps

Step 1 and step 2 are for a book. Step 3 is for a game. The rest are for both. Your agent edits on a branch and tells you what changed at each step.

<Steps>
<Step title="Write the shot list for a book">
The agent reads your blurb and writes one prompt per scene: the place, the light, the motion of the camera. It saves the list as a brief with `new_brief`, then adds the scenes with `write`, so you can change them. Expected result: a brief URL with one note per scene.
</Step>
<Step title="Generate the book shots">
The agent runs `find_models` with `output` video and the job in words, like "cinematic scene from a prompt", and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`. It takes a `prompt` and, to keep a character the same in every shot, the cover or a character image in `reference_images`. For a shot that must start on the cover, `seedance_2_5.frames` takes it as `first_frame`. For each scene, the agent calls `generate` with `dry_run: true`, the scene prompt, `aspect_ratio` 16:9 and a `duration`, 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` per scene, and names each take with `rename`. Expected result: a sequence URL per take, which the agent reads with `read`. You pick the takes to use.
</Step>
<Step title="Bring in the gameplay and find the best moments">
For each big recording, the agent calls `start_upload`, sends the bytes, then calls `add_media` with the `upload_id`. The agent runs `media` with `audio.onsets` and `audio.content` on each recording to find the loud spans: shots, explosions, a crowd. It runs `video.sceneSplit` to find the cuts, and looks at each span with `video.frames`. Expected result: a list of moments, in seconds.
</Step>
<Step title="Cut the trailer on the music">
The agent makes a 16:9 timeline with `new_timeline` and a branch with `timeline_history`. It adds the music, reads its beats with `audio.beats`, and places each shot or moment with `place_media` so the cuts land on beats. It adds a hit with `add_transition` and type `impact` or `flash` at the big cuts. Expected result: a cut that moves with the music.
</Step>
<Step title="Add the text and title cards">
The agent adds each line with `add_text` and fades it in and out with `set_keyframes` on `opacity`. At the end, it places the cover or the logo and the call to action. Expected result: readable cards between the shots.
</Step>
<Step title="Add the voice and the sound">
The agent runs `find_models` with "voice line" and with "sound effect", and reads each pick with `get_model`. Good picks are `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a `voice_id` from `search_library`, and `elevenlabs_sfx`, with a `prompt` and a `duration` within the range `get_model` gives. Your agent can search for others with `find_models`. Each one gets a `generate` with `dry_run: true`, and the agent 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`. It reads each sequence URL with `read` and places the sound. It puts `ducker` on the music track with `add_audio_effect`; a new timeline ducks under `A1` by default. Expected result: a sequence URL for each sound, and the voice clear over the music.
</Step>
<Step title="Check, then export">
The agent runs `capture` at each card and a few shots, `check_timeline`, and `audio.loudness` on the music and voice. Then it runs `export` with `format` video. Expected result: an export card with status `completed`.
</Step>
</Steps>

The same job from a terminal, for a game trailer:

```bash
invideo project new --title "Starfall trailer"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Trailer v1"
invideo asset upload <edit-url> ./captures/*.mp4
invideo media audio.onsets <sequence-url>
invideo media audio.content <sequence-url>
invideo media video.sceneSplit <sequence-url> --dry-run
invideo media video.frames <sequence-url> --at 42,43.5,45 --out ./look
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name trailer-v1 --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 \
  --token <state_token> --operations @ops.json
invideo edit capture <branch-url> --at 0,8,20,58 --out ./frames
invideo edit check <branch-url>
invideo edit export <branch-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` that `invideo asset upload <edit-url>` returns for each recording, a `…/notebook/seq-N.M` URL.
- `<state_token>` comes from `invideo edit show <edit-url>` for the branch command. `<branch-url>` is the `.branch_url` that `invideo branch new` returns. For `edit change`, `<state_token>` is read again with `invideo edit show <branch-url>`.
- `@ops.json` reads a bare JSON list of ops, the `operations` list of the call below.
- `<card-url>` is `.sequences[0]` of the export result. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it.

For a book trailer, the shots are generated. Find and read the model, price one scene, then run it with the price as the cap:

```bash
invideo gen models <project-url> --query "cinematic scene from a prompt"
invideo gen model <project-url> --model seedance_2_5.r2v
invideo gen run <page-url> --model seedance_2_5.r2v --dry-run \
  -i prompt="slow push through a foggy harbor at dawn" \
  -i aspect_ratio=16:9 -i duration=6
invideo gen run <page-url> --model seedance_2_5.r2v \
  --max-credits <price> --idempotency-key scene-1 \
  -i prompt="slow push through a foggy harbor at dawn" \
  -i aspect_ratio=16:9 -i duration=6
invideo status <thread-url> --wait
```

`<page-url>` is a notebook page of the project, listed by `invideo notebook show <project-url>`. `<price>` is the dry run's `.estimated_credits`. `<thread-url>` is the `url` the paid run returns.

The key MCP call, in full, places a moment on a beat, adds a hit, and adds a title card. `<branch-url>` is the branch URL that `timeline_history` returns, and `<state_token>` comes from `get_timeline` on it. `<sequence-url>` is the sequence URL that `add_media` returns for the recording. `c3` and `c4` are the clip ids on each side of the cut, from `get_timeline`. The fight starts 42 seconds into the recording. It goes on the timeline at frame 96, a beat at 3.2 seconds at 30 fps.

```json
{
  "url": "<branch-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "place_media", "asset": "<sequence-url>",
      "track": "V1", "at_f": 96, "source_start_seconds": 42,
      "source_end_seconds": 45.5, "mode": "overwrite",
      "linked_audio": true },
    { "op": "add_transition", "left_clip": "c3", "right_clip": "c4",
      "type": "impact", "in_f": 4, "out_f": 4 },
    { "op": "add_text", "track": "V2", "start_f": 300, "end_f": 360,
      "text": "Wishlist on Steam",
      "style": { "font_size": 88, "align": "center", "shadow": 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:** the shots from `seedance_2_5.r2v` for a book, the voice from `elevenlabs_text_to_speech.elevenlabs_tts_v4`, sounds from `elevenlabs_sfx`, and paid stock music.
- **Tool ops:** `audio.onsets`, `audio.content`, `audio.beats`, `audio.loudness`, `video.sceneSplit`, `video.frames`. The dry run shows its price before anything starts.
- **Free:** uploads, the cuts, the text and the export.

A game trailer from your own footage takes the agent a few minutes. A book trailer takes longer, because each shot is generated and you pick the takes. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems come from shots that do not match each other, or gameplay with no sound to read.

| 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. |
| `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show <card-url> --out <dir>`. |
| The hero looks different in each shot | Generate with a reference image and `seedance_2_5.r2v`, and keep the same words for the character in every prompt. |
| A shot has text or a logo in it | Generate it again with "no text" in the prompt, or cover it with a card. |
| The recording has no sound | `audio.onsets` finds nothing. The agent picks moments from `video.frames` and `video.sceneSplit`, and you check them. |
| An upload by link fails | Upload the file with `start_upload` instead of a link. |
| `generate` returns status `held` | A safety review. It is not over. `read` the URL again later. |
| CLI exit 5 | A limit on credits or quota. Check the balance before more shots. |
| Avoid: calling `generate` again to check on a shot | Instead: `read` the thread URL, or call `status`. |
| Avoid: using every take | Instead: you pick the takes. The agent marks them with `mark_sequence` only when you agree. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a 9:16 book trailer for TikTok from my thriller. Three fast shots,
one line of text each, a heartbeat sound, and the cover at the end.
```

```text
Cut a short teaser from my game's boss fight in ./boss.mp4. Slow
motion on the last hit, a glitch on the cuts, and the logo at the end.
```

```text
My recordings have no sound. Find the action by looking at the frames,
cut them to this track, ./theme.mp3, and show me the moments first.
```

## When to use something else

invideo does not record gameplay. Capture it with OBS Studio, the Xbox Game Bar, or your console's capture. Store pages like Steam have their own trailer rules. Read them before you export.

For a book cover itself, work with a designer, or ask your agent to generate one with a model it finds with `find_models`. The trailer uses the cover you bring.

## Related

- [Make a gaming montage from your clips](/how-to/creators/gaming-montage)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)
- [Make an intro, welcome video, outro or logo animation for your channel or business](/how-to/creators/intro-outro-logo-animation)
- [Make a thumbnail for the video](/how-to/creators/thumbnail)
- [Models](/reference/models)