---
title: Translate a training video and retime the cut to fit the new voice
description: Translate and dub a training video: approve the translated script, voice it, then stretch the cut so the new voice fits at a natural pace.
---
Translate a training video into another language: a translated voiceover, a dub, a localized version. Your agent transcribes the original, translates the script, and waits for your approval. Then it voices the new script and changes the cut so the new voice fits, holding a slide longer or opening a pause, instead of speeding the voice up.

Use invideo for this when you want the translated voice at a natural pace, with the picture retimed on an editable timeline, and a branch per language you can compare.

## Quickest path

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

```text
Translate this training video <edit-url> into German. Transcribe it,
translate the script, and show me the German script before you voice
anything. Then voice it, mute the English voice, and retime the cut so
the German fits. Never speed up the voice. Work on a branch called de.
```

In a chat app, you paste the timeline URL or drag the video in. In a terminal, the agent uploads the file you name.

## What you need

The script approval is the step that matters most.

- The video, on an invideo timeline or as a file.
- The target language.
- A person who reads that language and approves the script. The agent translates, but a native speaker catches the errors.
- A voice: a stock voice from `search_library`, or a clone of the original speaker with their consent.
- A glossary of product names and terms that must stay as they are.

## Steps

The agent works on one branch per language.

<Steps>
<Step title="Transcribe the original">
The agent prices `audio.transcript` with `dry_run` on the video's sequence URL from `add_media` 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 sees every word with its time and speaker.
</Step>
<Step title="Translate, then wait">
The agent translates line by line and keeps each line's original start and end. It writes the script to a brief with `new_brief`, so you can read and edit it in invideo. It sees your approval, or applies your changes with `edit`.
</Step>
<Step title="Voice the approved script">
1. The agent runs `find_models` with "narration voice" and the language, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a voice whose languages include the target, from `search_library` in `elevenlabs_text_to_speech_voices`. For the original speaker's voice, a good pick is `seed_audio_1_0.ta2a`, with their clips as `reference_audio_1` to `reference_audio_3`. Your agent can search for others with `find_models`.
2. It calls `generate` per line with `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` per line with `max_credits` set to that price and an `idempotency_key`, like `line-07-de`. It gets a thread URL and, when the result lands, one sequence URL per line. It reads each URL with `read` and never calls `generate` again to check.
</Step>
<Step title="Branch and mute the original voice">
The agent creates a branch with `timeline_history`, and mutes the original voice there with `set_audio_muted`. It sees a new `state_token`.
</Step>
<Step title="Place each line and retime the cut">
The agent places each new line at its original start with `place_media`. Where a line runs long, it opens time on every track with `edit_time_range` mode `insert`, or holds a slide longer with `trim_clip` on its tail. Where a line runs short, it removes the extra time with `edit_time_range` mode `close_gap`. It never uses `retime` on the voice. It sees each line end before the next starts.
</Step>
<Step title="Translate the words on screen">
The agent changes text clips with `set_text`, and adds captions with `add_captions` from a transcript of the new voice. It sees the translated text in `capture` frames.
</Step>
<Step title="Check, then export">
The agent calls `capture` at each changed spot and `check_timeline`, then `export` on the branch. It sees an export card with status `completed`.
</Step>
</Steps>

The terminal version:

```bash
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> --max-credits <price>
invideo library search <project-url> \
  --library elevenlabs_text_to_speech_voices --query "German narrator"
invideo gen models <project-url> --query "German narration voice"
invideo gen model <project-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \
  -i prompt=@line-07-de.txt -i voice_id=<voice-id>
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  --max-credits <price> --idempotency-key line-07-de \
  -i prompt=@line-07-de.txt -i voice_id=<voice-id>
invideo status <thread-url> --wait
invideo notebook show <thread-url>
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name de --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @retime-de.json
invideo edit capture <branch-url> --at 10,42,75 --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/de
```

Where each value comes from:

- `<sequence-url>` is the video's `url` from `invideo asset upload`, a `…/notebook/seq-N.M` URL.
- `<price>` is each dry run's `.estimated_credits`.
- `<project-url>` is the video's project. `<page-url>` is a notebook page of the project, listed by `invideo notebook show <project-url>`.
- `<voice-id>` comes from the `library search` line. It works only with `elevenlabs_text_to_speech.elevenlabs_tts_v4`.
- `<thread-url>` is the `url` the paid `gen run` returns. `notebook show` on it lists the take's sequence URL.
- `<edit-url>` is the video's timeline URL, from `invideo edit new` or the editor. `<state_token>` comes from `invideo edit show <edit-url>` for `branch new`.
- `<branch-url>` is the `branch_url` that `invideo branch new` returns. After that, `<state_token>` comes from `invideo edit show <branch-url>`, read again before each change, because the main token is stale on the branch.
- `<card-url>` is `.sequences[0]` of the export answer. `invideo status` waits but saves nothing. `invideo notebook show` saves the video as `./out/de/export.mp4`, and the agent renames it.

The file behind `@retime-de.json` is the bare list of ops that `--operations` takes. Here one line runs long, so the agent opens the extra frames on every track and places the take. `c4` is the original voice clip's id from `invideo edit show`. The `asset` is the take's sequence URL from the thread.

```json
[
  { "op": "set_audio_muted", "target": "c4", "muted": true },
  { "op": "edit_time_range", "timeline": "T1",
    "start_f": 1260, "end_f": 1290, "mode": "insert" },
  { "op": "place_media", "asset": "<line-07-sequence-url>",
    "track": "A1", "at_f": 1170,
    "source_start_seconds": 0, "source_end_seconds": 4,
    "mode": "overwrite", "linked_audio": false }
]
```

### No one-shot dub

invideo has no model that translates a whole video in one call. For a quick draft with no script step, use a dubbing service, named at the end of this page. Use the steps above when the wording matters.

## 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, each voice take, and stem separation if needed.
- Free: the branch, every edit, `capture` and `export`.

The voice and the edit take under an hour per language. Your review of the script takes the longest. See [Credits](/account/credits) for prices.

## If something goes wrong

Most problems are lines that do not fit.

| 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. |
| `audio.transcript` refused with `code: "not_found"`, or CLI exit 2 | The call named a media bin asset. Pass the video's sequence URL from `add_media` or `invideo asset upload`. |
| CLI exit 3 on the first change after `invideo branch new` | The main token is stale on the branch. Run `invideo edit show <branch-url>` and use its `state_token`. |
| `invideo status --wait` ends and the folder is empty | `status` does not download. Run `invideo notebook show <card-url> --out <dir>`. |
| A line overlaps the next | Open time with `edit_time_range` mode `insert` at the end of the line, or hold the slide longer. |
| The picture drifts out of sync | The time changed on one track only. Use `edit_time_range`, which moves every unlocked track. |
| The music cuts out with the old voice | The voice and music share one clip. Split stems with `media` `audio.separate` on the video's sequence URL, after a dry run, and keep the music stem. |
| Brand names are translated | Keep them in the script as they must be said, and list them in the brief. |
| CLI exit 3 | The edit changed since your read. Run `invideo edit show` and rebuild. |
| Avoid: speed up the voice to fit | Instead: retime the cut. Fast speech is hard to follow in training. |
| Avoid: voice before approval | Instead: show the script and wait for a yes. |

## Prompts to try

Each prompt is a real variation of this job.

```text
Make Spanish (Mexico) and Portuguese (Brazil) versions of this video, one
branch each. Use the glossary in our brief. Show me both scripts first.
```

```text
Give me a quick French draft of the first few lines only, so I can see
if the length works before we do the rest.
```

```text
Translate only the on-screen text and captions into Japanese. Keep the
English voice.
```

## When to use something else

invideo does not judge translation quality. A native speaker or a translation vendor reviews the script. For a one-shot dub with no script step, use ElevenLabs Dubbing or HeyGen video translation, then bring the file into invideo for the cut and captions. For a speaker on camera, the new voice does not match their lips. Re-sync the mouth with a lip sync model, as on [Dub existing footage](/how-to/training/dub-existing-footage).

## Related

- [Dub existing footage](/how-to/training/dub-existing-footage)
- [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course)
- [Make an SRT captions file for an LMS](/how-to/training/srt-for-an-lms)
- [Localize a winning ad](/how-to/marketing/localize-a-winning-ad)
- [Know the cost before you spend](/how-to/cost-before-you-spend)