---
title: Use ElevenLabs with invideo
description: Bring voice, music and sound from ElevenLabs into invideo as audio files, run ElevenLabs models inside invideo, or seed captions from a Scribe transcript.
---
It depends on where you make the sound. ElevenLabs makes voice and audio: Text to Speech, Speech to Text with Scribe, Music, Sound effects, Dubbing and a Voice changer. invideo adds the picture and the timeline the sound sits on, and it runs several ElevenLabs models inside the project, so your agent makes the voice and places it in one place.

Use ElevenLabs when your voices and projects live there. Use the ElevenLabs models in invideo when the agent should make the sound and the cut together.

## When to use both

Use both when the sound comes from ElevenLabs and the video comes together in invideo. Common cases:

- **A voiceover you made in ElevenLabs.** The agent places it under the footage and cuts the picture to it.
- **A song or sound effects.** You made them in ElevenLabs Music or Sound effects. The agent places them on their own tracks.
- **A transcript from Scribe.** You have the words with times. The agent turns them into captions.

## ElevenLabs inside invideo

invideo runs these ElevenLabs models with `generate`. The agent reads each model's inputs with `get_model` first.

| Model | What it makes |
| --- | --- |
| `elevenlabs_text_to_speech.elevenlabs_tts_v4` | A voiceover from text |
| `elevenlabs_text_to_dialogue.generate_v4` | A dialogue between voices |
| `elevenlabs_speech_to_speech.elevenlabs_sts_multilingual_v2` | A recording in another voice |
| `elevenlabs_sfx` | A sound effect, with an option to loop |
| `elevenlabs_music_v2_5_song` | A song with vocals |
| `elevenlabs_music_v2_5_instrumental` | Music with no vocals |

For a voice, the agent searches the model's voice library with `search_library`. For `elevenlabs_text_to_speech.elevenlabs_tts_v4`, `get_model` names it on the `voice_id` input: `elevenlabs_text_to_speech_voices`. Each voice has a `preview` you can play. Your workspace's cloned voices are in the list too.

## Hand-off: from ElevenLabs into invideo

Download the audio from ElevenLabs. MP3 is its default format. Then your agent brings it in:

- **A public link.** `add_media` with `media_url`.
- **A file on your computer.** `start_upload` with the `file_name`, a PUT of the bytes to the `upload_url`, then `add_media` with the `upload_id`. In a terminal, `invideo asset upload <project-url> <file>`.
- **A file in a chat app.** You drag the file into the chat. It arrives through `file` on `add_media`.

Each file becomes a sequence in the project, with its own sequence URL. On a timeline's URL, `add_media` also puts it in that timeline's media bin.

The agent places the audio with `place_media` on an audio track and sets its level with `set_audio_gain`.

**A Scribe transcript as captions.** Scribe gives each word with its start and end time. The agent turns each time into frames at the timeline's rate, groups the words into lines, and writes them into `add_captions` as slides with words. No `audio.transcript` run is needed, so the captions cost no credits.

## Hand-off: from invideo to ElevenLabs

When you want to dub or change a voice in ElevenLabs, your agent exports the sound. `export` with `format` `video` and `mode` `audio` gives the audio alone, with `audio_format` `wav`, `aac` or `opus`. You upload that file to ElevenLabs.

For the whole video, for example to dub it in ElevenLabs Dubbing, the agent exports with `mode` `video`. The result is a 1080p MP4.

## Steps

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.

Your agent runs a dry run first. For any call that costs 1 credit or more, it tells you the price and waits for your yes. A call under 1 credit runs without asking, and your agent tells you what it cost.

<Steps>
<Step title="Bring the audio in, or pick a voice">
The agent calls `add_media` for each ElevenLabs file. To make the voice in invideo, it calls `search_library` for a voice instead. Expected result: a sequence URL per file, or a voice `id`.
</Step>
<Step title="Price the voice">
The agent reads `elevenlabs_text_to_speech.elevenlabs_tts_v4` with `get_model` and sets the `prompt` text and the `voice_id`. It calls `generate` with `dry_run: true` and the real inputs, and tells you the price. Expected result: a price and no charge.
</Step>
<Step title="Make the voice">
The agent calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a thread URL, then a sequence URL when the voice lands. The agent reads that URL with `read`, and never calls `generate` again to check.
</Step>
<Step title="Place the sound on a branch">
The agent makes a branch with `timeline_history`, then places the voice and music with `place_media`. Expected result: a new `state_token`.
</Step>
<Step title="Add captions">
The agent writes `add_captions` from the Scribe words. With no transcript, it prices `audio.transcript` with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Expected result: captions that light up word by word.
</Step>
<Step title="Check, then export">
The agent checks the levels with `media` `audio.loudness`, runs `capture`, then `export` with `target_lufs`. Expected result: an export card with status `completed`.
</Step>
</Steps>

A caption slide written from Scribe words, at 30 frames a second. The fence is the bare list of ops that `--operations @ops.json` takes:

```json
[
  {
    "op": "add_captions",
    "track": "V2",
    "slides": [
      {
        "text": "Welcome to the launch",
        "start_f": 0,
        "end_f": 45,
        "words": [
          { "text": "Welcome", "start_f": 0, "end_f": 12 },
          { "text": "to", "start_f": 12, "end_f": 18 },
          { "text": "the", "start_f": 18, "end_f": 24 },
          { "text": "launch", "start_f": 24, "end_f": 45 }
        ]
      }
    ]
  }
]
```

Each frame number is a Scribe time in seconds times the timeline's fps, from `get_timeline`.

The voice from a terminal:

```bash
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo gen model <project-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4
invideo library search <project-url> \
  --library elevenlabs_text_to_speech_voices --query "calm"
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 --dry-run \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  -i prompt=@script.txt -i voice_id=<voice-id> \
  --max-credits <price> --idempotency-key voice-1
```

`<project-url>` comes from `invideo project new` or `list_projects`. `<name>` is the name you choose in `invideo agent register`. `<page-url>` is a page that `invideo notebook show <project-url>` lists. `<price>` is the price the dry run returns. `<voice-id>` is an `id` that `invideo library search` returns.

## When to stay in ElevenLabs

Stay in ElevenLabs when the job is audio alone: a podcast voice, an audiobook or a voice agent. ElevenLabs Dubbing also dubs a finished video there. Its own tools hold your voice library and your Studio projects.

Move to invideo when the sound needs a picture, captions and a cut, and an agent that edits both together.

## If something goes wrong

| Symptom | Fix |
| --- | --- |
| `add_media` with `media_url` is refused | The link must be public. Download the file, then upload it with `start_upload` and `add_media` with the `upload_id`. |
| `generate` refuses the `voice_id` | A voice id belongs to one model. Search `elevenlabs_text_to_speech_voices` for `elevenlabs_text_to_speech.elevenlabs_tts_v4`. |
| Captions run ahead of or behind the voice | Scribe times are in seconds. Multiply each by the timeline's fps from `get_timeline`, then check a few frames with `capture`. |
| `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. |
| Avoid: call `generate` again to check on a run | Instead: read the thread or sequence URL with `read`. A second `generate` starts a second paid run. |

## Related

- [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)
- [Add word-by-word captions](/how-to/creators/word-by-word-captions)
- [Use Whisper timings with invideo](/integrations/whisper)
- [Dub existing footage](/how-to/training/dub-existing-footage)
- [Models](/reference/models)