教程
如何调用 Kling 2.5 Turbo 文生视频 API:curl 与 Python 指南
kling-2.5-turbo/text-to-video 端点能为你提供什么
kling-2.5-turbo/text-to-video 是 HiAPI 上对外提供的文生视频模型。你给它一段文本提示词,它返回一段生成的视频。名称里的“turbo”说明了它优化的方向:比标准质量档位更快的周转速度,代价是丢失一些细节。对于草稿渲染、故事板预览、社交媒体剪辑和创意迭代来说,这个取舍通常是正确的。
在写第一行代码之前,最需要内化的一点是:这是一个异步端点。视频生成需要数秒到数分钟,远超任何合理的 HTTP 超时。因此 API 被拆分为两个操作:
- 提交 —— 你 POST 提示词和参数,立即拿回一个任务标识符。
- 轮询 —— 你反复用该标识符 GET 任务,直到它进入终态,然后从完成的响应载荷中读取视频结果。
如果你试图把它建模为一次阻塞调用,就会遇到超时、重试时重复生成,以及高负载下的连接重置。先提交再轮询的模式不是需要绕开的麻烦;它是正确的心智模型。下面的每个代码示例都围绕它构建,一旦你内化了这一点,集成的其余部分就很直接了。
还需要设定一个预期:端点是有状态的,但状态在服务端,不在你这边。任务独立于你的 HTTP 连接而存在。你的脚本可以在轮询中途崩溃、重启,然后用 ID 重新接上同一个任务——只要你把那个 ID 持久化到了某个地方。从一开始就按这个思路设计。
请求结构:提示词、快速预设和灵活时长
你只能控制少数几个字段,但每个字段都会对任务产生实质影响。以下才是真正重要的部分。
提示词
提示词是主要的创意输入。把它当作镜头描述,而不是搜索查询。这个模型的好提示词通常包括:
- 主体 —— 屏幕上是谁或什么。
- 动作 —— 主体在片段中做什么。
- 镜头 —— 构图和运动,例如
slow dolly in、static wide shot、handheld follow。 - 环境和光线 —— 场景、时间、氛围。
- 风格 —— 如果你想引导观感,可以写
cinematic、anime、product photography等。
保持具体,并把主体放在前面。模糊的提示词会产生模糊的运动,而 turbo 档位会放大这一点,因为它留给解释的空间更少。
fast/turbo 预设
该模型家族支持一个快速预设,用部分精细度换取延迟。启用它时,你是在告诉后端优先考虑速度——运动仍然连贯,但精细纹理、小脸和复杂背景会比质量路径更早劣化。在你测试提示词变体的迭代循环中使用它;当你最终渲染主镜头时,考虑质量路径是否是更好的最后一步。该预设是一个请求字段,因此是每个任务的决策,而不是账户级的全局设置。
灵活时长
时长在模型支持的范围内是灵活的,而不是固定为单一长度。更长的时长意味着要生成更多帧,因此完成时间更长、成本更高——计费按输出秒数计算。选择能满足镜头的最短时长。社交媒体帖子的五秒循环不需要和叙事节拍同样的长度。
字段纪律
只设置你需要的字段。未知或拼错的键是静默配置错误的常见来源,所以让 JSON 请求体保持小、明确,并和管道配置的其余部分一起纳入版本控制。
用 curl 发起请求
每次 HiAPI 调用都使用相同的认证模式:在 Authorization 头中携带 bearer token。把密钥放在环境变量里,这样它就不会出现在 shell 历史或已提交的脚本中。
export HIAPI_API_KEY="your_api_key_here"
然后提交任务。确切的字段名和端点路径应取自模型参考;下面的形式是规范形式:
curl -X POST "https://api.hiapi.ai/v1/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-2.5-turbo/text-to-video",
"prompt": "A slow dolly-in on a ceramic coffee cup on a wooden table, morning light raking across the surface, steam rising, shallow depth of field, cinematic",
"duration": 5,
"fast": true
}'
你应预期拿回的不是视频。而是一个确认,包含任务标识符及其初始状态——通常是 queued 或 processing 状态,外加一个 id 字段。保存那个 ID;它是后续所有操作的句柄。
最小响应大致如下:
{
"id": "job_abc123",
"status": "queued",
"model": "kling-2.5-turbo/text-to-video"
}
提交调用应很快返回——正常条件下远低于一秒。如果它挂起,问题在连接性或认证,不在模型。如果返回 401,检查头格式(Bearer 前缀很重要)。如果返回 422,你的 JSON 请求体格式有误或缺少必填字段。
不要给这个调用添加 -L、重试或长超时。提交步骤要么快速成功,要么快速失败。所有等待都发生在轮询循环中,也就是接下来要讲的内容。
Python 中的同一请求
Python 版本是同一 HTTP 契约的薄封装。使用 requests 配合共享的 Session,让连接池在提交和每次轮询之间生效。把它包在函数里,这样你的其余代码永远不直接接触原始 HTTP。
import os
import time
import requests
BASE = "https://api.hiapi.ai/v1"
HEADERS = {
"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
"Content-Type": "application/json",
}
session = requests.Session()
def submit_video(prompt: str, duration: int = 5, fast: bool = True) -> str:
body = {
"model": "kling-2.5-turbo/text-to-video",
"prompt": prompt,
"duration": duration,
"fast": fast,
}
resp = session.post(f"{BASE}/video/generations", json=body, headers=HEADERS, timeout=15)
resp.raise_for_status()
return resp.json()["id"]
def poll_video(job_id: str, timeout_s: int = 600, interval_s: float = 3.0) -> dict:
deadline = time.monotonic() + timeout_s
delay = interval_s
while time.monotonic() < deadline:
resp = session.get(f"{BASE}/video/generations/{job_id}", headers=HEADERS, timeout=15)
resp.raise_for_status()
data = resp.json()
status = data.get("status")
if status in ("succeeded", "failed", "cancelled"):
return data
time.sleep(delay)
delay = min(delay * 1.5, 15.0)
raise TimeoutError(f"job {job_id} did not finish in {timeout_s}s")
if __name__ == "__main__":
job = submit_video("A slow dolly-in on a ceramic coffee cup, morning light, steam rising, cinematic")
result = poll_video(job)
print(result)
有几个细节值得保留而不是精简掉:每个请求上的 timeout,这样卡住的套接字不会挂起你的 worker;指数退避并设一个合理的上限;以及单独的 TimeoutError,让调用方能够区分“仍在运行”和“已坏掉”。
如果你更喜欢 httpx,转换很直接——相同的方法、URL 和 JSON 请求体。传输层不是有趣的部分;契约才是。在开始轮询之前,把 job_id 存到持久的地方,这样重启不会让进行中的生成成为孤儿。
轮询任务并读取响应
轮询循环是大多数集成 bug 的所在地。三条规则能让它保持可靠。
规则 1:只有终态才结束循环
你会看到瞬态——queued、processing——以及终态,如 succeeded、failed 和 cancelled。只有终态才退出循环。不要把未知状态字符串当作成功,也不要在 processing 上中断。每次迭代都记录状态;当凌晨两点出问题时,那条日志是你唯一的证据。
规则 2:退避,不要空转
对于需要一分钟的任务,固定一秒轮询是浪费;而在运行批量任务时,激进轮询可能触及速率限制。从大约两到三秒开始,每轮乘以约 1.5 倍,上限为十到十五秒。一个一分钟任务的总请求数从六十降到十五以下,而最坏情况下的检测延迟仍然只是上限值。
规则 3:把资产和元数据分开
完成的响应载荷同时包含两者。视频本身以 URL 形式交付(而且通常带过期时间),而其他一切——任务 ID、模型、时长、状态、耗时——都是关于你如何得到它的元数据。读取 URL,及时下载,并自己存储。生成的资产 URL 不是永久 CDN;把它们当作交接,而不是家。把任务 ID 和你自己的副本一起持久化,这样你能把任何片段追溯回产生它的确切请求。
关于 failed 的说明
failed 状态是任务级结果,不是传输错误。HTTP 调用成功了;生成没有成功。阅读错误载荷——它可能表明内容策略拒绝、不支持的参数组合或内部故障。对策略拒绝原样重试只会再次失败,所以在考虑重试之前先按原因分支。
处理错误、超时和重试
区分两个错误世界,并分别处理。
传输级错误是 HTTP 失败:连接重置、5xx 响应、速率限制 429 和客户端超时。这些不能说明任务是否运行过。用指数退避和抖动重试,并限制尝试次数。
任务级错误是成功 HTTP 响应中的终态。任务运行了并产生了明确结果。重试轮询没有帮助;如果你要重试,那是一次新的提交,而且只在失败原因是暂时性的时候才做。
重试正确的东西
这是微妙的部分。如果你的提交调用超时,你不知道服务器是否接受了任务。盲目重新提交可能产生两次生成和两次扣费。更安全的模式是用客户端生成的请求键让提交幂等,你把它作为头或请求体字段发送,这样重复提交会返回原任务而不是启动新任务。如果你使用的 API 面不提供这个,那么在提交超时时,记录提示词哈希和时长,并在重新提交前检查你最近的任务。
每一层都要有超时
设置三个不同的超时,不要混为一谈:
- 每请求超时 —— 短,例如十到十五秒。这限制单次 HTTP 调用,不是任务。
- 整体任务截止时间 —— 整个生成的墙钟预算。如果超过,标记任务为孤儿、告警,然后继续。
- 面向客户端的超时 —— 如果用户在等待,决定你是流式传输进度还是向前端返回任务句柄。
实用的重试策略
用退避重试 429 和 5xx,上限设小。永远不要重试 400、401、403 或 422——那些是你请求中的 bug,重复它们只会烧配额。记录每次失败的响应体;HiAPI 错误载荷通常会指出有问题的字段。
批量安全
在扇出许多任务时,添加并发限制和带抖动的启动延迟。一百个同时提交是自找的速率限制事故。五到十个 worker 的池,各自独立轮询,要稳定得多,也更容易观察。
上线前的生产检查清单
在这离开笔记本之前,把这些决策定下来。
- 超时和截止时间。 每个调用都有每请求超时,有整体任务截止时间,以及任务成为孤儿时发生什么的明确策略。把它们写成常量,而不是魔法数字。
- ID 持久化。 在轮询开始前存储
job_id和提示词哈希。这是让重启和审计成为可能的关键。 - 资产存储。 成功时把完成的视频下载到你自己的存储桶。永远不要把你不控制的 URL 作为永久引用送进前端或数据库。
- 日志记录。 记录每次状态转换,包含任务 ID、模型、时长、预设和耗时。当成本或质量问题出现时,这是回答它们的数据集。
- 成本意识。 计费按输出秒数,所以时长是你的主要成本杠杆。turbo 预设让延迟(因此 worker 占用)保持低位。跟踪每个功能生成的秒数,让成本讨论基于真实数字而不是猜测。
- 幂等性。 提交时使用客户端请求键,并制定什么构成安全重新提交的规则。
- 失败 UX。 现在就决定用户在任务级失败时看到什么:重试按钮、回退提示词,还是纯文本消息。静默空转是最差的选择。
- 提示词版本控制。 把提示词放在配置里,而不是内联在处理器中,这样你可以在不重新部署的情况下比较不同变体的输出。
端点本身很小——一次提交,一次轮询。几乎所有的工程努力都在它周围的生命周期中,而这正是生产质量的决定之处。从 HiAPI 上 kling-2.5-turbo/text-to-video 的模型参考开始,然后围绕它构建这里描述的脚手架。