使用指南
如何在 hiapi API 上使用 kling-3.0/motion-control 制作短视频
如果你曾经尝试让生成视频中的角色做出某个特定动作——不是“跳舞”,而是这个特定片段里的这个特定舞蹈——你就知道通常的选项都很糟糕:手动逐帧转描、重新训练一个运动模型,或者干脆放弃,接受文本提示词给你的任何结果。kling-3.0/motion-control 跳过了所有这些。你给它一张角色图片和一个参考视频,它就把参考中的动作和表情迁移到你的角色上——不需要骨骼绑定、不需要关键帧、不需要动作捕捉服。
本文走一遍真实的短视频工作流:先把一张驾驶员照片制作成一段简短的参考片段,然后用这段片段通过 motion-control 驱动一个完全不同的角色图片。下面的每个请求都是对 hiapi 的 /v1/tasks API 的真实调用,每个素材都是在这篇写作过程中生成的(没有从厂商演示图库借用任何东西),每个价格都是从 hiapi 的定价端点 实时拉取的。
kling-3.0/motion-control 到底做什么
该模型接收两个输入:
image_url—— 单张角色肖像(“目标”)。这决定了最终出现在输出中的是谁。video_url—— 运动参考片段,3–30 秒。这决定了他们做什么。
输出是目标角色执行参考视频的动作和面部表情的视频,渲染分辨率为 720p 或 1080p。它不接受文本提示词、时长或宽高比——输出构图直接跟随参考片段,输出长度也跟随输入片段的长度(我们的 3 秒参考返回了 3.03 秒的输出)。
这种只有两个输入的狭窄契约,正是它对短视频内容有用的原因:你不需要动作捕捉设备就能给品牌吉祥物、产品角色或风格化虚拟形象制作可信的表演——你只需要任何一段人类做你想要动作的视频。
你需要准备什么
- 一个 hiapi API 密钥(
Authorization: Bearer <key>) - 一张可通过 HTTPS 公开访问的角色图片(不是你的目标——是你的驱动角色)
- 第二张角色图片,作为你要动画化的实际目标
- 如果你想在本地提取封面帧或检查片段时长,需要
ffmpeg/ffprobe,与本文做法相同
真实演示:一个动作片段,两个不同角色
motion-control 的关键在于参考视频和最终角色不必匹配。为了证明这一点,本演示使用了三个生成步骤:
1. 一张驾驶员肖像,动画化成一段简短的参考片段:

那张肖像通过 grok-imagine-1.5/image-to-video 变成了 3 秒、480p 的动作片段——这是从静态图片制造参考片段的快速、便宜的方法,而不是去找现成的片段:
2. 一个完全不同的目标角色——同样的动作,完全不同的外观:

3. 把两者都喂给 motion-control。 摊主执行快递员一模一样的转身回头动作:
这就是整个工作流:生成(或获取)任何你喜欢的动作片段,把 motion-control 指向一个完全无关的角色图片,然后得到那个角色执行该动作。对于短视频流水线来说,这意味着一个参考动作库可以驱动无限数量的角色,而无需每次重新拍摄或重新制作参考动画。
最小可用请求(curl)
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3.0/motion-control",
"input": {
"image_url": "https://static.hiapi.ai/blog/kling-3-0-motion-control-short-form-video/target-character.png",
"video_url": "https://static.hiapi.ai/blog/kling-3-0-motion-control-short-form-video/motion-reference.mp4",
"resolution": "720p"
}
}'
响应(任务已创建,仍在处理中):
{
"code": 0,
"data": {
"taskId": "tk-hiapi-01M4CWNSYA7RB637YJ2QZMHMMS",
"status": "pending"
},
"success": true
}
轮询直到完成:
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01M4CWNSYA7RB637YJ2QZMHMMS \
-H "Authorization: Bearer $HIAPI_API_KEY"
在我们的运行中,一个 3 秒 720p 片段从头到尾大约花了 2.3 分钟(状态在切换到 success 之前大约循环了十几次 handling)——设计轮询循环时,请预留几分钟,而不是几秒。最终响应:
{
"code": 0,
"data": {
"taskId": "tk-hiapi-01M4CWNSYA7RB637YJ2QZMHMMS",
"status": "success",
"output": [
{
"type": "video",
"url": "https://temp.hiapi.ai/7c6ttvrbpt/01M4CWNSYA7RB637YJ2QZMHMMS-0.mp4",
"storage": "temp",
"expireAt": 1792039027
}
]
},
"success": true
}
那个 output[0].url 是一个临时链接——expireAt 是 Unix 时间戳,在我们的测试中有效期大约 24 小时。请立即下载并重新托管;不要从你发布的任何内容中直接链接到它。
Python 中的相同流程
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
def create_motion_control_task(image_url: str, video_url: str, resolution: str = "720p") -> str:
resp = requests.post(
API_BASE,
headers=HEADERS,
json={
"model": "kling-3.0/motion-control",
"input": {
"image_url": image_url,
"video_url": video_url,
"resolution": resolution,
},
},
timeout=60,
)
resp.raise_for_status()
return resp.json()["data"]["taskId"]
def wait_for_result(task_id: str, timeout_s: int = 600, poll_every: int = 10) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
resp = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
resp.raise_for_status()
task = resp.json()["data"]
if task["status"] == "success":
return task["output"][0]["url"]
if task["status"] == "fail":
raise RuntimeError(task.get("error"))
time.sleep(poll_every)
raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")
if __name__ == "__main__":
task_id = create_motion_control_task(
image_url="https://your-cdn.example.com/target-character.png",
video_url="https://your-cdn.example.com/motion-reference.mp4",
resolution="720p",
)
output_url = wait_for_result(task_id)
video_bytes = requests.get(output_url, timeout=120).content
with open("motion-control-output.mp4", "wb") as f:
f.write(video_bytes)
print(f"saved {len(video_bytes)} bytes")
没有什么复杂的——创建任务,按间隔轮询 GET /v1/tasks/{taskId},在变为 success 的那一刻下载 output[0].url,并在临时链接过期前自己重新托管。
motion-control 实际校验的参数
schema 很严格——这三个字段之外的任何内容都会被拒绝,提前知道这一点很有用,而不是通过反复试验才发现:
| 字段 | 是否必填 | 说明 |
|---|---|---|
image_url |
是 | 公开 HTTPS URL,目标角色 |
video_url |
是 | 公开 HTTPS URL,3–30 秒动作参考 |
resolution |
否(有默认值,但值得设置) | "720p" 或 "1080p"——这也决定了价格档位 |
你可能从其他视频模型那里期待的字段——duration、aspect_ratio、prompt——都会以 schema 错误被拒绝:
{
"code": 1,
"message": "input: Object { input } has unexpected additional properties: duration, aspect_ratio",
"success": false
}
这是设计使然:输出的长度和构图完全继承自参考视频,所以 duration/aspect_ratio 没有什么可控制的。如果你想要更长或构图不同的输出,请在发送前裁剪或重新构图参考片段,而不是修改请求。
定价:按输出秒计费,而不是按请求计费
直接来自 hiapi 的定价端点:
| 分辨率 | 价格 |
|---|---|
| 720p | $0.10 / 输出秒 |
| 1080p | $0.172 / 输出秒 |
计费由实际输出时长(estimated_seconds)驱动,它反映你的参考片段长度——而不是固定的每请求费用。我们的 3 秒参考在 720p 下产生了 3.03 秒的输出,大约花费 $0.30。一个 10 秒的 1080p 参考片段则接近 $1.72。如果你要在内容日历中批量使用,实际可调的杠杆是参考片段长度:更短的参考片段成本更低,并且仍然能为短视频格式(Reels、TikTok、Shorts)承载完整的动作表演,这些格式中 3–8 秒往往就是整个片段。
生产注意事项
- 有意识地选择驱动片段的构图。 输出继承参考视频的宽高比、镜头距离和节奏——特写参考会保持特写输出,无论你的目标角色图片如何裁剪。
- 清晰的表情比微妙的表情迁移得更好。 参考中清晰的转身、挥手或歪头在目标角色上能可靠地呈现;非常细微、自然的微表情更难让模型识别和迁移。
- 在一个参考片段上复用于许多角色。 由于
video_url和image_url完全独立,内容流水线中最高效的模式是:先建立一个小的参考动作库,然后用同一个片段运行许多不同的角色图片。 - 临时输出 URL 有效期很短。
expireAt通常是一天左右——立即下载并重新托管,而不是把下载排到以后。 - 处理不是即时的。 在这个测试中,一个 3 秒 720p 片段从头到尾花了两分多钟;请围绕分钟(而不是文本生图调用通常的秒级)来规划你的轮询循环和任何下游自动化。
相关内容
有一个参考片段和一个想要配对的角色?从定价页面获取密钥,然后把上面的 curl 请求指向你自己的 image_url/video_url——上面的整个循环都可以直接复制粘贴。
常见问题
我可以使用任何视频作为动作参考吗? 任何有清晰人类(或类人)表演者的视频都可以,只要它可通过 HTTPS 公开访问且长度为 3–30 秒。它不需要包含你的目标角色——这正是该模型的意义所在。
输出会保留参考视频的背景吗? 不会——角色的外观,包括目标图片所暗示的环境,会延续下来;参考视频提供的是动作和表情,而不是场景内容。
为什么我的请求被“unexpected additional properties”拒绝了?
schema 只接受 image_url、video_url 和 resolution。像 duration、aspect_ratio 或 prompt 这样的字段不属于该模型的输入,会立即返回 400——请从 payload 中删除它们。
一个 motion-control 任务需要多长时间?
每个片段预留几分钟。我们的 3 秒 720p 示例从任务创建到可下载的 success 输出大约花了 2.3 分钟。
我可以独立于价格控制输出分辨率吗?
不可以——resolution 既是输出质量设置,也是价格档位选择器:"720p" 按 $0.10/输出秒计费,"1080p" 按 $0.172/输出秒计费。