MiniMax 对口型视频(ia2v)
输入一张人像图、一段音频和文本 prompt,输出节奏精准的演唱或讲话短视频。使用你自己的 API key 在线测试,或阅读接口文档。
API key
输入 API key 以便提交或查询任务。
创建对口型任务
以下字段与 POST /aigc/task(task_type: "minimax_ia2v")的请求体一一对应。
或查询已有任务
Result
请求日志
本页面向 API 发出的所有请求按顺序记录,最新的排在最前。
暂无请求记录。
Demo 演示视频
更多对口型演示视频
流行女声演唱 (5s)
4/3女声唱跳 (17s)
9/16流行男声 (8s)
9/16概览
MiniMax Lip Sync Video(minimax_ia2v)能把一张人像图和一段音频,变成一段演出视频:角色的嘴部动作与微表情由图片和音频共同驱动,口型会跟随实际唱的或说的内容走。这是单次调用——立即拿到一个 task_id,通常一分多钟就能生成好。
基础配置
| 配置项 | 值 |
|---|---|
| Base URL | https://api.foxaihub.com/api/v2 |
| 鉴权头 | api-key: YOUR_API_KEY |
| task_type | minimax_ia2v |
Warning: 请求头名字是 api-key,不是 api_key。任何余额大于 $0 的账户都能提交——不像 Music Video 流水线那样有单独的最低余额门槛。
接口一览
| 接口 | 用途 |
|---|---|
| POST /aigc/task | 提交一个图片+音频生成视频(对口型)的任务 |
| POST /aigc/task/wait | 提交任务并阻塞等待,直到任务结束或超时 |
| GET /aigc/task?ids= | 读取一个或多个任务的状态与结果 |
这与 Music Video 流水线里对口型镜头背后是同一套模型,这里以直连、单次调用的形式开放出来——没有分镜,没有多阶段状态机,只是一张图、一段音频、一句 prompt。
参数与约束
所有参数都放在建单请求的 params 对象里。每一项都会在扣费之前完成校验——传值不合法会返回 400,且不会扣费。
| 字段 | 类型 | 必填 | 约束 |
|---|---|---|---|
| image | string(URL) | 是 | 可公开下载的 http(s) URL——不接受 base64 |
| audio | string(URL 或 base64) | 是 | 可公开访问的 http(s) URL,或不超过 30MB 的 base64 Data URL。驱动口型——见下方说明 |
| prompt | string | 是 | 描述这段表演——表情、情绪强度、镜头取景 |
| resolution | string | 是 | "768p" 或 "1080p" |
| aspect_ratio | string | 是 | "1:1"、"4:3"、"3:4"、"16:9"、"9:16" 之一 |
| duration | integer(秒) | 是 | 3–15 |
Note: 实际生成像素由 resolution + aspect_ratio 在服务端查表换算得到。像 9:16 这样的竖屏比例是演唱/说话类角色最常用的选择——768p + 9:16 是 768×1344,1080p + 9:16 是 1088×1920。768p 下另外四档是 1:1 = 768×768,4:3 = 1024×768,3:4 = 768×1024,16:9 = 1344×768;1080p 对应为 1:1 = 1088×1088,4:3 = 1440×1088,3:4 = 1088×1440,16:9 = 1920×1088。
音频怎么传:URL 或直接上传
如果音频已经放在某个可公开访问的地址上,直接传 URL——我们不会复制它,同一个 URL 反复请求也不产生额外开销。如果文件只在你本机,就内联上传:把整个文件以 base64 Data URL 的形式放进 params.audio(解码后最大 30MB),我们会把它存到 CDN 上、把 params.audio 改写成生成的 URL,再用这个 URL 建单。调试台的「上传文件」标签走的就是这条路。注意 image 没有内联形式,仍然必须是可公开访问的 URL。
{
"task_type": "minimax_ia2v",
"params": {
"image": "https://example.com/portrait.jpg",
"audio": "data:audio/mpeg;base64,SUQzBAAAAAA...",
"duration": 5
}
}
Note: 内联上传是为了方便临时试跑,不是文件托管服务:存下来的文件是临时的,而且每次请求都要把整首歌重新传一遍。生产环境——尤其是同一首歌要出多个镜头——请把音频托管一次,然后传 URL。
音频如何驱动口型
- 我们从你的音频开头取 duration 秒——不传就是取开头这一段,多个镜头需要不同片段的话,请提前把音频切好再分别上传。
- 截取是在解码后的波形上做的,样本级精确——窗口长度就是 duration 秒,不会多一帧也不会少一帧。
- 实际片段长度是 min(音频真实长度, duration)。如果音频比 duration 短,片段就会提前结束。
- 计费始终按你请求的 duration 计算,不是按实际片段长度——音频较短不会退回差价。
- 如果音频 URL 下载失败,整个任务会失败(并按「计费规则」一节自动退款)。
Warning: 如果你确实要自己切音频,千万不要用 ffmpeg 的流拷贝模式(-c copy)。它只能按 MP3 帧边界切,一个「5 秒」的片段实测通常是 4.977 秒、并且整体偏移约 30 毫秒——足以让口型对不上,而容器元数据仍然显示 5 秒,光看元数据发现不了。请改用重编码,并保证长度是整数秒。
如果一定要自己切:安全的 ffmpeg 写法
手工切片只要守住两条就不会失步:一是重编码而不是流拷贝,这样切点落在精确的采样上,而不是最近的压缩帧边界;二是让片段长度是整数秒,这样它刚好填满 duration × 24 + 1 的帧窗口。输出 WAV 最稳妥,因为它完全没有编码器延迟和补齐;输出 MP3 也可以,只要是重编码。
# 推荐 —— WAV,样本级精确,没有编码器补齐
ffmpeg -ss 8 -i song.mp3 -t 5 -ar 48000 -ac 2 -c:a pcm_s16le shot.wav
# 也可以 —— MP3,前提是重编码而不是流拷贝
ffmpeg -ss 8 -i song.mp3 -t 5 -ar 48000 -ac 2 -c:a libmp3lame -q:a 2 shot.mp3
# 千万不要这样 —— -c copy 按帧边界切,会漂移失步
# ffmpeg -ss 8 -i song.mp3 -t 5 -c copy shot.mp3
校验时要数解码出的采样数,而不是看容器时长——恰恰是后者会在流拷贝的切片上撒谎。采样数必须等于采样率乘以片段长度,上面的命令就是 48000 × 5 = 240000。
ffprobe -v error -select_streams a:0 -count_samples \
-show_entries stream=sample_rate,nb_read_samples -of default=nw=1 shot.wav
# sample_rate=48000
# nb_read_samples=240000
为什么时长必须是整数秒
生成按每秒 24 帧运行,视频和驱动它的音频窗口的帧数都按 duration × 24 + 1 计算。小数时长会让两者对不齐,所以只接受 3 到 15 之间的整数。
API 参考
POST /aigc/task
提交一个图片+音频生成视频(对口型)的任务。提交时立即扣费。
Parameters
| Field | Type | Required | Notes |
|---|---|---|---|
task_type |
string | Yes | 必须是 "minimax_ia2v" |
params.image |
string(URL) | Yes | 可公开下载的 http(s) URL |
params.audio |
string(URL 或 base64) | Yes | 可公开访问的 http(s) URL,或不超过 30MB 的 base64 Data URL |
params.prompt |
string | Yes | 表演 / 表情 / 取景 |
params.resolution |
string | Yes | "768p" 或 "1080p" |
params.aspect_ratio |
string | Yes | "1:1" / "4:3" / "3:4" / "16:9" / "9:16" |
params.duration |
integer | Yes | 3-15 秒;同时也是使用的音频长度 |
Request Body
{
"task_type": "minimax_ia2v",
"params": {
"image": "https://example.com/portrait.jpg",
"audio": "https://common.foxai.me/sample_music/jp2.mp3",
"prompt": "她对着镜头演唱,表情温柔,固定机位",
"resolution": "768p",
"aspect_ratio": "9:16",
"duration": 5
}
}
Response
{ "success": true, "task_id": "a42e2c77-ded8-48aa-8aa4-dfd9daa43801" }
Errors
| Status | When | Body |
|---|---|---|
400 |
某个参数校验失败(resolution/aspect_ratio 不在允许范围、时长超范围、image 不是 URL、audio 既不是 URL 也不是能解码的 base64) | {"success":false,"error":"Invalid params for minimax_ia2v: audio: invalid base64"} |
400 |
task_type 未知或已禁用 | {"success":false,"error":"Unsupported task type: minimax_ia2v"} |
401 |
api-key 缺失/无效,或余额为 0 | {"message":"Unauthorized"} |
402 |
扣费本身失败(余额不足) | {"success":false,"error":"Insufficient balance"} |
413 |
请求体过大——内联上传的音频超过 30MB | {"success":false,"error":"Request body exceeds 42008576 bytes"} |
500 |
该 task_type 的定价配置无效 | {"success":false,"error":"Invalid price configuration for task type: minimax_ia2v"} |
POST /aigc/task/wait
与 POST /aigc/task 相同,但会阻塞 HTTP 响应,直到任务到达终态或 wait_timeout 到期。适合不想自己轮询的脚本。
Parameters
| Field | Type | Required | Notes |
|---|---|---|---|
task_type |
string | Yes | "minimax_ia2v" |
params |
object | Yes | 与上面相同的结构 |
wait_timeout |
integer(秒) | No | 1-600,默认 60 |
Request Body
{
"task_type": "minimax_ia2v",
"params": {
"image": "https://example.com/portrait.jpg",
"audio": "https://common.foxai.me/sample_music/jp2.mp3",
"prompt": "她对着镜头演唱,表情温柔,固定机位",
"resolution": "768p",
"aspect_ratio": "9:16",
"duration": 5
},
"wait_timeout": 120
}
Response
任务到达 completed 或 failed 后,返回完整的任务对象(与 GET /aigc/task 的形状相同)。
Errors
| Status | When | Body |
|---|---|---|
408 |
wait_timeout 到期时任务仍在运行 | {"success":false,"task_id":"...","status":"processing","message":"Task wait timeout after 60s"} |
400 / 401 / 402 / 500 |
与 POST /aigc/task 相同 | 见上表 |
GET /aigc/task?ids=
按 id 读取一个或多个任务。免费。响应是一个裸数组,不是对象。
Parameters
| Field | Type | Required | Notes |
|---|---|---|---|
ids |
string | Yes | 逗号分隔的 task id,一次最多 25 个 |
Response
[ { "task_id": "...", "task_type": "minimax_ia2v", "status": "completed", "params": {...}, "data": ["https://cdn.../result.mp4"], "created_at": "...", "queue_time_sec": 4, "generation_time_sec": 58 } ]
Errors
| Status | When | Body |
|---|---|---|
400 |
ids 缺失,或请求的 id 数超过 25 个 | {"error":"Task IDs required"} |
401 |
api-key 缺失或无效 | {"message":"Unauthorized"} |
Webhook 通知
追踪对口型视频任务进度有两种方式:通过 GET /aigc/task?ids= 轮询(或短脚本使用 POST /aigc/task/wait),或者配置 Webhook。在生产环境中我们推荐使用 Webhook——当任务完成或失败时,服务器会自动向你的接口推送通知,无需长连接或高频轮询。
Note: Webhook 在 Dashboard 控制台配置(每个账户对应一个接收地址),配置完成后,所有 AIGC 任务(包括 minimax_i2v 和 minimax_ia2v)在终态时都会自动推送到该地址,直接在你的服务器上接收处理即可。
投递格式
每次投递都是一次带有标准外层的 POST 请求:
{
"event": "task.completed",
"type": "minimax_ia2v",
"delivery_id": "9f2c1a3e-abcd-4d11-8f00-0123456789ab",
"created_at": "2026-08-26T09:31:02.000Z",
"data": {
"task_id": "a42e2c77-ded8-48aa-8aa4-dfd9daa43801",
"task_type": "minimax_ia2v",
"status": "completed",
"params": {
"image": "https://example.com/character.jpg",
"audio": "https://example.com/vocal.mp3",
"prompt": "singing passionately, expressive micro-expressions",
"resolution": "768p",
"aspect_ratio": "9:16",
"duration": 5
},
"data": ["https://cdn.../result.mp4"],
"created_at": "2026-08-26T09:30:10.000Z",
"queue_time_sec": 4,
"generation_time_sec": 58
}
}
| 请求头 | 值 |
|---|---|
| Content-Type | application/json |
| User-Agent | FoxAI-Webhook/1 |
| X-Webhook-Event | 与 body 中的 event 一致(task.completed 或 task.failed) |
| X-Webhook-Type | 与 body 中的 type 一致 |
| X-Webhook-Delivery | 与 body 中的 delivery_id 一致 |
| X-Webhook-Timestamp | 投递时的 Unix 时间戳(秒) |
结果类型
一个地址会收到账户下所有业务的推送,所以 event 表示发生了什么,type 表示这是哪种结果。type 与建单时传入的 task_type 完全一致,可以直接用它来分发处理逻辑:
| type | 结果类型 |
|---|---|
| minimax_ia2v | 对口型视频(图片 + 音频)任务到达终态 |
| minimax_i2v | 图生视频任务到达终态 |
| asr-serverless | 音乐转写任务到达终态 |
| mv | 音乐视频流水线事件 |
| ping | 在 Dashboard 触发的测试投递 |
事件列表
| Webhook 事件 | 触发条件 | data 包含内容 |
|---|---|---|
| task.completed | 任务成功生成 | 完整任务对象,data 数组中包含视频 URL |
| task.failed | 任务生成失败(已自动全额退款) | 包含失败原因的任务对象 |
重试策略
- 每次尝试超时时间为 10 秒。
- 分别在 5 秒、10 秒、20 秒后重试——最多总共 4 次尝试,在约 35 秒内收敛。
- 仅在网络错误、超时、HTTP 408、429 与 5xx 时重试。其余 4xx 状态码不会重试。
- 同一条投递在多次重试中保持相同的 X-Webhook-Delivery(即 delivery_id)——可用作幂等去重。
安全性建议
Warning: 建议在 Webhook URL 中携带一段较长的随机路径或 token 参数。在处理关键业务逻辑时,收到 Webhook 后建议调用 GET /aigc/task?ids= 进行二次确认。
限制与生命周期
任务生命周期
任务只有四种状态,并且只会单向推进:
pending -> processing -> completed
-> failed
| 状态 | 含义 |
|---|---|
| pending | 已接受,等待 GPU worker 领取 |
| processing | worker 正在运行生成 |
| completed | data 里是结果——一个数组,第一项就是视频 URL |
| failed | 出了点问题(包括音频 URL 有问题);扣的钱已自动退回 |
没有固定的 SLA。对口型生成比普通 i2v 稍重一些,通常会比一分钟略长——请用 GET /aigc/task?ids= 轮询,或用 POST /aigc/task/wait,而不要假设一个固定耗时。
排队耗时与生成耗时
任务对象里带两个耗时字段,单位都是秒:queue_time_sec 是建单(created_at)到第一次被 worker 领取(进入 processing)之间的时长,也就是排了多久队;generation_time_sec 是从第一次被领取到到达 completed/failed 之间的时长,也就是真正生成花了多久。在对应节点还没发生之前都是 null——比如任务还在 pending 时两个都是 null,进了 processing 之后 generation_time_sec 仍然是 null,直到终态才会有值。
Note: minimax_ia2v 内部其实是两段式流水线(先出草稿 latent,再 refine 成片,中间会经过一个不对外暴露的 streaming 中间态)。generation_time_sec 覆盖的是从第一次被领取到最终完成/失败的全程,包含中间的交接等待,不会因为分两段跑而变成两个数字或漏掉某一段。
重试与超时
领取了任务却停止响应的 worker 会被回收并重试,最多总共 3 次。如果所有尝试都用完,任务会被标记为 failed 并退款——你不需要自己实现超时和退款逻辑。
任务可见性
Warning: GET /aigc/task 不校验归属——任何持有合法 api-key 的人,只要知道 task_id 就能读取它的状态和结果。如果 prompt、音频或结果内容比较敏感,请把 task_id 当作半私密信息,不要把它暴露在公开链接里。
用 webhook 代替轮询
详见上方的「Webhook 通知」一节获取完整配置接口、投递格式与重试策略。
推荐客户端数据库结构
如果你在自己的后端(如 MySQL / PostgreSQL)持久化任务状态,以下是推荐的表结构定义:
任务表(Tasks Table)
CREATE TABLE aigc_tasks (
task_id CHAR(36) NOT NULL PRIMARY KEY,
task_type VARCHAR(32) NOT NULL,
status VARCHAR(20) NOT NULL,
params JSON NOT NULL,
data JSON NULL,
created_at DATETIME(3) NULL,
synced_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
CONSTRAINT chk_aigc_tasks_status CHECK (status IN ('pending', 'processing', 'completed', 'failed'))
) ENGINE=InnoDB;
CREATE INDEX idx_aigc_tasks_status ON aigc_tasks (status);
CREATE INDEX idx_aigc_tasks_task_type ON aigc_tasks (task_type);
Webhook 幂等去重表
搭配 INSERT IGNORE 或 ON DUPLICATE KEY UPDATE 使用,确保同一条 Webhook 投递不会被重复消费:
CREATE TABLE webhook_deliveries (
delivery_id CHAR(36) NOT NULL PRIMARY KEY,
task_id CHAR(36) NULL,
event VARCHAR(64) NOT NULL,
payload JSON NOT NULL,
received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) ENGINE=InnoDB;
CREATE INDEX idx_webhook_deliveries_task_id ON webhook_deliveries (task_id);
同步策略
- 在 POST /aigc/task 返回 task_id 后立即向 aigc_tasks 写入一条记录。
- 当收到 Webhook 推送或轮询拉取到最新状态时,根据 task_id 执行 upsert 更新状态与结果。
- 当 status 变为 completed 时,从 data 数组第一项提取视频 URL 供业务端使用。
计费规则
minimax_ia2v 与 minimax_i2v 的计价方式相同——按分辨率档位和秒数计费,单价见下表,建单时立即扣款。不像 Music Video 流水线那样有单独的预扣/结算两步。如果任务失败或超时,扣的钱会自动全额退回。
计费公式
price = unit_price_by_resolution[resolution] x duration
| resolution | 每秒单价 | 含义 |
|---|---|---|
| 768p | $0.025 | 768p 档位的每秒单价,也是实际的最低消费(duration 最小是 3 秒,即 $0.075) |
| 1080p | $0.05 | 1080p 档位的每秒单价,不随 aspect_ratio 变化 |
算价示例
| resolution | aspect_ratio | 时长 | 计算 | 价格 |
|---|---|---|---|---|
| 768p | 9:16(竖屏,常用) | 5秒 | $0.025 x 5 | $0.125 |
| 768p | 16:9(横屏) | 3秒(最短) | $0.025 x 3 | $0.075 |
| 1080p | 9:16(竖屏) | 15秒(最长) | $0.05 x 15 | $0.75 |
Warning: 计费按 duration 算,不是按实际片段长度。一段 10 秒的音频配 duration: 5,和一段 5 秒的音频配 duration: 5,价格是一样的——较长音频用不完的部分不会退钱,较短音频也不会少收钱。
失败会怎样
- 扣费发生在 worker 开始处理之前,也就是提交的那一刻。
- 如果任务最终状态是 failed——包括因为音频 URL 下载失败——扣的钱都会自动全额退回。
- 无响应的 worker 最多会被重试 3 次;如果所有尝试都用完,任务会被标记为 failed 并按同样方式退款。