H3 Studio API

← 返回生成页 Swagger 调试台 ↗ openapi.json ↗

在一张 RTX 5090 上运行的 MiniMax-H3 视频生成服务。文生视频、图生视频(1 到 6 张图),输出 24 fps 带立体声的 mp4。任务在单卡上顺序执行,新任务自动排队。

口令

地址与鉴权

公网https://desktop-lp9ii17.tail97a7d2.ts.net
本机http://127.0.0.1:8000

所有 /api/* 请求都需要口令,三种传法任选一种:

推荐Authorization: Bearer <TOKEN> 请求头
备选x-token: <TOKEN> 请求头
备选?token=<TOKEN> 查询参数

口令错误或缺失返回 401 {"detail":"bad token"}。口令保存在服务器的 webapp/config.json,修改后重启服务生效。已开启 CORS,浏览器页面可以直接跨域调用。

接口一览

方法路径说明
POST/api/v1/generate用 JSON 创建任务。文生视频,或图生视频(图片给 URL 或 base64)。可选同步等待、完成回调。
POST/api/jobs同上,multipart 表单版本,图片作为文件字段 images(可多个)。网页就是用的这个。
POST/api/v1/tts声音克隆:Qwen3-TTS 学一段参考人声,念给定文字,返回 wav 地址。也有 multipart 版 /api/tts
POST/api/v1/imageQwen-Image-2.1:用 JSON 创建文生图或改图任务(0 到 10 张参考图,URL 或 base64)。可选同步等待、完成回调。
POST/api/images同上,multipart 表单版本,图片作为文件字段 images。网页就是用的这个。
GET/api/jobs任务列表(视频和图片任务混排),最新在前。
GET/api/jobs/{id}单个任务。加 ?wait=true&timeout=600 会阻塞到完成或超时。
GET/api/jobs/{id}/video下载成品 mp4(H.264 + AAC 立体声 32 kHz)。
GET/api/jobs/{id}/image下载成品 png(图片任务)。
DELETE/api/jobs/{id}排队中:取消;生成中:中断;已完成:删除任务和文件。
GET/api/statusComfyUI 是否在线、当前任务 id、排队数。
GET/api/config可用的模型方案、尺寸表、时长选项。
GET/out/{id}.mp4 · /out/{id}.png成品的静态地址(可直接放进 <video src> / <img src>,无需口令)。

创建任务 POST /api/v1/generate

请求体 JSON,所有字段除 prompt 外都可省略:

字段类型默认说明
promptstring必填画面、镜头运动和声音的描述,中英文均可。引号里的台词会做口型同步。
profilestringfasth3fasth3 画质最好(8 步)· turbo_int8 均衡(8 步)· fasth3_4step_int8 最快(4 步)
aspectstring16:916:9 · 9:16 · 1:1
resstring480p352p · 480p · 768p,实际像素见下方尺寸表
secondsnumber51 到 15 秒。帧数会向上取整到模型的 17k+5 帧网格(24 fps),例如 5 秒 → 124 帧 = 5.17 秒
seedint-1-1 表示随机。相同参数和 seed 可复现
stepsint00 表示用方案默认(8 或 4),一般不用改
imagesstring[][]0 到 6 张。每项是 https://… 图片地址,或 data:image/png;base64,…。用法由 image_mode 决定。关键帧模式:1 张 = 首帧;2 张 = 首帧 + 末帧;3 到 6 张 = 首帧、末帧,其余按顺序均匀锚定到时间轴,图片会被缩放裁切到目标画幅。参考模式:全部作为参考图
image_modestringkeyframekeyframe 图片钉在对应帧上,视频首帧就是第 1 张图 · reference 图片只提供人物 / 物体 / 风格,视频不从图片开始。提示词里用 <Picture 1><Picture 2> 指代各张图,不写会自动加在开头
audiosstring[][]0 到 3 段音频(每段 2 到 15 秒),https://…data:audio/wav;base64,…。用法由 audio_mode 决定
audio_modestringvoicevoice 音色参考:H3 用这段声音的音色,自己念提示词里的台词,提示词里用 <Audio 1> 指代(不写会自动加上;带图片时自动切到参考图模式)· track 音轨:第 1 段音频原样作为视频音轨从第 0 帧铺满,画面对口型
tts_textstring填了就走克隆朗读:Qwen3-TTS 学 audios[0] 的音色念这段话,合成结果作为音轨对口型(等价于 track 模式)。可配 tts_ref_text(参考音频原文,可选)和 tts_language(Auto / Chinese / English …)
waitboolfalsetrue 时请求阻塞到任务完成再返回最终任务对象
timeoutint600wait 的最长等待秒数,上限 1800;超时返回当时的状态(任务继续跑)
callback_urlstring任务结束(成功或失败)后把任务对象 POST 到这个地址,JSON 格式

返回值就是任务对象;不带 wait 时立即返回,状态为 queued

multipart 版本 POST /api/jobs

字段名与上表相同(prompt, profile, aspect, res, seconds, seed, steps),图片放在一个或多个 images 文件字段里。不支持 waitcallback_url,拿到 id 后用 GET /api/jobs/{id}?wait=true 等待即可。

文生图 / 改图 POST /api/v1/image

Qwen-Image-2.1(7B,2026-09-20 发布):不传图就是文生图;传 1 到 10 张图就是改图 / 多图参考,提示词里用 Picture 1Picture 2 指代各张图(按传入顺序)。支持中英文文字渲染。返回值同样是任务对象,成品字段是 image。实测(25 步,模型已加载):qwen21 1K 约 4.5 秒、2K 约 27 秒;qwen21_bf16 1K 约 8 秒、2K 约 46 秒;单图改图 1K 约 7 秒;krea2_turbo 1K 约 3.3 秒、2K 约 18 秒,带 1 张风格参考约 8 秒。切换模型后的第一次调用多约 5 到 20 秒加载。

字段类型默认说明
promptstring必填要画的画面;有图时是修改指令
negative_promptstring""负面提示词,只在 cfg 大于 1 时生效
profilestringqwen21qwen21 Qwen-Image-2.1 INT8(默认,文生图 + 改图)· qwen21_bf16 全精度,约慢一倍 · krea2_turbo Krea 2 Turbo 12B NVFP4,8 步蒸馏,偏艺术审美,文生图 + 风格参考(不能改图)· krea2_turbo_int8 同上 INT8 版
aspectstring1:11:1 · 16:9 · 9:16 · 4:3 · 3:4
resstring1K1K 约 100 万像素 · 2K 约 400 万像素(模型原生 2048²)。改图时参考图也按这个档缩放
sizestring直接指定 宽x高(32 的倍数,256 到 4096),给了就忽略 aspect/res
size_from_refboolfalse改图时输出尺寸跟随第 1 张图(缩放到 res 档),适合保持构图的局部修改
seedint-1-1 随机
stepsint00 = 方案默认 25
cfgnumber00 = 方案默认 1.0(引导已蒸馏进模型,一般不用改)
imagesstring[][]https://…data:image/png;base64,…。qwen21:0 到 10 张,作为改图 / 参考对象;krea2:0 到 3 张,只借用画风、色调、质感,内容不保留
wait / timeout / callback_url同视频任务,timeout 默认 300

尺寸表

画幅1K2K
1:11024×10242048×2048
16:91344×7682752×1536
9:16768×13441536×2752
4:31152×8642304×1728
3:4864×11521728×2304

curl · 文生图,同步等结果

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/image \
  -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
  -d '{"prompt":"一张咖啡馆海报,手写体中文标题「晨光咖啡」,暖色调,胶片质感","aspect":"3:4","res":"1K","wait":true}'
# → {"id":"…","status":"done","image":"/out/….png","image_download":"/api/jobs/…/image",…}

curl · Krea 2 Turbo 文生图 + 一张风格参考

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/image   -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json"   -d '{"prompt":"a lighthouse on a rocky coast at dawn, mist, golden light",
       "profile":"krea2_turbo","images":["https://example.com/watercolor_style.jpg"],
       "aspect":"16:9","res":"1K","wait":true}'

curl · 改图,两张参考图

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/image \
  -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
  -d '{"prompt":"让 Picture 1 里的人穿上 Picture 2 的外套,保持姿势、背景和光线不变",
       "images":["https://example.com/person.png","https://example.com/coat.png"],
       "size_from_ref":true,"res":"1K"}'

curl · 上传本地图片改图(multipart)

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/images \
  -H "Authorization: Bearer <TOKEN>" \
  -F "prompt=把背景换成雪山日出,其它保持不变" -F "size_from_ref=true" \
  -F "images=@photo.png"

任务对象

{
  "id": "20260918_202901_6197",
  "kind": "video | image",                // image = Qwen-Image-2.1 任务
  "status": "queued | running | done | failed",
  "prompt": "…", "profile": "fasth3", "mode": "t2v | i2v | t2i | edit",
  "aspect": "16:9", "res": "480p", "size": "864x480",
  "seconds": 5.0, "frames": 124, "seed": 1234, "steps": 8, "image_count": 0,
  "created": 1789731030.1,

  "position": 1,                          // queued:队列位置(1 = 下一个)
  "progress": {"value": 3, "max": 8},     // running:采样步进度
  "stage": "采样", "elapsed": 12.3,        // running:当前阶段、已用秒数

  "exec_s": 24.7,                         // done:生成耗时(秒)
  "video": "/out/20260918_202901_6197.mp4",             // done(视频):可直接播放的静态地址
  "video_download": "/api/jobs/20260918_202901_6197/video",  // done(视频):带文件名的下载地址
  "image": "/out/….png", "image_download": "/api/jobs/…/image",  // done(图片):同上;另有 negative, cfg, size_from_ref
  "finished": 1789731060.2,

  "error": "…",                           // failed:原因
  "callback_status": 200                  // 设置了 callback_url 时:回调的 HTTP 状态
}

stage 依次经过:加载模型 → 加载文本编码器 → 编码提示词/图片 → 采样 → 视频解码 → 音频解码 → 封装 → 保存。模型只在切换方案时重新加载。

可选值

尺寸表(宽×高,均为 32 的倍数)
352p480p768p
16:9608×352864×4801344×768
9:16352×608480×864768×1344
1:1480×480672×6721024×1024
模型方案
profile步数特点
fasth38FastH3 8 步完整模型,画质最好,默认
turbo_int88Turbo LoRA,风格略不同,速度相近
fasth3_4step_int84最快,细节稍软

时长:任意 1 到 15 秒,网页上给的是 5 / 8 / 10 / 15。

耗时参考

RTX 5090,fasth3 8 步,实测每条片子的生成耗时(不含排队):

分辨率5 秒10 秒采样速度备注
352p≈ 13 s≈ 26 s1.8 s/步预览、快速试提示词
480p≈ 27 s≈ 54 s4.5 s/步速度与可看度的折中
768p≈ 90 s≈ 178 s18.2 s/步最高画质,10 秒片显存接近 32 GB 上限

fasth3_4step_int8 采样步数减半,整体约快 30% 到 40%。切换方案的第一条任务多 3 到 10 秒加载时间。同一时间只跑一个任务,排队时间 = 前面任务的耗时之和。

调用示例

curl · 文生视频,同步等结果,然后下载

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/generate \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"一只戴墨镜的小熊猫在舞台上打鼓,暖色聚光灯,观众欢呼,电影感。声音:鼓点、欢呼声。","res":"480p","seconds":5,"wait":true}'

# 返回的 JSON 里 status 为 done 时:
curl -L -o clip.mp4 -H "Authorization: Bearer <TOKEN>" \
  https://desktop-lp9ii17.tail97a7d2.ts.net/api/jobs/<id>/video

curl · 图生视频,两张图(首帧 + 末帧),不等待

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/generate \
  -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
  -d '{"prompt":"镜头缓慢推进,画面从第一帧过渡到最后一帧。声音:轻柔的风声。",
       "images":["https://example.com/first.png","https://example.com/last.png"],
       "res":"480p","seconds":5}'
# → {"id":"2026…","status":"queued",…}

curl -s -H "Authorization: Bearer <TOKEN>" \
  "https://desktop-lp9ii17.tail97a7d2.ts.net/api/jobs/<id>?wait=true&timeout=600"

curl · 参考图模式(视频不从图片开始)

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/generate \
  -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
  -d '{"prompt":"<Picture 1> 里的女孩走进咖啡馆,坐到窗边翻开一本书,镜头缓慢推近。声音:咖啡馆环境音。",
       "images":["https://example.com/girl.png"], "image_mode":"reference",
       "res":"480p","seconds":5}'

curl · 声音克隆朗读台词并对口型

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/v1/generate \
  -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" \
  -d '{"prompt":"<Picture 1> 里的老人站在灯塔窗前,面部特写,认真地对着镜头说话,口型清晰。声音:他的声音,雨声。",
       "images":["https://example.com/keeper.png"],
       "audios":["https://example.com/keeper_voice.wav"],
       "tts_text":"海上的风很大,你要小心。今晚我会一直守在这里。",
       "tts_ref_text":"别怕,灯还亮着。我在这儿等你回来。", "tts_language":"Chinese",
       "res":"480p","seconds":5}'

只想要语音不要视频:POST /api/v1/tts,JSON 字段 textref_audioref_text(可选)、language,同步返回 {"audio":"/out/tts_….wav"}

curl · 上传本地图片(multipart)

curl -s https://desktop-lp9ii17.tail97a7d2.ts.net/api/jobs \
  -H "Authorization: Bearer <TOKEN>" \
  -F "prompt=The scene comes alive, gentle camera drift. Audio: ambient." \
  -F "res=480p" -F "seconds=5" \
  -F "images=@first.png" -F "images=@middle.png" -F "images=@last.png"

Python · 轮询进度并下载

import base64, time, requests

BASE = "https://desktop-lp9ii17.tail97a7d2.ts.net"
H = {"Authorization": "Bearer <TOKEN>"}

def data_uri(path):
    return "data:image/png;base64," + base64.b64encode(open(path, "rb").read()).decode()

job = requests.post(f"{BASE}/api/v1/generate", headers=H, json={
    "prompt": "A golden retriever puppy runs through autumn leaves, slow motion. Audio: leaves crunching.",
    "images": [data_uri("first.png")],      # 可省略 → 文生视频
    "res": "480p", "seconds": 5, "seed": 42,
}).json()

while job["status"] in ("queued", "running"):
    time.sleep(3)
    job = requests.get(f"{BASE}/api/jobs/{job['id']}", headers=H).json()
    print(job["status"], job.get("position"), job.get("stage"), job.get("progress"))

if job["status"] == "done":
    mp4 = requests.get(BASE + job["video_download"], headers=H).content
    open("clip.mp4", "wb").write(mp4)
    print("saved, generation took", job["exec_s"], "s")
else:
    print("failed:", job.get("error"))

JavaScript · 浏览器 fetch,同步等待后直接播放

const BASE = "https://desktop-lp9ii17.tail97a7d2.ts.net";
const r = await fetch(BASE + "/api/v1/generate", {
  method: "POST",
  headers: { "Authorization": "Bearer <TOKEN>", "Content-Type": "application/json" },
  body: JSON.stringify({ prompt: "城市夜景航拍,霓虹反射在湿润的街道上。声音:车流、雨声。", res: "352p", seconds: 5, wait: true })
});
const job = await r.json();
if (job.status === "done") document.querySelector("video").src = BASE + job.video;   // /out/… 不需要口令

回调模式

提交时带 "callback_url": "https://你的服务器/hook",任务结束后会向该地址 POST 一份任务对象(成功和失败都会发)。video 是相对路径,拼上 BASE 即可下载;回调的 HTTP 状态会记录在任务的 callback_status

错误与限制

状态码含义
400参数错误:未知 profile / aspect / res,prompt 为空,seconds 不在 1 到 15,图片下载失败或格式不对,图片超过 25 MB。detail 里有原因
401口令缺失或错误
404任务不存在,或视频尚未生成完成
422JSON 字段类型不对(FastAPI 校验),返回里逐字段说明