HiAPI
博客

教程

如何在 HiAPI 上调用 kling-4.0/image-to-video:curl、Python 与轮询

2026年11月3日
封面图:深松绿底上被平面切割的大型棱柱几何,鼠尾草绿切面,构图克制。

kling-4.0/image-to-video 端点的作用

kling-4.0/image-to-video 可将单张静态图片转换为一段较短的生成视频。在 HiAPI 上,它作为基于任务的端点提供:你提交一张图片,以及一段提示词风格的描述,说明你希望画面如何运动,API 会立即返回一个任务句柄,而不是最终完成的视频。

在请求层面,调用方需要提供:

  • 模型标识符(kling-4.0/image-to-video),
  • 源图片(通常是可公开访问的图片 URL),
  • 一段文本描述,用于指导图片如何运动,或场景中应该发生什么,
  • 该端点为此模型记录的所有额外生成选项。

返回的并不是视频本身。提交响应会携带一个任务标识符和一个初始状态。真正的视频片段会在生成任务完成之后才可用,届时你可以通过引用该标识符来获取。

这种拆分正是该端点的完整心智模型:提交 → 获取任务 id → 轮询状态 → 下载结果。下文每一节都是这个循环的变体。

由于该端点是异步的,你的集成代码有两项职责,而不是一项:它必须发送格式正确的提交请求,并且必须管理后续流程,直到任务进入终止状态。处理好这两点,剩下的只是常规衔接工作。

前置条件与认证

在任何调用之前,你需要两样东西:一个拥有该模型访问权限的 HiAPI 账户,以及一个从控制台签发的 API 密钥。

认证是按请求进行的。每次调用 API 都会在 HTTP 头中包含你的密钥——标准模式是 bearer 风格的授权头:

Authorization: Bearer <YOUR_HIAPI_API_KEY>

不要让密钥进入源代码管理。通常的做法如下:

  • 将它存储在环境变量中(例如 HIAPI_API_KEY),并在运行时读取。
  • 绝不要将它粘贴到客户端代码中,也不要粘贴到你之后会提交到仓库的 curl 命令中。
  • 一旦密钥泄露,请从控制台轮换它。

在 shell 中导出它,以便下面的 curl 和 Python 示例都能读取:

export HIAPI_API_KEY="your-key-here"

你还需要一个可访问的图片 URL。该端点通过引用来使用图片,因此你笔记本电脑上的本地文件路径不可行——请将图片托管在具有稳定 HTTPS URL 的位置,或者如果平台提供资源机制,则上传图片并使用返回的引用。

密钥导出且图片可访问后,你就可以提交任务了。

逐步解析 curl 请求

一个完整的提交请求如下所示:

curl -X POST "https://api.hiapi.ai/v1/tasks" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-4.0/image-to-video",
    "input": {
      "image": "https://example.com/your-image.jpg",
      "prompt": "A slow camera push-in as the subject turns toward the light; soft afternoon shadows"
    }
  }'

逐部分解读:

  • -X POST — 任务创建是 POST,而不是 GET。请求携带描述作业的正文。
  • URL — 统一的 HiAPI 任务端点。对于基于任务的模型,这是同一条路由;模型是在正文中选择的,而不是在路径中。
  • Authorization — 你的密钥,如上一节所述。
  • Content-Type: application/json — 正文是 JSON;省略或拼错这个头,服务器通常会在请求到达模型之前就拒绝它。
  • model — 字面字符串 kling-4.0/image-to-video。请将其视为精确且区分大小写;拼写错误会产生模型未找到错误,而不是有用的提示。
  • input.image — 源静态图片,以 URL 形式提供。这是模型要使其动起来的帧,因此请选择清晰且构图明确的图片。
  • input.prompt — 自然语言指导。描述运动和镜头行为(推近、平移、主体移动)以及整体氛围。模糊的提示词会产生模糊的运动。

即时响应是一个任务对象,而不是视频。它包含作业的标识符和一个状态字段——提交后通常类似于排队或待处理状态。保存该标识符;这是你之后检查作业所需的唯一信息。

此时视频片段尚不存在。这是预期行为,下一节将展示如何处理。

Python 中的相同调用

Python 版本做的事情完全相同——相同的端点、相同的头、相同的正文——因此你选择的工具不会改变协议。

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]

payload = {
    "model": "kling-4.0/image-to-video",
    "input": {
        "image": "https://example.com/your-image.jpg",
        "prompt": "A slow camera push-in as the subject turns toward the light; "
                  "soft afternoon shadows",
    },
}

resp = requests.post(
    "https://api.hiapi.ai/v1/tasks",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=60,
)

resp.raise_for_status()
task = resp.json()
task_id = task["id"]
print("submitted:", task_id, task.get("status"))

实践中需要注意的几点:

  • 使用 json=payload,而不是手工序列化字符串。它会为你设置内容类型,并避免引号错误。
  • 将提交请求和后续操作放在同一个函数或类中,这样任务 id 不会在步骤之间丢失。
  • 设置明确的超时时间。提交调用应快速返回;它只是创建作业,而不是等待视频。
  • 不要调用 raise_for_status() 后还继续假定任务存在——非 2xx 响应意味着没有创建任务,错误正文通常会告诉你哪个字段有误。

如果你在构建服务,请将此调用包装在一个小型客户端中,一个方法用于提交,一个方法用于检查状态。这样可以将重试、日志记录和密钥处理集中在一处,而不是分散在各调用点。

轮询异步任务直至完成

图生视频的生成比聊天补全耗时明显更长——模型必须合成许多帧、对其进行编码并存储结果。如果不在提交响应中保持连接长时间打开,就无法返回视频片段,因此该端点在设计上就是异步的。

如何检查状态

使用 GET 请求按标识符轮询任务:

curl "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"

响应会描述作业:其状态,以及完成后的输出。状态通常从排队状态经过运行状态进入终止状态——例如成功,或因错误消息而失败。

Python 中的简单轮询循环

import time

def wait_for_task(session, base_url, task_id, timeout=900):
    deadline = time.time() + timeout
    delay = 2.0
    while time.time() < deadline:
        r = session.get(f"{base_url}/tasks/{task_id}", timeout=30)
        r.raise_for_status()
        data = r.json()
        status = data.get("status")

        if status in ("succeeded", "failed"):
            return data

        time.sleep(delay)
        delay = min(delay * 1.5, 15.0)  # gentle backoff, capped

    raise TimeoutError(f"task {task_id} did not finish in time")

退避指导

  • 从较短的间隔开始并逐渐增大。生成不会在第一秒完成,因此频繁请求端点只会浪费配额和触发速率限制。
  • 限制间隔,以便及时注意到已完成的作业——稳定状态下几秒钟即可。
  • 始终设置硬性截止时间。除非你设定边界,否则永远无法完成的任务与耗时异常长的任务无法区分。
  • 从后台工作进程或定时作业中轮询,而不是阻塞 Web 请求。如果用户在 UI 中等待,让前端轮询你自己的状态端点。
  • 对状态调用中的瞬时网络错误进行重试,但不要重试已经报告 failed 的任务——此时正确的操作是提交一个新任务。

检索并存储返回的视频片段

当轮询返回终止成功状态时,任务对象包含生成视频的输出引用——一个指向已完成视频的资源 URL 或等效引用。

result = wait_for_task(session, "https://api.hiapi.ai/v1", task_id)
if result["status"] != "succeeded":
    raise RuntimeError(result.get("error") or "generation failed")

video_url = result["output"]["video_url"]

with session.get(video_url, stream=True, timeout=120) as r:
    r.raise_for_status()
    with open(f"{task_id}.mp4", "wb") as f:
        for chunk in r.iter_content(chunk_size=1 << 16):
            f.write(chunk)

这里通常会出现两个设计决策。

及时下载。 输出 URL 通常有时间限制。如果你打算保留视频片段,请将其复制到你自己的存储中,而不是将原始 URL 交给用户并希望它保持有效。

将元数据与文件一起存储。 将任务 id、提示词、源图片引用和创建时间与视频一起持久化保存。当以后有人问为什么视频片段看起来是这样时,该记录就是答案。

对于提供服务,常见模式是:在后端生成,将文件存储在对象存储中,并向客户端返回你自己的稳定 URL。这样你的应用就能控制访问、过期和缓存,而不是依赖生成资源的生命周期。

如果你想用不同的运动重新生成,请提交一个调整了提示词的新任务——每个任务都是独立的,无需修改已完成的任务。

排查失败的请求

出现问题时,从请求结构向外排查。大多数失败都归结为少数几种原因。

提交调用返回错误

  • 模型字符串错误。 kling-4.0/image-to-video 必须完全匹配,包括大小写和斜杠。打印你实际发送的字符串,而不是信任源文件。
  • 认证被拒绝。 确认头是 Authorization: Bearer <key>——不是裸密钥,不是查询参数——并且环境变量在运行请求的同一 shell 或进程中已设置。
  • 图片无法访问。 图片必须能被平台通过 HTTPS 获取。localhost URL、私有存储桶或防盗链的主机都会失败。在无痕浏览器中打开 URL,验证它无需认证即可解析。
  • 字段缺失或命名错误。 正文将模型输入嵌套在 input 下。将 prompt 或 image 放在顶层而不是 input 内是常见失误,验证错误通常会指出字段名。
  • 内容类型。 发送 JSON 正文而不带 Content-Type: application/json 会在涉及模型之前就被拒绝。

任务已创建但从未成功

  • 轮询太少或根本没有轮询。 检查你的循环是否真的在运行,以及它比较的状态值是否与 API 返回的一致。终止状态检查中的拼写错误会导致无限循环。
  • 任务变为 failed。 阅读任务对象中的错误消息;它通常指向输入——例如无法解码的图片。
  • 你触及了截止时间。 如果作业在超时附近仍在运行,请提高上限,而不是反复重新提交,后者只会增加负载和成本。
  • 输出链接已过期。 如果任务成功但下载返回 404,说明完成与检索之间经过了太多时间。成功后立即下载。

一个快速诊断习惯:在最初几次集成时,逐字记录提交响应正文。它会告诉你任务 id、初始状态以及该端点返回的确切字段名,从而消除之后每次失败中的猜测。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档