---
title: Make a training explainer from a document, without an avatar
description: Turn a policy, SOP or handbook page into a narrated explainer video with b-roll, text slides and captions, and no talking avatar.
---
Turn a document into a training explainer video: a policy, an SOP, a handbook chapter, a compliance memo. Your agent reads it, writes a short script, voices it, covers it with stock or generated b-roll and text slides, and adds captions. No avatar and no presenter on camera.

Use invideo for this when you want the script, the voice and every shot on one editable timeline, so a reviewer can ask for a change and the agent fixes that one part.

## Quickest path

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

```text
Read handbook-ch3.pdf and make a short training explainer in invideo.
Write the script first and show it to me. Then voice it with a clear
narrator, add stock b-roll and a text slide for each key rule, and add
captions. No avatar. Show me frames before you export.
```

In a chat app, you attach the document to the chat. In a terminal, the agent reads the file from the folder you name.

## What you need

The document is the source. The rest are choices.

- The document: PDF, DOCX, a web page you saved, or text you paste.
- The length you want, and who watches it.
- A voice style. The agent sends you voice previews from `search_library`.
- Brand colors and a font, if you have them. A font file comes in with `add_media`.
- The shape: 16:9 for an LMS or a meeting screen, 9:16 for phones.

## Steps

The agent writes, you approve, then it spends.

<Steps>
<Step title="Read the document and write the script">
The agent reads the document and writes a script in short scenes, each with one line of narration and one key rule to show. It sees your approval or your changes.
</Step>
<Step title="Voice the script">
1. The agent runs `find_models` with "narration voice", picks one, and reads its inputs with `get_model`. A good pick is `seed_tts_2_0`. Your agent can search for others with `find_models`. It picks a voice with `search_library` in `seed_tts_2_0_voices`, the library for that model.
2. It calls `generate` with the script as `prompt`, the `voice_id` and `dry_run: true`, and tells you the price.
3. 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 gets a thread URL and, when the result lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check.
</Step>
<Step title="Find b-roll">
The agent searches `search_library` in `stock_video` for each scene and sends you the previews. Where stock has nothing that fits, it generates the shot.

1. It runs `find_models` with the shot in words, and reads its pick with `get_model`. A good pick is `seedance_2_5.r2v`. Your agent can search for others with `find_models`.
2. It calls `generate` with a `prompt`, `generate_audio` false and `dry_run: true`, and tells you the price.
3. 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 the shot's sequence URL with `read`.

It sees stock ids and sequence URLs.
</Step>
<Step title="Build the timeline">
The agent makes a timeline with `new_timeline` and a branch with `timeline_history`. It places the voice on an audio track and the b-roll on a video track with `insert_media` or `place_media`, adding stock with `add_media` and `stock`. It sees a new `state_token`.
</Step>
<Step title="Add text slides">
For each key rule, the agent adds a text clip with `add_text` over the b-roll, styled with your font and colors. It sees the text clips in `get_timeline`.
</Step>
<Step title="Add captions">
The agent prices `audio.transcript` with `dry_run` on the voice's sequence URL 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. Then it sends `add_captions`. It sees a caption clip.
</Step>
<Step title="Check, then export">
The agent calls `capture` at each scene change and `check_timeline`, then `export` with format `video`. It sees an export card with status `completed`.
</Step>
</Steps>

The terminal version:

```bash
invideo project new --title "Handbook chapter 3"
invideo library search <project-url> --library stock_video \
  --query "office team meeting"
invideo library search <project-url> --library seed_tts_2_0_voices \
  --query "calm female trainer"
invideo gen models <project-url> --query "narration voice"
invideo gen model <project-url> --model seed_tts_2_0
invideo gen run <page-url> --model seed_tts_2_0 --dry-run \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo gen run <page-url> --model seed_tts_2_0 \
  --max-credits <price> --idempotency-key handbook-3-voice \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo status <thread-url> --wait
invideo notebook show <thread-url>
invideo media audio.transcript <voice-sequence-url> --dry-run
invideo media audio.transcript <voice-sequence-url> \
  --max-credits <price>
invideo edit new <project-url> --name "Chapter 3 v1"
invideo asset add <edit-url> --stock <stock-id>
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name chapter-3 --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @scenes.json
invideo edit capture <branch-url> --at 3,20,45,80 --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:

- `<project-url>` comes from `invideo project new`, and `<edit-url>` from `invideo edit new`.
- `<voice-id>` comes from the `seed_tts_2_0_voices` search. It works only with `seed_tts_2_0`.
- `<page-url>` is a notebook page of the project, listed by `invideo notebook show <project-url>`. `<price>` is each dry run's `.estimated_credits`.
- `<thread-url>` is the `url` the paid `gen run` returns. `<voice-sequence-url>` is the voice file that `notebook show` on it lists.
- `<stock-id>` comes from the `stock_video` search.
- `<branch-url>` is the `branch_url` that `invideo branch new` returns.
- `<state_token>` comes from `invideo edit show` on the URL the next command runs on: `<edit-url>` for `branch new`, then `<branch-url>`, read again before each change.
- `<card-url>` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/export.mp4`, and the agent renames it.

The file behind `@scenes.json` is the bare list of ops that `--operations @scenes.json` takes. It holds one text slide for one rule. `start_f` and `end_f` are frames at the timeline's frame rate.

```json
[
  { "op": "add_text", "track": "V2", "start_f": 360, "end_f": 540,
    "text": "Report every spill at once",
    "style": { "font_size": 72, "font_weight": 700,
      "color": "#ffffff", "background_color": "#1a1a1acc",
      "align": "center" } }
]
```

## 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 voice, the transcript for captions, each stock clip you add, and each generated shot.
- Free: searching stock, every edit, `capture` and each export.

Generated shots cost the most. Stock is cheaper, and text slides are free. A short explainer takes under an hour. See [Credits](/account/credits) for prices.

## If something goes wrong

Most problems come from the script or the shots.

| 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. |
| `generate` refuses the voice: "voice_ids are model-specific" | The voice comes from another model's library. Search `seed_tts_2_0_voices` for `seed_tts_2_0`. |
| `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show <card-url> --out <dir>`. |
| The script misses a rule | Ask the agent to list every rule in the document first, then map each to a scene. |
| Stock looks generic | Search with concrete words from the scene. Or generate the shot, after a dry run. |
| A generated shot has sound you do not want | Set `generate_audio` to false, or mute its audio clip with `set_audio_muted`. |
| Text is hard to read on busy b-roll | Add a `background_color` to the text style, or blur the b-roll with the `gaussian_blur` effect through `add_effect`, or darken it with `edit_grade`. |
| 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. |
| CLI exit 5 | Credits ran out. Stop and tell the person. |
| Avoid: say done after the last edit | Instead: `capture` and `check_timeline` first. |

## Prompts to try

Each prompt is a real variation of this job.

```text
Turn our new expense policy into a short explainer. Text slides only,
no b-roll, our brand colors, and captions.
```

```text
Make a short safety explainer from sop-forklift.docx. Use stock
warehouse footage. Vertical for phones.
```

```text
Read this onboarding page and make a short explainer for each section.
Use the same voice and style for all of them.
```

## When to use something else

If you want a talking presenter, use an avatar tool such as HeyGen or Synthesia, then bring the clip in for captions and b-roll. invideo does not check that the script is legally correct. Your policy owner reviews the script before the agent voices it.

## Related

- [Turn slides into a narrated video, one deck or hundreds](/how-to/training/slides-to-narrated-video)
- [Make a whiteboard explainer from your script](/how-to/training/whiteboard-explainer)
- [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course)
- [When to use HeyGen or Synthesia vs invideo](/compare/heygen-synthesia)
- [Know the cost before you spend](/how-to/cost-before-you-spend)