# Characters and promo videos

For AI agents using the `h3` CLI. [SKILL.md](https://minimax.xxt.ai/SKILL.md) sections 9 and 10 have the essentials; this file has the full commands and rules. HTTP endpoints for the same features are in [references/api.md](https://minimax.xxt.ai/references/api.md) section 7.

## 1. Character library

When the same person appears in several shots, create a character first: a few clear face photos plus a voice. Create once, reuse everywhere; face and voice stay consistent from shot to shot.

```bash
h3 character create --name Mia \
  --photo front=front.jpg --photo three_quarter_left=left.jpg --photo three_quarter_right=right.jpg \
  --description "a cheerful woman in her twenties with shoulder-length hair" \
  --voice-description "a woman around 25, warm and slightly breathy, mid-low pitch, medium pace, relaxed tone" \
  --language English                     # no --voice: the platform designs a voice from the description (5–20 s extra)
h3 character list                        # my characters
h3 character show Mia                    # <character> is an id or a name
h3 character add-photo Mia side=side.jpg
h3 character remove-photo Mia <photo-id> # at least one photo must remain
h3 character order-photos Mia <photo-id> [<photo-id>…] # listed photos move to the front in that order, the rest keep theirs; the first is the cover
h3 character set-voice Mia new.m4a       # switch to a recording; clear-voice removes the voice
h3 character set-voice Mia --template teen-girl   # switch to a ready-made voice template (section 3)
h3 character update Mia --description "…"
h3 character delete Mia                  # deletes photos and voice too
```

- **Photos**: 1–8. Use 3–5 clear close-ups of the face, **at least one `front`**, plus three-quarter views etc. Angles are only `front`, `three_quarter_left`, `three_quarter_right`, `side`, `full_front`, `full_back` (no `other`). Photos are content-checked at creation; a rejection says which photo.
- **Voice**: every character gets one; without it, it can't speak. One of three:
  - The user has their own (or an authorized) recording: `--voice`, 3–15 s; only the first 15 s are used.
  - A stock role that fits one of the 14 **voice templates** (section 3), e.g. a little girl, a grandpa, a domineering CEO, a livestream host: `--voice-template <id>`. Free, instant, no audition used. Templates were recorded in Chinese, but the timbre carries over: an English line with the `ceo` template still sounded like it [tested here 11-04]; Japanese and Korean are untested.
  - Otherwise: write `--voice-description`; the platform designs a ~10 s voice from it (an audition). **You design the voice description (section 2), even if the user didn't ask for a voice.** Without one, the voice is built from the description and usually has no character.
- **Description**: a noun phrase about looks, e.g. "a woman in her thirties with shoulder-length black hair". Description and voice description both go into the video prompt.
- `--language` is the language the character speaks: `Chinese` (default), `English`, `Japanese`, `Korean`.
- At most 50 characters per account. Name 1–40 characters, unique among your undeleted characters. Name, description and voice description cannot contain `<`, `>` or line breaks.
- Character photos and voices are kept until you delete them; job assets and videos still follow the 8-hour retention. When writing your own HTTP client, upload photos and recordings with `"purpose": "character"` (api.md sections 3 and 7; the CLI does this for you).
- If the voice couldn't be made (e.g. no auditions left today), `create` says so on stderr and the character has `voice.status` `none` or `failed`; run `h3 character audition <character>` later. When a voiceless character has lines, `h3 submit` designs a temporary voice from its voice description first (one audition), then submits; tell the user, and change it later only if they want a specific voice.
- A character with `exemptModeration: true` can't be used in normal jobs (`character_exempt_only`): use another character, or the person's photos via `--ref`.

## 2. Designing a voice

Without a recording, the voice is built entirely from this one phrase. Generic phrases like "a clear female voice, fast pace" produce forgettable voices. Before creating the character, design a voice from the character's role, age and personality, written as **one noun phrase**: about 30–45 Chinese characters, or about 20–30 English words. In this order:

1. **Age and gender**, optionally a role: "a taxi driver in his forties", "a bubble-tea shop girl around 25";
2. **Timbre**, one or two concrete words: warm, breathy, husky, smoky, deep, full, round, crisp, nasal;
3. **Pitch**: high, medium, mid-low, low;
4. **Pace**: fast, medium, slow;
5. **Tone and accent**: relaxed, laughs easily, easygoing, gentle, brisk, lazy; a northern Chinese accent, a Sichuan accent;
6. Optional, half a sentence of setting: "like chatting with a friend".

Tested on the voice-design model, read in full:

- 「二十五岁左右的女声，音色温暖、略带气声，音调中等偏低，语速中等，语气轻松」 (a woman around 25, warm, slightly breathy, mid-low pitch, medium pace, relaxed)
- 「二十五岁左右的奶茶店女店员，声音温暖、带点沙，语气轻松爱笑」 (a bubble-tea shop girl around 25, warm, a little husky, relaxed and smiley)
- 「四十多岁的男声，低沉、略带沙哑，语速偏慢，语气温和，像在跟老朋友聊天」 (a man in his forties, deep, slightly husky, slow, gentle, like chatting with an old friend)
- 「四十多岁的出租车司机，嗓音低沉沙哑，带北方口音，说话随和」 (a taxi driver in his forties, deep and husky, northern accent, easygoing)

Write the description in the character's language (Chinese for a Chinese-speaking character).

- **No instructions about delivery over time**: "pace speeds up and slows down", "a smile at the end of sentences", "pauses to think between sentences". The model then reads the sample sentence twice or only half of it (tested: 60+ Chinese characters with such wording broke 1–3 times in 3). Over 50 Chinese characters, cut it down.
- **Only write what you want.** No negatives like "not a broadcaster voice": the voice description also goes into the video prompt, and negated things get pulled in.
- Characters in the same film should differ in at least two of age, timbre and pace, so the viewer can tell who is speaking.
- After creating, tell the user the voice description you wrote.

## 3. Voice templates and auditions: changing a voice

**Voice templates**: 14 voices made in advance, seven groups of one woman and one man, spread far apart so characters don't sound alike:

| group | female | male |
|---|---|---|
| child | `girl` (about 8) | `boy` (about 9) |
| teen | `teen-girl` (17, sweet, playful) | `student` (20, fresh, sunny) |
| young | `young-woman` (28, bright, brisk) | `young-man` (30, deep, warm, magnetic) |
| middle | `mom` (45, gentle, caring) | `uncle` (50, deep, commanding) |
| elder | `grandma` (75, frail, kind) | `grandpa` (70, husky, slow, smiling) |
| persona | `queen` (32, cold, low, imposing) | `ceo` (35, cold, curt, domineering) |
| host | `host` (26, livestream sales, fast, upbeat) | `narrator` (40, broadcast narrator) |

```bash
h3 character voice-templates --out ./voices    # id, name, gender, age, description and a listening link for each; --out downloads all 14
h3 character create --name Wang --photo front=front.jpg --voice-template ceo
h3 character set-voice Wang --template uncle   # switch to another template
```

- Picking a template copies it to the character as its own voice (`voice.source` `template`, `voice.template` the id) and sets the voice description to the template's. Free, no audition used, takes a second or two.
- Pick by role, age and sex; tell the user which template you picked and give them the listening link. Don't give two characters who talk to each other the same template.
- Nothing fits (a specific accent, a very particular timbre)? Design one (section 2) with an audition, below.

**Auditions**:

```bash
h3 character voice Mia                         # prints a listening link (valid 1 hour); --out ./voices downloads it
h3 character audition Mia --voice-description "…"   # redesign from a new description, replacing the current voice
h3 character quota                             # used / remaining today
# Listen first, decide later: a preview not attached to any character
h3 character preview-voice --voice-description "…" --out ./voices
h3 character create --name Mia --photo front=front.jpg --voice-preview <asset> --voice-description "…"
h3 character set-voice Wang --preview <asset> --voice-description "…"
```

- **You cannot hear audio.** Give the user the listening link or downloaded file (or let them listen on the website) and ask if they like it. If not, ask what is off (too old, too sharp, too muffled, too flat), change that part of the description and redesign. When the user wants to pick a voice, use `preview-voice` and create the character once they are happy.
- Auditions are free, 20 per account per day (reset at midnight Singapore time; failures of the voice service don't count), including the one made at character creation. Each takes 5–20 s. Don't loop: check `h3 character quota` first; when used up (`audition_limit`), try tomorrow or ask the user for a recording.
- If the voice fails at creation, the character is still created with `voice.status` = `none`; run `h3 character audition <character>` to see the error code (e.g. `audition_limit`, `voice_unavailable`).
- `audition` without `--voice-description` uses the character's current voice description (or the description if none); `--voice-description ""` designs from the description and clears the voice description. The voice description is saved only when a voice is made.
- Previews must be used within 6 hours; unused ones are deleted. `--voice`, `--voice-preview` and `--voice-template` are mutually exclusive.

## 4. Using characters in videos

```bash
h3 submit --mode ref2v --aspect 16:9 --seconds 8 \
  --prompt "Living room, evening. Mia sits on the sofa reading; Wang walks in through the door and stands in front of her. Static camera, medium shot." \
  --character Mia --character Wang \
  --line "Wang:pushes the door open, takes off his coat=You're back." --line "Mia:looks up and smiles=Yeah, dinner's on the table." \
  --wait --out ./out

# Several shots in the same place: attach the same scene image every time and just say "living room" in the prompt
h3 submit --mode ref2v --aspect 16:9 --seconds 8 \
  --prompt "Living room, night. Mia and Wang sit side by side on the sofa watching TV; Wang hands Mia a bowl of fruit. Static camera, medium shot." \
  --character Mia --character Wang --ref "other:living room=living-room.jpg" \
  --wait --out ./out
```

- `--character <name or id>` picks a character; repeat it, order = character order. Works in `ref2v`, `i2v`, `lipsync`, `promo`. In `lipsync` pick exactly one (the person singing or speaking); the voice comes from `--audio`, the lyrics still go in `--dialogue`, no `--line`.
- **With characters, person photos come from the characters.** Scenes, products and props still go in via `--ref other:<what>=<file>` (only `other`; characters + `--ref` images ≤ 8). This locks one location across several shots.
- **Lines**: `--line <character>=<text>` or `--line <character>:<action>=<text>`, in speaking order, at most 10, each ≤ 200 characters, no `<` or `>`. The action says what the character does or how they sound while speaking, **without a subject** ("sighs softly and stands up", not "she sighs"). If a name or action contains `=` or `:`, use the character id. With characters, don't use `--dialogue`.
- Lines can also go straight into `--prompt`, in quotes with the speaker before them: `Wang walks in: "You're back."` (Chinese 「」 quotes also work). Without `--line`, the platform uses an LLM to split them into lines (text unchanged; each has `"fromPrompt": true` in the job's `lines`). On-screen text (signs, captions) goes after "reading" / 「写着」 plus quotes and is not treated as a line. If the speaker is unclear: `invalid-input` with `path` = `prompt`. **Splitting them yourself with `--line` is more accurate and faster.**
- **At most 3 speakers per shot**, and every speaker needs a voice. If burned-in captions show up, resubmit with a different `--seed`.
- **Use character names directly in the prompt**; the platform matches them. Describe the scene fully: set dressing, lighting, positions, clothes, actions, camera. With only a sentence or two, two-person dialogue often burns the lines in as captions; in `ref2v` with lines the platform fills in the scene and a closing action, but writing it fully yourself is safest. Looks and voice come from the description and voice description; don't repeat them.
- **A look that must hold across shots** (period costume, hairstyle, headdress): create a separate character for it, with 5 photos of the person in that look (`front`, both three-quarters, `side` both ways) and the original's voice (`h3 character voice <original> --out <dir>`, then `--voice <file>`). With the everyday character, hair drifted back toward the photos' short modern cut [tested here 11-03].
- Clothes follow the prompt by default; only face, hair and build come from the photos. To keep the photo's clothes, add `--wardrobe <name or id>` (only matters in `ref2v`; in `i2v` clothes follow the first frame) and don't describe that character's clothes in the prompt.
- At most 8 photos in total (7 with a last frame: the model takes at most 9 images and first/last frame use one each). `--ref` images take slots first; the rest go to characters. Each character gets one front photo first, then the others are filled in turn (same for `ref2v`, `i2v`, `lipsync`). One character with no `--ref` gets all of its photos.
- **Pick photos per shot angle**: `--character Mia=front,side` uses only those angles of Mia's photos for this shot (angles: `front`, `three_quarter_left`, `three_quarter_right`, `side`, `full_front`, `full_back`). Accurate beats many: profile shot `front,side` or `front,three_quarter_left`; from behind `front,full_back`; full body `front,full_front`. **Always include `front`**: the front photo is the main identity cue. With two or three people in frame, pick 2–3 angles each so one person doesn't take all the slots. An angle the character has no photo for gives `invalid-input`; check with `h3 character show` first. Without angles, the default selection above applies. Occasionally the end of a clip pastes the reference photo itself into the frame (e.g. a grey-background headshot); resubmit with a different `--seed`. With several people talking it is common: section 6. The job's `characters` and `lines` show what was used. Full rules: api.md section 4.

## 5. Promo videos

One character hosts and talks to camera about one to a few products. Portrait, one take. Create the host as a character first; **the host must have a voice**.

```bash
h3 submit --mode promo --aspect 9:16 --seconds 8 --character Mia \
  --product "face cream=cream_front.png,cream_side.png" --product-note "face cream=white jar, gold lid" \
  --product "dress=dress.png" --wear "dress=outfit" \
  --scene "live studio=room.png" \
  --selling-points "24-hour hydration, safe for sensitive skin, free samples with every order today" \
  --wait --out ./out
```

- **One clip per submit**, 4–15 s. **Lines total at most 30 units**, or captions appear on screen: each Chinese character counts 1, each English word or number 5/3, punctuation 0 (so about 18 English words).
- **Products**: `--product <name>=<file1>[,<file2>,<file3>]`, at most 4 products, 1–3 images each, at most 6 images total; use clear front shots. `--product-note <name>=<note>` adds color or size (≤ 100 characters); names 1–40 characters. Large text and logos reproduce; tiny text blurs.
  - Clothes, shoes, bags worn by the host: `--wear <name>=outfit`; jewelry, watches, glasses: `--wear <name>=accessory`. Otherwise the host holds the product up.
- **Scene** (optional): `--scene <name>=<file>`, one image, the name says what it is.
- **Lines**, pick one:
  - Write them: `--line "Mia:picks up the cream and holds it to the camera=I've used this cream for a month."`.
  - Give `--selling-points "<points>"` (≤ 300 characters), or nothing at all: the platform writes 1–3 lines (`"generated": true` in `lines`, no extra credits).
  - Put selling points and quoted lines into `--prompt`; the platform extracts lines, selling points and what to wear.
  - **Splitting it yourself with `--line` or `--selling-points` plus `--wear` is the most accurate.**
- **Host off camera** (`--off-camera`): for videos without a visible host. The host's photos are not sent; the clip is a first-person view where only hands hold and turn the products, and the host's voice narrates off screen. Still pick `--character` (for the voice). `--wear` is not allowed (nobody wears the product). With `--line`, write hand actions (`--line "Mia:turns the jar to the front and says=..."`), not looks or smiles.
- `--prompt` is optional; to set actions, shot size or setting, use the character, product and scene names in it. Not allowed: `--first-frame`, `--last-frame`, `--ref`, `--audio`, `--dialogue`, `--wardrobe`; `--segments` must be 1. If captions appear, resubmit with a different `--seed`.

**A one- or two-minute video**: the platform makes one clip at a time; split and join it yourself.

1. Split the script into 8–10 s parts, each with ≤ 30 units of lines, breaking between sentences.
2. Submit every part with the same host, products, scene image and description, adding `--part <n>/<total>` (e.g. `--part 2/6`): when writing lines, the platform opens in part 1, covers selling points in the middle and closes with a call to buy in the last part. Parts can be submitted in parallel. **Give every part the same `--scene` image and the same shot size in `--prompt`** (e.g. `A medium shot of Mia at the counter, …`), with product names in English: otherwise background and framing change between parts [tested here].
3. Download each with `--wait --out`, then join in order: `h3 concat final.mp4 part1.mp4 part2.mp4 …` (needs local ffmpeg; macOS: `brew install ffmpeg`; add `--force` to overwrite). The platform doesn't add subtitles or music; add them locally.

## 6. Two or three people talking in one shot

Tested here 11-01 (about 100 takes: `i2v`, 9:16, 8 s, a first frame with everyone in it, characters with voices; each line's speech timing checked against whose mouth moved).

**What actually goes wrong**: rarely a plain mouth swap. The model cuts on its own to a close-up of one person, sometimes that character's reference photo pasted in whole (plain background and all), and the next line plays over it, so a listener seems to speak. It mostly happens in the second half of the clip; burned-in captions sometimes come with it. Small wording changes (shorter voice phrases, a lips-close sentence after each line) left the same seeds cutting at the same moments; another seed, or positions for three people (below), changes it.

**Always for dialogue**: `--segments 2`, and after downloading look at one frame inside each line (`h3 frame <file> --at <s>`; lines come in order, about 1 s per 4 Chinese characters plus a short gap): is the speaker on screen with lips apart, the others with lips closed? If neither take works, resubmit with another `--seed`.

**Two people** (static two-shot; both faces visible, or one with their back to the camera): `--line` in the normal mode is enough. Tested: 4 and 6 alternating lines, a man and a woman, one speaker with his back to the camera: every line on the right mouth in all takes.

**Two people of the same sex who both speak in one clip: the model decides who gets which voice, by how they look, not by whose voice it is.** Tested here 11-03 and 11-04: two men (around 40 and around 70, voices about 121 and 122 Hz), 11 jobs, 19 takes. The older man always spoke in the same one of the two voices, whichever character that voice was saved on: with the voices the right way round every take was wrong, with the two voices swapped between the characters every take came out right, so nothing we pass decides it. `--character` order, the platform's prompt, `raw` with `<Audio n>` either way round, naming each line's voice and three seeds all changed nothing; the platform hands the voices to the model in the right order. Lips and words were always on the right person. A man and a woman, or only one of the two speaking, came out right. This can't be fixed on the platform: **shoot same-sex dialogue as shot / reverse shot, one speaker per clip**: pass both characters, write the silent one as `<name> only listens and never speaks; his lips stay closed the whole time.`, give each clip its own first frame and cut between them (all voices right, checked by ear). Listen to the takes yourself, or have the user listen: voiceprint comparison couldn't tell two similar male voices apart.

- Say in the prompt where each one stands and that it is one take: `Mia stands on the left and Wang on the right, turned toward each other … The camera holds a static shot in one continuous shot.`
- Two people of the same sex: see the voices above; also the listener's lips moved during the other's line in 1 of 2 takes.

**Three or more people** (`i2v`): give every character a position with `--position "<character>=<who and where>"`, a short phrase matching the first frame (`小美=左边的年轻女人`, `Grandpa=the old man in the center`), plus `--line` as usual. With a position for every character, the platform introduces everyone by position, names each speaker by position, orders the lines (`First` / `Next` / `Then` / `Finally`) and closes the speaker's lips after each line while the others listen. Three-person dinner table, same 5 seeds, 2 takes each: lines on the right mouth 36/40 with positions, 32/40 without (a hand-written `raw` version of the same pattern: 39/40); unrequested close-ups in 4, 5 and 2 of 10 takes. If any character lacks a position the normal format is used and `h3 submit` prints a reminder.

```bash
h3 submit --mode i2v --first-frame table.png --aspect 9:16 --seconds 8 --segments 2 \
  --character 小美=front --character 爸爸=front --character 阿强=front \
  --position 小美=左边的年轻女人 --position 爸爸=中间的老人 --position 阿强=右边的男人 \
  --prompt "A medium-wide shot of a family dinner table in a warm dining room in the evening. 爸爸 sits at the center, 小美 on the left, 阿强 on the right. The camera holds a static shot in one continuous shot." \
  --line "爸爸:picks up his chopsticks=今天谁做的饭？" --line "小美:points at 阿强=是阿强做的。" --line "阿强:pushes a dish toward 爸爸=爸，您尝尝。"
```

- Still say in the prompt where everyone sits and that it is one continuous shot.
- Positions work only in `i2v` without `--raw`. To build on the pattern in `raw` (e.g. to add shots), submit once with `--position`, copy `promptFinal` from `h3 status <job>` and edit it; numbering rules below.

**Numbers in `raw` with characters** (get them wrong and faces or voices go to the wrong person):

- `<Picture 1>` is the first frame; then each character's photos, grouped in `--character` order.
- **Every photo at a listed angle is used** while the 8 slots last (each character's front photo first, then in turns): a character with three `front` photos and `=front,three_quarter_left` takes 4 slots. Count with `h3 character show <character>` before numbering.
- `<Audio n>` is the n-th character in `--character` order (not speaking order); `(S1)`, `(S2)` follow speaking order.

**A line that must land on one person: shot / reverse shot.** In `raw`, put each line inside its own shot: `[Shot 2] At 00:02.000, the camera cuts to a medium close-up of <Subject 2>, the man in the navy t-shirt, framed alone in the same kitchen. <Subject 2> (S2) … says … <d>…</d> His lips close as he finishes.` Tested: every line on the right person. Costs: at most two cuts in 8 s (the third cut morphed in both takes), and close-ups lose the first frame's background, so attach the scene image with `--ref "other:kitchen=kitchen.png"`. This is also how to pin a line to a moment: the cut time is the anchor.

**One speaker per clip, then `h3 concat`**: safe for the mouth, but a 4 s two-shot with one line still cut to the silent listener's close-up in 2 of 4 takes; check it the same way.

**Off-screen voice** (a character heard but not seen): still pass the character with `--character <name>=full_back` so it brings a voice but no face; in the prompt say it stays in the next room and never appears. The on-screen person's lips moved with the off-screen line in 2 of 4 takes, `raw` wording no better: make two takes and pick, or put that line in its own clip.

**Character photos**: don't build a character from frames of generated videos; tried here, burned-in captions appeared in 6 of 10 takes.
