---
title: Make a personalized video message from Santa or an AI presenter
description: A personalized video message where Santa or an AI presenter says your child's or friend's name, with the name on screen too.
---
You get a personalized video message, also called a custom greeting video or a video from Santa, where a talking Santa or an AI presenter says the person's name and a few lines you write. The name also shows on screen, so it reads right even if the voice says it a little off. It works for a Christmas message, a birthday shout-out, a trip reveal or a thank-you.

Use invideo for this when you want to hear the voice and fix the name before you pay for the video: your agent makes the voice first, you listen, and only then does it make the talking presenter.

## Quickest path

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

```text
Make a 30 second vertical video message from Santa for my son Arjun,
age 6. Santa says he heard Arjun was kind to his little sister and
that he should keep practicing piano. Use an original Santa, a warm
older voice, and "Merry Christmas, Arjun" on screen. Let me hear the
voice and tell me the price before you make the video.
```

In a chat app, you write the lines in the chat, and drag any photo into the project's Media panel in invideo. In a terminal, you name the files and the agent uploads them.

## What you need

The words and the name matter most. Write the name the way it sounds if it is unusual.

- **The script.** Four to six short sentences, with the name and one or two real details.
- **The name and how to say it.** For example "Siobhan, said shi-VAWN".
- **The presenter.** An original Santa, an AI presenter, or a photo of a person who agreed to it.
- **The voice.** Warm, cheerful, calm, an accent. Not the voice of an actor or a film character.
- **The shape.** 9:16 for a phone, 16:9 for a TV.

invideo sets no rule of its own on likeness. Each model provider does: some models decline to clone a real person's voice or face, others allow it with consent. Characters from a film, a show or a brand belong to their owners, and the rights are yours to clear. The safe ask is an original Santa or presenter.

## Steps

Your agent makes the voice first, so you hear the name before it makes the video.

<Steps>
<Step title="Write the script with you">
The agent writes the lines with the name in them, spelled by sound when it is unusual, and reads them back to you. Expected result: a script you approve.
</Step>
<Step title="Pick a voice">
The agent runs `find_models` with the job in words, like "warm text to speech voice", and `get_model` on its pick. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, or `seed_tts_2_0`. Your agent can search for others with `find_models`. It searches that model's own voice library with `search_library`, for example "warm older man": `elevenlabs_text_to_speech_voices` for the ElevenLabs model, `seed_tts_2_0_voices` for Seed TTS. A voice id works only with its own model. You play the previews and pick one. Expected result: a voice id.
</Step>
<Step title="Make the voice and listen">
The agent runs `generate` with the script, the voice id and `dry_run: true`, 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`. You listen to the name. Expected result: the voice's sequence URL, which the agent reads with `read`, never with a second `generate`.
</Step>
<Step title="Make or bring the presenter image">
For an original Santa, the agent runs `find_models` with the job in words, like "portrait image of an original Santa", and `get_model` on its pick. A good pick is `nanobanana_pro`. Your agent can search for others with `find_models`. It calls `generate` with a `prompt`, `aspect_ratio` 9:16 and `dry_run: true`, 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`. For a real person, it brings in their photo with `start_upload` and `add_media` instead. Expected result: an image's sequence URL with a clear, front-facing face, which the agent reads with `read`.
</Step>
<Step title="Make the talking video">
The agent runs `find_models` with the job in words, like "talking avatar from a photo and a voice", and `get_model` on its pick. A good pick is `heygen_photo_avatar`, which takes `image`, `audio` and `aspect_ratio`. Your agent can search for others with `find_models`, such as `kling_avatar.std`, which takes `image`, `audio` and a `prompt`. It calls `generate` with the image, the voice and `dry_run: true`, 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`. Expected result: the talking video's sequence URL, as long as the voice, which the agent reads with `read`, never with a second `generate`.
</Step>
<Step title="Put the name on screen">
The agent makes a timeline with `new_timeline`, places the video with `place_media` and `linked_audio` true, and adds the name with `add_text`. It can add soft music from `stock_music` under the voice with the `ducker` audio effect. A new timeline ducks under `A1` by default. The agent sets `set_sidechain_source` only when the voice is on another track. Expected result: the name on screen while it is said.
</Step>
<Step title="Check and export">
The agent runs `capture` at the start, the name and the end, and `media` `video.frames` on the talking video to check the mouth and eyes. Then it runs `export` with `format` video. 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 "Santa for Arjun"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo gen models <project-url> --query "warm text to speech voice"
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 "warm older man"
invideo gen run <page-url> --dry-run \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo gen run <page-url> --max-credits <price> \
  --idempotency-key arjun-voice-1 \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  -i prompt=@script.txt -i voice_id=<voice-id>
invideo status <thread-url> --wait
invideo gen models <project-url> \
  --query "talking avatar from a photo and a voice"
invideo gen model <project-url> --model heygen_photo_avatar
invideo gen run <page-url> --dry-run --model heygen_photo_avatar \
  -i image=<image-sequence-url> -i audio=<voice-sequence-url> \
  -i aspect_ratio=9:16
invideo gen run <page-url> --max-credits <price> \
  --idempotency-key arjun-video-1 --model heygen_photo_avatar \
  -i image=<image-sequence-url> -i audio=<voice-sequence-url> \
  -i aspect_ratio=9:16
invideo status <thread-url> --wait
invideo edit new <project-url> --name "Message" --width 1080 --height 1920
invideo edit show <edit-url>
invideo edit change <edit-url> --timeline T1 --token <state_token> \
  --operations @ops.json
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`. `<voice-id>` comes from the `library search` line.
- `<page-url>` is a notebook page; `invideo notebook show <project-url>` lists them. Each `<price>` is the `.estimated_credits` of the dry run before it.
- `<thread-url>` is the `url` each paid run returns. `<voice-sequence-url>` and the talking video's URL are the sequences `invideo notebook show <thread-url>` lists once each lands.
- `<image-sequence-url>` is the presenter image: the URL `invideo asset upload` returns for a photo, or the sequence a `nanobanana_pro` run makes with the same dry run and paid run pattern.
- `<state_token>` comes from `invideo edit show`. `ops.json` holds a bare list of operations: `place_media` for the talking video and `add_text` for the name.
- `<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 `generate` call that makes the talking video, as a dry run first. `<page-url>` is a notebook page from `read` on the project. The two sequence URLs are the image and the voice the earlier steps made.

```json
{
  "url": "<page-url>",
  "model": "heygen_photo_avatar",
  "dry_run": true,
  "inputs": {
    "image": "<image-sequence-url>",
    "audio": "<voice-sequence-url>",
    "aspect_ratio": "9:16",
    "expressiveness": "medium"
  }
}
```

## 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, a generated presenter image, the avatar video, priced per second of voice, and paid stock music.
- **Free:** voice previews, the timeline, the name on screen, `capture` and the export.
- **Tool ops:** `video.frames`. The dry run shows its price before anything starts.

The voice takes under a minute. The avatar video takes a few minutes. Making the voice first saves money, because a wrong name costs a voice, not a video. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are the name, the mouth, or a model that declines a likeness.

| 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 voice says the name wrong | Spell it by sound in the script and make the voice again. The name on screen stays right. |
| The mouth does not match the words | Try the other avatar model, or a photo with the face straight on and the mouth closed. |
| A model declines a voice or a face | That model's provider does not allow that likeness. Read the refusal `message`, try a model whose rules allow it, or ask for an original look. |
| Status `needs_confirmation` | Only you can confirm it, in invideo. Open the URL the agent gives you. |
| CLI exit 5 | A credit limit. Check your balance on the credits page. |
| Avoid: making the video before you hear the voice | Instead: voice first, then the avatar. |
| Avoid: the agent resends `generate` after a timeout | Instead: it reads the thread, or retries with the same `idempotency_key`. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a birthday shout-out from a friendly AI presenter for my friend
Kofi. She says happy birthday and mentions his trip to Lisbon. 1:1,
with "Happy birthday, Kofi" on screen.
```

```text
Make a trip reveal for my parents. A presenter says "Pack your bags,
you are going to Kyoto in April". End on a photo of Kyoto from stock.
Vertical.
```

```text
Make the same Santa message for three kids, Ava, Leo and Noor, one
branch each. Only the name and one detail change. Let me hear each
name first.
```

## When to use something else

For a message from a real celebrity, use a service where the person records it themselves. Cloning a real person's voice or face depends on the model provider's rules and on the person's consent, which is yours to get.

For many messages from one recording, like sales videos, see [Make a personalized video for every prospect from one recording](/how-to/marketing/sales-outreach-video). This page is for a few personal messages.

## Related

- [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo)
- [Make a video invitation for a birthday, wedding, baby shower or gender reveal](/how-to/personal/video-invitation)
- [Voice a script or narrate a course](/how-to/training/voice-a-script-or-narrate-a-course)
- [Know the cost before you spend](/how-to/cost-before-you-spend)
- [Licensing and commercial use](/account/commercial-use)