教程
如何通过 HiAPI API 调用 flux-3-max/keyframes-to-video:curl 与 Python 指南
面向开发者的认证、关键帧提交、任务轮询与结果获取
这个集成实际做什么
flux-3-max/keyframes-to-video 是一个异步任务 API,用于根据关键帧图像生成视频。与在同一个 HTTP 响应中返回结果的同步端点不同,此模型接收你的关键帧,创建后台任务,并返回一个可用于检查进度的任务标识符。
端到端生命周期分为四个阶段:
- 认证 — 每个请求都携带你的 HiAPI API 密钥。
- 提交 — 发送关键帧和参数以启动视频任务。
- 轮询 — 反复查询任务状态,直到达到终态。
- 获取 — 从任务成功时返回的 URL 下载生成的视频。
牢记这一生命周期会决定你如何编写客户端:提交和结果获取是分开的调用,你的应用必须能够容忍一个需要数十秒到数分钟的任务。下面的 curl 和 Python 示例遵循同样的四个阶段,因此你可以将此流程移植到任何语言或作业运行器中。
获取 API 密钥并认证
你的 API 密钥从 HiAPI 仪表板签发。请像对待密码一样对待它:它标识你的账户并授权计费调用,因此绝不应出现在源代码、提交历史或日志输出中。
认证以 HTTP 头的形式在每个请求中传递:
Authorization: Bearer $HIAPI_API_KEY
在实践中,将密钥存储在环境变量中并在运行时读取。对于 shell 示例,每个会话导出一次:
export HIAPI_API_KEY="your-key-here"
对于 Python,使用 os.environ["HIAPI_API_KEY"] 读取它,而不是硬编码字符串。将 .env 文件添加到 .gitignore,并且如果为了调试而记录请求,请在其到达日志聚合器之前对 Authorization 头进行脱敏。如果密钥曾被暴露,请立即从仪表板轮换它。
用 curl 构建请求
提交视频任务意味着发送一个 JSON 主体,其中指定模型并携带你的关键帧。关键帧输入和生成参数的确切字段名记录在模型页面上,因此请将其作为权威来源;下面的结构展示了请求的形态。
curl -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-3-max/keyframes-to-video",
"input": {
"keyframes": [
"https://example.com/frame-01.png",
"https://example.com/frame-02.png"
]
}
}'
每个部分的作用:
model— 选择flux-3-max/keyframes-to-video,这样同一个端点以后可以路由到其他模型,而无需更改你的传输代码。input.keyframes— 有序的图像 URL 列表。顺序很重要:第一帧锚定片段的开始,后续帧引导后续时刻。Authorization— 上述的 bearer 头。Content-Type— JSON 主体所必需的。
响应是一个包含标识符的任务对象。保存该 ID;它是后续每次轮询的句柄。
Python 中的相同请求
Python 版本镜像了 curl 调用。使用 requests 可以保持简短,但如果你希望零依赖,标准库也同样可行。
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"
def submit_video_task(keyframe_urls: list[str]) -> str:
response = requests.post(
f"{BASE_URL}/tasks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"model": "flux-3-max/keyframes-to-video",
"input": {"keyframes": keyframe_urls},
},
timeout=30,
)
response.raise_for_status()
return response.json()["id"]
task_id = submit_video_task([
"https://example.com/frame-01.png",
"https://example.com/frame-02.png",
])
print(task_id)
有两个值得保留的细节:显式的 timeout,这样挂起的连接不会永远阻塞你的工作进程;以及 raise_for_status(),这样 4xx 或 5xx 会作为异常浮现,而不是静默的错误载荷。保持函数小而纯粹——它应该提交并返回 ID,仅此而已。轮询是另一回事。
轮询任务状态并获取结果
视频生成需要真实的计算时间,因此 API 不会阻塞直到文件出现。相反,你查询任务直到它完成。状态为 succeeded 时携带输出 URL;failed 携带错误;其他任何值意味着继续等待。
import time
import requests
def wait_for_video(task_id: str, poll_interval: int = 5, max_wait: int = 600) -> str:
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
response = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
response.raise_for_status()
task = response.json()
if task["status"] == "succeeded":
return task["output"]["video_url"]
if task["status"] == "failed":
raise RuntimeError(task.get("error", "task failed"))
time.sleep(poll_interval)
raise TimeoutError(f"task {task_id} did not finish in time")
生产环境的设计说明:
- 轮询间隔 — 几秒钟就足够了。猛击端点会增加负载,却不会让任务更快完成。
- 截止时间 — 始终限制总等待时间,并在失败时大声报错,而不是永远循环。
- 下载 — 返回的 URL 是临时的;在任务成功后立即获取文件并将其移动到自己的存储中。
- 解耦 — 在 Web 应用中,在后台工作进程中运行此循环,并通过 webhook 或队列通知客户端,而不是保持 HTTP 请求打开。
处理错误和边缘情况
大多数集成失败分为四类。
认证错误 (401/403)。 密钥缺失、格式错误或不再有效。检查环境变量是否确实在发起调用的进程中已导出——一个常见的陷阱是本地 shell 正常工作,但容器或 cron 作业中缺少该变量。
输入错误 (4xx)。 无法访问的关键帧 URL、不支持的图像格式或超出允许范围的参数将拒绝提交。在提交前验证每个关键帧 URL 都可公开获取;缓慢或受限的主机是原本正确的请求失败的最常见原因。
任务失败。 任务可能被接受,然后在生成过程中失败。始终检查错误字段,而不是将完成的轮询视为成功。将任务 ID 与错误一起记录,以便你可以将其与支持请求相关联。
超时和重试。 提交时的网络错误通常可以安全地通过退避重试。成功提交后重试则不行——你可能会创建重复任务并产生重复费用。在重试前读取响应,并在轮询循环中也使用带抖动的指数退避。
最后一点卫生提示:绝不记录 Authorization 头,如果关键帧 URL 包含签名查询字符串,请对其进行清理。当对该模型的字段名或限制有疑问时,请查看 flux-3-max/keyframes-to-video 文档,并在你的客户端中完全照搬这些值。