---
name: h3-video
description: Make videos and songs on the H3 video platform (minimax.xxt.ai, powered by MiniMax H3) — lip-sync (a photo sings or talks to a voice track), image-to-video with first frame or first + last frame, text-to-video, free shots (no first frame: characters or photos plus text, steady with big motion and wide shots; saved characters keep face and voice consistent), promo videos (a character pitches products), motion swap (swap the person in a video for the person in your photos), and songs (lyrics + style, two tracks per run). Use when the user wants to make a video, animate a picture, lip-sync a photo, shoot MV shots or chain shots into a longer video, or write and generate a song (做视频、让图片动起来、对口型、出歌、写歌). Works through the h3 CLI and spends the user's account credits.
---

# H3 video generation

Platform: https://minimax.xxt.ai . You work through the `h3` CLI; every command prints JSON. Talk to the user in their language; the platform's error `message`s are in Chinese.

Read these when needed:

- [references/prompting.md](https://minimax.xxt.ai/references/prompting.md): **read before writing your first prompt for a user.**
- [references/characters.md](https://minimax.xxt.ai/references/characters.md): before creating or using characters, or making promo videos.
- [references/songwriting.md](https://minimax.xxt.ai/references/songwriting.md): before any song; all song and My Voice commands.
- [references/motion-swap.md](https://minimax.xxt.ai/references/motion-swap.md): motion swap.
- [references/api.md](https://minimax.xxt.ai/references/api.md): only if you write your own HTTP client.

`h3 skill install --host <you>` saves these files where your agent reads skills and keeps them updated: `claude` (Claude Code, the default), `codex`/`agents` (`~/.agents/skills`, also read by Cursor, Gemini CLI, OpenCode, Copilot), `cursor`, `gemini`, `opencode`, `copilot`, `all` (Claude Code + `~/.agents`); `--dir <dir>` for elsewhere. A short-drama series (episodes, shot tables, subtitles, an ending MV): `h3 skill install drama` (after login) adds the h3-drama, drama-finish and drama-mv skills, kept up to date the same way.

## 1. Install and sign in

`h3` is one Python file, standard library only, Python 3.9+.

```bash
mkdir -p ~/.local/bin
curl -fsSL https://minimax.xxt.ai/h3.py -o ~/.local/bin/h3 && chmod +x ~/.local/bin/h3
h3 --version          # if not found: ~/.local/bin/h3 or python3 ~/.local/bin/h3 (Windows: save as h3.py, run python h3.py)
```

**`h3` updates itself** (CLI and saved skill files) when the platform has a new version. If output contains `h3Update`, re-read SKILL.md and carry on; no need to tell the user. If `h3Update.status` is `failed`, the command still worked; with the user's consent re-download as above and run `h3 skill install`. `h3Notice` means an old CLI that can't self-update: do what it says once. `h3 update` checks now; `H3_NO_AUTO_UPDATE=1` only reports.

Sign in with a link:

1. `h3 login --no-wait`; send the user `verificationUrlComplete` and `userCode` exactly as returned: open the link (valid 10 minutes), sign in, check the code, click Authorize (「授权」).
2. Then run `h3 login --wait` (waiting rules in section 2). It saves the key and returns the email and credits. `login_denied` / `login_expired`: ask the user, then start over.
3. `"alreadyLoggedIn": true` means the saved key works; `--force` switches accounts.

If the user hands you an API Key, pass it on stdin, never as an argument: `printf '%s' 'h3_…' | h3 login --with-key` (or env `H3_API_KEY`). Never write the key into project files or repeat it in full.

Then run `h3 modes` once: it is authoritative for each mode's durations, assets and upload limits.

## 2. Making a video: the steps every time

1. Pick the mode and assets (section 3), write the prompt (section 4).
2. **Price check**: run the same `h3 submit` command with `--dry-run` (uploads and holds nothing). Tell the user the exact `credits`, and `waitSeconds` + `estimateSeconds` for the time; `enough: false` → section 5. Above 1000 credits at once, or before a batch, ask first.
3. Submit (same command without `--dry-run`). **Give the user the job's `webUrl` right away**: they can watch progress, play and download in the browser.
4. **Output carries `next`: the concrete next step. Follow it** (wait, download, resubmit, or what to tell the user).
5. After downloading, give the user **the full path of each file** and the `webUrl`, and remind them: Videos, songs and uploaded files are kept for 8 hours after the job ends, then deleted automatically. Please download them in time.

```bash
h3 submit --mode i2v --first-frame shot1.png \
  --ref front=face_front.jpg --ref three_quarter_left=face_left.jpg \
  --aspect 9:16 --seconds 6 \
  --prompt "A medium shot frames the girl standing by the river at dusk. She slowly turns her head toward the camera and smiles softly as the evening breeze lifts her hair. The camera holds a static shot." \
  --dry-run             # then the same without --dry-run, plus --wait --out ./out; local files upload automatically
```

**Waiting** (`h3 login --wait`, `submit --wait`, `h3 wait`, `h3 song … --wait`): progress on stderr with `[h3]`. Default limit 540 s, then exit code 4 while the job keeps running; run the wait again (`h3 wait <job-id> --out ./out` also downloads when done). If your shell tool has a time limit, set `--timeout` below it.

**Review**: `h3 submit` returns once the platform has checked the content (seconds; a few minutes when many jobs are waiting). It queues reviews itself, so submit a whole batch at once or in parallel; don't throttle.

Without `--wait`: `h3 status <job-id>` (once), `h3 wait <job-id> [--out ./out]`, `h3 pull <job-id> --out ./out` (two takes → `h3-<id8>-A.mp4`, `-B.mp4`), `h3 cancel <job-id>` (full refund), `h3 jobs` (`--all` for everything).

## 3. Choosing a mode

| Mode | When | Assets | Duration |
|---|---|---|---|
| `lipsync` | A person in a photo sings or talks to a voice track | first frame + voice track (both required) + 0–8 reference images | 2–15 s, **= voice track length** |
| `i2v` | Animate an image; with a last frame, move from first to last | first frame + optional last frame + 0–8 reference images (0–7 with a last frame) | 4–15 s |
| `t2v` | No image; everything from the prompt | none | 4–15 s |
| `ref2v` | Free shot: no first frame; the model frames and moves the shot from characters or person photos and text. Steadier than `i2v` for big motion and wide shots; can't continue a previous shot. Product/scene images allowed (angle `other`). One take | characters + reference images, 1–8 total; no first frame | 4–15 s |
| `swap` | Swap the person in a video for the person in your photos; background and audio stay | `h3 swap --video … --person …`; no prompt; motion-swap.md | 2–60 s |
| `promo` | A character pitches 1–4 products (section 10) | 1 character + product images + optional scene | 4–15 s |

| Flag | Meaning |
|---|---|
| `--aspect` | `9:16` (default, 768×1344), `16:9`, `1:1`. First/last frames should match, else center-cropped |
| `--seconds` | Up to two decimals; credits round up to whole seconds |
| `--segments 2` | Two takes (A, B) to pick from; double credits (not `ref2v` or `promo`) |
| `--resolution 1080p` | Upscaled to 1080p; ~30 s longer, **double credits** (default `768p`) |
| `--seed` | Fixed seed, for comparing prompt tweaks |
| `--idempotency-key` | Auto-generated; when retrying the same submission yourself, reuse it so only one job is created |

### Assets

- **First frame** sets scene, composition, clothes, light; short side ≥ 720 px. **Last frame** (`i2v`): same scene and person, or it jumps. **Voice track** (`lipsync`): clean vocals (only a mixed song? separate the vocals first); it becomes the clip's audio as is; over 15 s, cut into several clips.
- **Whenever a person is on screen, attach a character (`--character`) or person reference images (`--ref`)**, first-frame and lip-sync modes included; else faces drift, and small faces in wide shots blur. Saved character: `--character` attaches all its photos. Else 3–5 sharp close-ups, one at the angle the person faces in the shot; not faces cropped from the first frame.
- `--ref <angle>=<file>` angles: `front`, `three_quarter_left` (the person's left cheek toward the camera), `three_quarter_right`, `side` (faces); `full_front`, `full_back` (full body); `other` with a note: `--ref "other:the guitar in her hands=guitar.png"`.
- Images JPG/PNG/WebP ≤ 10MB; audio MP3/WAV/M4A/AAC/FLAC/OGG ≤ 20MB. Reuse an upload within retention as `asset:<asset-id>` (ids in the job's `inputs` or from `h3 upload <files…>`).

### Several shots (MV, longer videos)

Plan a shot list; every shot keeps the same `--character`/`--ref`, scene image and `--aspect`. Join the finished clips in order with `h3 concat out.mp4 part1.mp4 part2.mp4@0.6+2.8 …` (local ffmpeg; `@start+length` keeps only that part and re-encodes once).

- **Cut** between shots: each shot gets its own first frame (or `ref2v`); submit them all at once.
- **Continuous** (one take flowing into the next): `--first-frame job:<job-id>[:B]` uses that take's last frame (local ffmpeg; take A or the first finished one by default), so these shots go one after another. Write the prompt starting from that picture. If the last frame may be blurred or mid-blink, `h3 frame job:<job-id>` saves it as PNG to look at first (`--at <seconds>` for another frame), then `--first-frame <png>`.

## 4. Prompts

**Read [references/prompting.md](https://minimax.xxt.ai/references/prompting.md) before your first prompt.** Essentials:

- **Write only the scene description, in English**; the platform translates leftovers and adds H3's format, alignment sentences, `[Shot 1]`, style prefix, reference-image notes, speaker tags and ambient sound. No tags like `<Picture 1>`, no field names, no line breaks.
- Time order from the first frame: who/where/wearing what → action starts → develops → result. Only visible and audible things, shot size, camera = movement + amplitude + speed (`The camera pushes in at fast speed.`; still: `The camera holds a static shot.`). Slow moves stretch every clip: for fast-cut work (short dramas, ads) default to static and cut.
- **Only write what you want**: no negative prompt; `no …` pulls the thing in. Default `in one continuous shot`. Wide-shot faces need a matching-angle reference. 60–150 words per shot. Concrete sounds in `--sound`.
- **Lip-sync**: `--dialogue` is **word-for-word the voice track**, ending with a full stop; describe expression, gestures, camera, not the lyrics. Avoid `restrained`, `subtle`, `almost still`.
- **First + last frame**: one continuous shot ending with `settles into the pose and composition of the final frame`. To cut (works in 4 s): `[Shot 2] At 00:02.000, the camera cuts to ...`, starting that shot in a pose different from the last frame (prompting.md section 4).
- `--dialogue` (one speaker; with characters use `--line`, except in `lipsync`) and `--line` keep the original language. Full control: `--raw` (prompting.md section 3).

```bash
h3 submit --mode lipsync --first-frame girl_river.png --audio verse1.wav --seconds 8.4 --character Mia \
  --prompt "A medium close-up frames Mia standing by the river at dusk, facing the camera. She sings with gentle, expressive facial movement, her right hand resting lightly on her chest, her hair moving in the evening breeze. The camera holds a static shot in one continuous shot." \
  --dialogue "晚风吹过河岸，我还在等你。" \
  --sound "Soft wind over the river, water lapping against the bank, distant birds."
```

## 5. Credits and timing

- **1 credit = ¥0.01. Priced by Singapore time: daytime 10:00–22:00: 9 credits per second; night 22:00–10:00 next day: 6 credits per second.** Seconds round up per take; two takes cost double; 1080p ×2; motion swap ×3. The rate at submission applies. `h3 modes` shows `creditsPerSecond`, `pricing` and `pricing.until`; for non-urgent clips mention night is cheaper.
- Held at submission, settled per take: success = full; delivered with QC failed = half; failed or canceled = refunded.
- `--dry-run` (section 2) gives the exact hold; not enough credits → shorten, one take, 768p, wait for night, or buy.
- Buying: `h3 buy <credits> [--currency CNY|USD]` (10000 to 1000000 credits) prints a Stripe link for the user to pay; don't pay it yourself. Check with `h3 orders <id>` or `h3 me`. Purchased credits don't expire and aren't refundable.
- Generation takes about half a minute per video second. The job's `estimateSeconds`, `queueAhead`, `waitSeconds` and `h3 queue` give the wait; don't speculate about machine counts.

## 6. Results

`segmentsDetail` lists each take: `status`; `qc` (usually `null`: no automatic check, so have the user watch; `passed: false` + `reasons`: half charged, still downloadable); `charged`; `error` (refunded; `next` says whether to resubmit unchanged or change inputs). Clips may run slightly longer than `--seconds` (billed by `--seconds`). If unhappy, fix the prompt first; for a different random result, resubmit without `--seed`. With characters or `--ref` images, a take now and then dissolves into one of the reference photos (plain backdrop) or cuts to a close-up partway through. This comes from the random seed, not the prompt, so rewording doesn't help; it is most common in wide shots with many people. Resubmit without `--seed`, or use `--segments 2` and pick.

## 7. Errors

Non-zero exit; the last stderr line is `{"error": "<code>", "message": "…", "next"?: "…"}`. Read `message`, then do `next` when present. Beyond that:

- `content_blocked`: nothing charged (a job already created is failed and refunded). No porn, exposed nipples or sexualized minors; tell the user, never work around it.
- `create_timeout`, `audition_timeout`: the platform may have finished; check `h3 character list` before retrying.
- `unrecognized arguments`: `h3 update`; still unknown → re-download (section 1).

Exit codes: `0` ok; `1` API/network; `2` usage or local file; `3` job failed/canceled; `4` wait timed out (still running). Full code list: api.md.

## 8. Other commands

`h3 me`, `h3 usage`, `h3 ledger` (credits); `h3 modes`, `h3 queue`; `h3 upload <files…>`; `h3 frame <video|job:<id>> [--at last|first|<s>]` (one frame as PNG); `h3 concat out.mp4 part1.mp4 …`; `h3 character …` (section 9); `h3 song …`, `h3 voice …` (section 12); `h3 feedback …` (section 13); `h3 logout`; `h3 <command> --help` for all flags.

## 9. Characters

For a person in several shots, create a character once (face photos + voice) and reuse it with `--character <name or id>` (`ref2v`, `i2v`, `lipsync` (one), `promo`); face and voice stay consistent. Lines: `--line "<character>:<action>=<text>"`, at most 3 speakers per shot. With characters, `--ref` takes only `other` images (scene, product, prop); every speaker needs a voice: for a stock role (child, grandpa, CEO, livestream host…) pick one of the 14 free voice templates (`--voice-template`, list with `h3 character voice-templates`), else design one; `h3 submit` designs a temporary one if missing; tell the user, who can change it later. Use names directly in the prompt. Pick angles per shot: `--character Mia=front,side` (always include `front`). **Two people of the same sex who both speak in one clip: the model hands out the voices by looks, not by character, and often gives each the other's: shoot them as shot / reverse shot, one speaker per clip. Two or three people talking in one shot: read characters.md section 6 first** (two people: `--line` and say who stands where; three or more in `i2v`: also `--position` for each); always `--segments 2` and check a frame inside each line. **You cannot hear audio**: give the user the listening link (`h3 character voice <character>`). Commands and voice design: [references/characters.md](https://minimax.xxt.ai/references/characters.md).

## 10. Promo videos

One character (with a voice) pitches 1–4 products; portrait, one take, 4–15 s, lines ≤ 30 units. `--off-camera`: the host is not shown, only their voice narrates over a first-person view of hands holding the products. Longer videos: `--part <n>/<total>` per clip, then `h3 concat`. Read characters.md section 5 first.

## 11. Motion swap

`h3 swap --video dance.mp4 --person front.jpg,three_quarter.jpg,full_body.jpg` swaps the person in a motion video (up to 60 s) for the person in the photos (up to 4 people: one `--person 照片…=role` each, 9 photos in total); **no prompt** (the platform writes it), only the people are redrawn, background and original audio stay; `--no-lip-sync` when nobody sings or talks. Read [references/motion-swap.md](https://minimax.xxt.ai/references/motion-swap.md) first.

## 12. Songs

Lyrics + style; **each run makes two tracks**. **Read [references/songwriting.md](https://minimax.xxt.ai/references/songwriting.md) before any song** (no real artist or song names in lyrics or style).

- 100 credits per track; **tell the user 200 credits will be held** per run. Failed tracks are refunded.
- `h3 song create --lyrics-file lyrics.txt --title "…" --style "…" --voice-template gentle-female --wait --out ./out`. Show AI-written lyrics (`h3 song lyrics "<idea>"`) to the user before generating.
- **On a network error, check `h3 song list` before resubmitting**: songs have no duplicate protection.
- Give the user the `webUrl`, the full paths and the retention reminder (section 2).

**My Voice** (`--my-voice`): sing in the user's own voice. **The agent cannot record for the user: both the a cappella take and the verification phrase must be recorded by the user in person** (or on the website's 「出歌」 page). Only new recordings of the user's own voice: no synthesis, other people's or old recordings. Read songwriting.md section 6 before any `h3 voice` command. Use `--consent` only after the user explicitly agrees to this text, shown verbatim; never agree on their behalf:

> 我确认这是我本人的声音，我已年满 18 岁，同意把录音交给出歌服务生成声音模型（可能涉及生物特征信息）。
> (I confirm this is my own voice, I am at least 18, and I agree to give the recordings to the song service to build a voice model, which may involve biometric information.)

## 13. Feedback

When the platform or these instructions get in your way (a bug, an error you couldn't resolve, wrong or missing instructions, something the user wishes worked differently), send one short note:

`h3 feedback "<what you did, what happened, what you expected>" --kind bug|docs|idea [--scenario mv|drama|motion_swap|product_ad|song|other] [--job <id>] [--song <id>] [--image shot.jpg]`

About a video: always pass `--job` and attach 1–4 frames showing the problem (`h3 frame out.mp4 --at <s>`); videos are deleted after 8 hours, screenshots are kept. No API keys or personal data; one note per problem (limit 20 per day). Tell the user in one line. `h3 feedback --list` shows replies.
