HiAPI
博客

教程

如何使用 hailuo 2.3 Fast 图生视频 API:curl、Python 与可运行的请求

2026年11月3日
如何使用 hailuo 2.3 Fast 图生视频 API:curl、Python 与可运行的请求

你手上有一张静态图片,想把它变成一段短视频。本指南将通过 hiapi 任务 API 接入 hailuo-2.3-fast/image-to-video:精确的输入 schema(已对照线上校验器验证)、可直接复制的 curl 请求、一个能轮询到任务完成的完整 Python 脚本,以及生产环境细节——回调、幂等重试,还有你实际会遇到的错误响应。

你需要准备

  • 一个 hiapi API 密钥——从你的控制台获取。密钥形如 sk-...,放在 Authorization: Bearer 请求头中。
  • 一张托管在公网可访问的 HTTPS URL 上的源图片。API 接收的是 URL,不是上传文件。
  • 任意 HTTP 客户端。下面的示例使用 curl 和 Python 的 requests。

该模型的按秒计费价格列在定价页面上。

输入 schema(已验证)

hailuo-2.3-fast/image-to-video 使用统一的异步任务端点:POST /v1/tasks 创建任务,GET /v1/tasks/<taskId> 轮询任务。输入 schema 很严格——未知字段会被拒绝并返回 400,而不是被静默忽略。

字段 类型 是否必填 说明
prompt string ✅ 描述你想要的运动
image_url string ✅ 单数形式——一个 URL 字符串,不是 image_urls 数组
duration string 可选 "6" 或 "10"——是字符串,不是数字
prompt_optimizer boolean 可选 让后端为运动改写你的提示词

校验器会抓住你的三个坑:

  1. duration 必须是字符串。 发送 "duration": 6 会返回 400,并提示 duration: got number, want string。请发送 "duration": "6"。
  2. 字段是单数形式的 image_url。 平台上许多其他视频模型(Grok Imagine、Kling)接收的是 image_urls 数组。这个模型接收单个字符串。
  3. 没有 resolution、aspect_ratio、seed、watermark 或 end_image_url。 它们都会返回 additional properties ... not allowed。输出画幅跟随你的源图片;运动控制只能通过提示词。

最小可运行请求:curl

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hailuo-2.3-fast/image-to-video",
    "input": {
      "prompt": "镜头缓慢推进,咖啡杯上蒸汽升腾,柔和的晨光",
      "image_url": "https://your-cdn.example.com/coffee.jpg",
      "duration": "6"
    }
  }'

成功响应:

{
  "code": 200,
  "data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
  "message": "success"
}

然后轮询:

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
  -H "Authorization: Bearer sk-YOUR_KEY"

视频渲染期间,data.status 为 "handling":

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
    "model": "hailuo-2.3-fast/image-to-video",
    "status": "handling",
    "storage": "temp",
    "completed": 0,
    "created": 1783648872
  },
  "message": "success"
}

终态为 "success"(视频 URL 在 data.output[0].url)和 "fail"(详情在 data.error)。

完整的 Python 脚本

import os
import time

import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]  # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}


def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
    resp = requests.post(
        API_BASE,
        headers={**HEADERS, "Content-Type": "application/json"},
        json={
            "model": "hailuo-2.3-fast/image-to-video",
            "input": {
                "prompt": prompt,
                "image_url": image_url,
                "duration": duration,  # 字符串:"6" 或 "10"
            },
        },
        timeout=60,
    )
    body = resp.json()
    if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
        raise RuntimeError(f"create failed: {resp.status_code} {body}")
    return body["data"]["taskId"]


def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(poll_s)
    raise TimeoutError(f"task {task_id} still running after {timeout_s}s")


if __name__ == "__main__":
    task_id = create_task(
        prompt="猫眨了眨眼,把头转向窗户,微风拂过它的毛",
        image_url="https://your-cdn.example.com/cat.jpg",
        duration="6",
    )
    print("task:", task_id)

    task = wait_task(task_id)
    video_url = task["output"][0]["url"]
    print("video:", video_url)

    # URL 位于带有效期的临时存储上——立即下载,不要直接外链它。
    mp4 = requests.get(video_url, timeout=120).content
    with open("output.mp4", "wb") as f:
        f.write(mp4)
    print(f"saved output.mp4 ({len(mp4)} bytes)")

这个脚本做对了两件快速拼凑的方案常忽略的事:

  • 它立即下载视频。 storage: "temp" 意味着输出 URL 带有有效期(expireAt)。请把字节持久化到你自己的存储;绝不要把返回的 URL 存入你的数据库。
  • 它把 fail 视为终态。 重新轮询失败的任务不会让它复活——请创建新任务。

生产环境注意事项

用回调代替轮询

对于脚本之外的使用场景,在创建任务时注册 webhook,完全跳过轮询循环:

{
  "model": "hailuo-2.3-fast/image-to-video",
  "input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
  "callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}

使用 "when": "final" 时,当任务到达 success 或 fail,你的端点会被调用一次。经验法则:轮询适合 CLI、批处理任务和任何临时性场景;一旦你有一个已经在监听的服务器,回调更胜一筹——视频任务要运行几分钟,而轮询循环在那几分钟里就是一个被占用的连接槽和一个被浪费的 worker。

幂等性

创建调用本身并不幂等——每次通过校验的 POST /v1/tasks 都会创建一个新的(计费)任务。如果你的任务运行器在超时时重试,请在处理结果之前按你自己的请求 id 为键存储拿到的 taskId。重试时,如果该键已有 taskId,就轮询它,而不是创建重复任务。

你实际会遇到的错误

症状 含义 修复
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} 密钥无效,或该密钥无法使用此模型 在控制台检查密钥;响应中包含供支持使用的 request_id
400 INVALID_REQUEST — duration: got number, want string 用了 JSON 数字而不是字符串 "duration": "6"
400 INVALID_REQUEST — additional properties '...' not allowed 你发送了 schema 之外的字段 去掉它——消息会指明每个违规字段
400 INVALID_REQUEST — missing required field "prompt" / "image_url" 输入为空或字段名错误 两个字段都是必填的
任务创建后到达 fail 运行时失败——常见原因是后端无法抓取的图片 URL 校验器在创建时不会抓取你的图片;请确保 URL 公网可访问

最后一行值得强调:创建时的校验只针对 schema。一个拼错或私有的 image_url 会给你一个看起来正常的 taskId 和一个几分钟后死掉的任务——所以要针对 fail 告警,而不只是 HTTP 错误。

相关阅读

常见问题

我可以设置分辨率或宽高比吗? 不可以。hailuo-2.3-fast/image-to-video 的 schema 会把 resolution 和 aspect_ratio 当作未知字段拒绝。画幅跟随你的源图片;如果你需要特定宽高比,请先裁剪输入图片。

支持哪些时长? 恰好两种:"6" 和 "10" 秒,以字符串传入。其他任何值都会返回 400,并提示 value must be one of '6', '10'。

我可以传多张参考图片吗? 不可以——该字段是单个 image_url 字符串。接受图片数组的模型(例如 Grok Imagine 的 image_urls)使用不同的 schema;不检查就不要在模型之间复制请求体。

如何控制运动? 只能通过 prompt——没有运动强度或镜头参数。请明确描述运动(“镜头缓慢推进”、“头发在风中摇摆”)。可选地设置 "prompt_optimizer": true 让后端扩展你的提示词。

有更慢、更高质量的变体吗? 有——hailuo-2.3/image-to-video(不带 -fast)也已上线平台,hailuo-2.3/text-to-video 覆盖无源图片的场景。切换前请检查每个变体的 schema;输入字段不保证一致。

费用是多少? 计费按生成视频的秒数计算,并因模型而异;请查看定价页面上的当前费率。

试用需要 API 密钥吗? 需要——所有任务 API 调用都需要 Bearer sk-... 密钥。你可以在控制台创建一个,并先在模型页面演练场中测试。

立即开始构建持久 AI 产物

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

阅读 API 文档