教程
如何通过 hiapi API 使用 omnihuman-1.5:curl、Python 与可直接运行的请求
omnihuman-1.5 可将一张人像照片加上一段音频,生成口型同步的说话视频。在 hiapi 上,它与其他所有媒体模型一样,运行在同一套异步任务协议上:先调用一次 POST /v1/tasks 创建任务,然后轮询(或接收 webhook)直到视频 URL 就绪。本指南使用真实的请求 schema——已与线上 API 逐字段核对——因此下面的 curl 和 Python 代码可以直接复制运行,而不只是示例。
你将构建什么
一个脚本,将人脸图像和语音轨道发送给 omnihuman-1.5,返回一个该人脸按照音频说话、口型同步的 MP4 文件。视频片段长度跟随你的音频——没有 duration 字段可设置。
前提条件
- 一个 hiapi API key。 在 dashboard 中创建一个;每次请求都会作为 Bearer token 发送。请求头格式请参阅 认证文档。
- 一个可公开访问的图像 URL 和音频 URL。 omnihuman-1.5 会在服务端下载两者,因此你的机器能匿名打开的
http(s)URL 即可;localhost路径和任务中途过期的签名 URL 则不行。
就这些——不需要 SDK,除 key 之外不需要账户。
输入 schema
omnihuman-1.5 接受严格的 input 对象。未知字段会被拒绝,因此这就是全部可用字段:
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
image_url |
string | 是 | 一张人像 URL。清晰、正面的单张人脸效果最好。 |
audio_url |
string | 是 | 用于口型同步的语音轨道。决定输出长度。 |
prompt |
string | 否 | 可选的动效/表情引导。 |
resolution |
string | 否 | "720p" 或 "1080p"。 |
没有纯文本模式:audio_url 是必填的。如果你只有脚本,请先生成语音(使用 TTS 模型,或像 heygen-avatar-v 这样的文本驱动数字人),然后将生成的音频 URL 传到这里。
最小可运行示例(curl)
创建任务:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "720p"
}
}'
响应中带有任务 id:
{ "code": 200, "data": { "taskId": "b3f1c2e8-...", "status": "pending" } }
轮询任务,直到它达到终止状态:
curl -s https://api.hiapi.ai/v1/tasks/b3f1c2e8-... \
-H "Authorization: Bearer sk-YOUR_KEY"
完成后,data.status 为 "success",视频位于 data.output[0].url:
{
"code": 200,
"data": {
"taskId": "b3f1c2e8-...",
"status": "success",
"output": [
{ "url": "https://temp.hiapi.ai/.../omnihuman.mp4", "expireAt": 1760000000 }
]
}
}
该 output URL 是临时的(带有 expireAt)。任务成功后应立即下载 MP4——不要在生产环境中直接热链该地址。
Python 中的同样调用
import time
import requests # pip install requests
API = "https://api.hiapi.ai/v1/tasks"
KEY = "sk-YOUR_KEY"
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
def create_task() -> str:
payload = {
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "720p",
},
}
r = requests.post(API, headers=HEADERS, json=payload, timeout=60)
r.raise_for_status()
return r.json()["data"]["taskId"]
def wait_for_video(task_id: str, timeout: int = 600, interval: int = 5) -> str:
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30)
data = r.json()["data"]
status = data["status"]
if status == "success":
return data["output"][0]["url"]
if status == "fail":
raise RuntimeError(f"omnihuman-1.5 task failed: {data.get('error')}")
time.sleep(interval)
raise TimeoutError(f"task {task_id} did not finish in {timeout}s")
if __name__ == "__main__":
tid = create_task()
print("task:", tid)
video_url = wait_for_video(tid)
# URLs expire — persist the bytes immediately.
mp4 = requests.get(video_url, timeout=120).content
with open("talking_head.mp4", "wb") as f:
f.write(mp4)
print("saved talking_head.mp4")
投入生产
优先使用回调而不是密集轮询。 添加一个顶层 callback 对象,hiapi 就会将完成的任务 POST 到你的端点,而不是让你轮询:
{
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "1080p"
},
"callback": { "url": "https://your.app/webhooks/hiapi", "when": "final" }
}
when 只接受 "final",并且会在成功和失败时都触发——因此你的 webhook 必须根据 data.status 分支处理。投递的 body 与通过 GET /v1/tasks/{id} 得到的是同一个对象。投递是至少一次语义,因此请按 taskId 去重。
绝不要在临时错误上重新提交。 如果轮询请求超时或连接中断,请重新轮询同一个 taskId——不要再次调用 POST /v1/tasks。重新提交会启动第二个计费任务。拿到 taskId 后立即保存。
分别处理三种失败形态:
- 认证失败 → HTTP
401,body{"error": {"code": "permission_denied", "type": "hiapi_error", ...}}。修复 key;不要重试。 - 错误请求(缺少/无效字段)→ HTTP
400,body{"code": 400, "error_code": "INVALID_REQUEST", "message": "..."}。message 会指出有问题的字段——修复后重新发送。 - 已启动但失败的任务 → HTTP
200,且data.status == "fail",并带有data.error。最常见的原因是服务端无法下载image_url/audio_url。请检查两者均可公开访问且仍然有效。始终根据data.status分支处理,而不仅仅是 HTTP 状态码。
价格按输出秒数计费,列在 pricing 页面;由于片段长度跟随你的音频,成本随音频时长变化。
相关指南
- 统一异步 API 介绍 —— 所有模型共享的
/v1/tasks创建与轮询契约。 - 快速开始 —— 从端到端完成你的第一个 hiapi 请求。
- HeyGen Avatar IV API 教程 —— 另一个照片转说话视频的模型,可用于比较口型同步方案。
- HeyGen Avatar V —— 当你没有音频文件时,可使用脚本驱动(文本转视频)的数字人。
常见问题
我可以用文本而不是音频文件来驱动 omnihuman-1.5 吗?
不可以。audio_url 是必填的,模型会对该音频进行口型同步。若需要从脚本到视频的流程,请先合成语音(任意 TTS),或使用像 heygen-avatar-v 这样的文本驱动数字人,然后将音频 URL 传到这里。
输出视频有多长?
跟随你的音频片段——没有 duration 参数。12 秒的语音轨道大约会生成 12 秒的视频。
什么样的图像效果最好? 一张光线清晰、正面的单人人像,位于公开 URL。合影或人脸严重遮挡会导致口型同步效果较差。
720p 还是 1080p?
两者都可用于 resolution。迭代时从 720p 开始;最终渲染时切换到 1080p。更高分辨率每秒成本更高——请参阅 pricing。
我的任务立即返回 status: "fail"。为什么?
几乎总是服务端无法获取某个输入 URL。请确认 image_url 和 audio_url 可公开访问(在无痕窗口中打开它们)且未过期。data.error 信息可帮助缩小范围。
我需要轮询,还是可以用 webhook?
两者皆可。简单脚本可使用 GET /v1/tasks/{id} 轮询;生产环境可注册 callback.url 并将 when 设为 "final",这样就不必保持轮询循环。