HiAPI
博客

教程

如何使用 Ray 3.2 文生视频 API:curl、Python 与一个可直接运行的请求

2026年11月3日
如何使用 Ray 3.2 文生视频 API:curl、Python 与一个可直接运行的请求

Ray 3.2 是 hiapi 模型目录中的一款文生视频模型,它和其他所有视频模型一样,通过统一的异步任务 API 调用——模型 id 为 ray-3.2/text-to-video,提交到 POST /v1/tasks。有些视频模型唯一的调节项只有提示词,Ray 3.2 不同,它提供三个真正可用的输出控制项——duration、resolution 和 aspect_ratio——每一个都在服务端严格校验。

本指南让你一次就发出能成功的请求:精确的输入 schema(已于 2026-10-19 对照线上 API 验证)、可直接复制粘贴的 curl 调用、完整的 Python 提交/轮询/下载脚本,以及生产环境细节——回调、幂等重试,以及你实际会看到的错误响应。

你将构建什么,以及需要准备什么

目标:提交一段文本提示词,轮询任务,并下载一段无声的 .mp4 片段(5 秒或 10 秒)。

前置条件:

  • 一个 hiapi API 密钥——从你的控制台获取。密钥形如 sk-...,放在 Authorization: Bearer 请求头中。刚接触任务 API?请先从快速开始入手。
  • 任意 HTTP 客户端。我们会展示 curl 和 Python(requests)。

Ray 3.2 的输出按片段计费,而且价格会随你的选择大幅上升——当前费率见定价页。在迭代提示词时,从 540p / 5 秒起步;一段 1080p 10 秒的片段可能比一次预算规模的图像渲染贵很多倍,所以别让你的开发循环一直跑在最高设置上。

精确的输入 schema(一个必填字段,三个严格枚举)

所有内容都放在一个 input 对象里。已对照线上 API 逐字段验证:

字段 类型 必填 允许值 默认值
prompt string 是 场景描述,最多 6000 个字符 —
duration integer 否 5 或 10 5
resolution string 否 540p、720p、1080p 540p
aspect_ratio string 否 16:9、9:16、1:1、4:3、3:4、21:9 16:9

写代码之前,有三件事值得牢记:

  1. duration 是整数,不是字符串。发送裸数字——"duration": 5。这与其他一些任务 API 视频模型相反(例如 hailuo-2.3 要求 "duration": "6" 作为字符串)。如果你要把请求体从一个模型移植到另一个模型,请重新检查这个字段;这是最常见的跨模型错误。
  2. 枚举值是被校验的,不是被截断的。超出范围的值会以 400 被拒绝,而不是被静默取整。没有 2k,没有 480p,没有 2:1。
  3. 没有 prompt_optimizer、seed 或 negative_prompt。构图完全通过 aspect_ratio 加提示词来控制。如果你发送 schema 不认识的字段,预期会收到 400——/v1/tasks 的输入 schema 因模型而异,所以不要假设在别处有效的键能沿用过来。

校验实际返回什么

以下是线上端点的真实响应(故意提交无效值,不创建任务,不计费):

// POST with "resolution": "2k"
{"code":400,"data":null,"error_code":"INVALID_REQUEST",
 "message":"invalid input: resolution: value must be one of '540p', '720p', '1080p'"}

// POST with "duration": 7
{"code":400,"data":null,"error_code":"INVALID_REQUEST",
 "message":"invalid input: duration: value must be one of 5, 10"}

// POST with "aspect_ratio": "2:1"
{"code":400,"data":null,"error_code":"INVALID_REQUEST",
 "message":"invalid input: aspect_ratio: value must be one of '16:9', '9:16', '1:1', '4:3', '3:4', '21:9'"}

message 会指出确切的字段和确切允许的集合——所以如果你忘了某个枚举值,API 会告诉你。注意 duration 的 5, 10 没有引号(数字),而 resolution 的 '540p' 是带引号的字符串:这个引号差异就是提醒你哪个字段是整数。

最小可运行示例:curl

创建任务:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ray-3.2/text-to-video",
    "input": {
      "prompt": "雨夜中,一名街头舞者在霓虹灯下旋转,水洼倒映着粉色和蓝色灯光,她的夹克随着旋转翻飞,镜头低角度环绕她,电影感",
      "duration": 5,
      "resolution": "540p",
      "aspect_ratio": "9:16"
    }
  }'

创建响应会带一个任务 id(已截断):

{ "data": { "taskId": "task_01k..." } }

轮询它,直到进入终态:

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

任务运行期间,data.status 会报告一个进行中的状态。两个终态是 success 和 fail。成功时(已截断):

{
  "data": {
    "taskId": "task_01k...",
    "status": "success",
    "output": [ { "url": "https://.../clip.mp4" } ]
  }
}

立即下载 data.output[0].url。输出 URL 是签名的,会过期——把字节保存到你自己的存储中,而不是直接热链任务 URL。Ray 3.2 返回的是无声 MP4(没有音轨),所以不要等待一个永远不会来的音频流。

完整的 Python 脚本(提交 → 轮询 → 下载)

import time
import requests

API_BASE = "https://api.hiapi.ai/v1"
API_KEY = "sk-YOUR_KEY"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}


def create_task(prompt: str, duration: int = 5,
                resolution: str = "540p", aspect_ratio: str = "9:16") -> str:
    resp = requests.post(
        f"{API_BASE}/tasks",
        headers=HEADERS,
        json={
            "model": "ray-3.2/text-to-video",
            "input": {
                "prompt": prompt,
                "duration": duration,          # 5 or 10 — an INTEGER, not a string
                "resolution": resolution,      # "540p" | "720p" | "1080p"
                "aspect_ratio": aspect_ratio,  # "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9"
            },
        },
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]


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


task_id = create_task(
    "一只纸船顺着积满雨水的排水沟漂流,水滴在水面荡起涟漪,"
    "秋叶打着旋漂过,低机位贴近水面拍摄,柔和的阴天光线"
)
print("task created:", task_id)

task = wait_task(task_id)
video_url = task["output"][0]["url"]

# Output URLs expire — download right away and store the bytes yourself.
video = requests.get(video_url, timeout=120).content
with open("ray32-clip.mp4", "wb") as f:
    f.write(video)
print(f"saved ray32-clip.mp4 ({len(video) / 1e6:.1f} MB)")

用 pip install requests 安装依赖,换上你的密钥,任务完成时磁盘上就会有一个 .mp4。视频任务需要几分钟,而不是几秒——给你的轮询循环一个宽松的截止时间(上面是 15 分钟),而不是假设它会快速返回。

生产环境注意事项:回调、幂等性、错误

优先使用回调而不是轮询

对于脚本以外的任何用途,在创建任务时注册 webhook,而不是轮询:

{
  "model": "ray-3.2/text-to-video",
  "input": { "prompt": "...", "duration": 10, "resolution": "720p" },
  "callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}

使用 "when": "final" 时,hiapi 会在任务进入终态时调用你的端点一次——没有轮询流量,也不会在两次间隔之间错过完成通知。你的处理器随后执行 GET /v1/tasks/<id>(或读取投递的响应体)来获取 output[0].url。对于无法暴露 HTTPS 端点的 CLI 和 notebook,轮询仍然可以。

让重试保持幂等

在创建调用返回的那一刻就持久化 taskId。如果你的进程在生成中途崩溃,通过轮询已存储的 id 来恢复——不要重新创建任务,否则你会为第二次渲染付费。只有当原始创建请求本身在返回任务 id 之前失败时,才重新创建。由于 Ray 3.2 按片段计费,而且高分辨率下的片段并不便宜,重复创建是实实在在的成本错误,而不只是浪费时间。

你实际会看到的错误

下面每一行都是经过验证的线上响应形状:

症状 响应 修复方法
密钥缺失/无效 401,嵌套 {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}} 检查 Authorization: Bearer sk-... 请求头以及密钥是否有访问权限。联系支持时请提供 request_id。
枚举值错误 400 INVALID_REQUEST,扁平 {"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: <field>: value must be one of ..."} 阅读 message 中指定的字段;它会列出确切的允许集合。
duration 以字符串发送 400 INVALID_REQUEST 发送裸整数 5 或 10,而不是 "5"。
未知模型 id 400,error_code: "MODEL_UNAVAILABLE","model not available via /v1/tasks" 严格使用 ray-3.2/text-to-video——到模型页面查看规范 id。
轮询时任务 id 错误 404,扁平 {"code":404,"data":null,"message":"task not found"}(注意:404 上没有 error_code) id 错误,或者你用了另一个账户的密钥来查询。
轮询时 status: "fail" 任务终态,详情在 data.error 阅读 data.error.code / data.error.message。失败任务会退款;内容策略标记和上游容量问题会在这里暴露——对于内容标记,用改写后的提示词重试。

相关资源

常见问题

模型 id 是什么,我该调用哪个端点? ray-3.2/text-to-video,作为顶层 model 提交到 POST https://api.hiapi.ai/v1/tasks,参数放在 input 下。它是异步的——你会拿回一个 taskId,然后轮询 GET /v1/tasks/<id>(或注册回调)。

duration 以秒为单位吗,为什么 "5" 会失败? 片段为 5 秒或 10 秒,该字段是整数:发送 5 或 10。带引号的字符串,或任何其他数字如 7,都会失败并返回 400 INVALID_REQUEST: duration: value must be one of 5, 10。

我可以设置分辨率和宽高比吗? 可以——这正是 Ray 3.2 与仅支持提示词的视频模型的不同之处。resolution 为 540p、720p 或 1080p;aspect_ratio 为 16:9、9:16、1:1、4:3、3:4、21:9 之一。两者都是可选的(默认 540p 和 16:9),且都会以 400 拒绝超出范围的值。

一段片段多少钱? Ray 3.2 按片段计费,分辨率是最大的杠杆——同样长度下,1080p 片段的成本是 540p 的几倍,而 10 秒片段的成本大约是 5 秒片段的三倍。费率会变化,所以请查看定价页,而不是硬编码一个数字,并在 540p/5 秒下做原型。

片段有音频吗? 没有——Ray 3.2 文生视频返回的是无声 MP4。如果你需要声音,请在后期添加,或使用单独的音频模型。

Ray 3.2 支持图生视频吗? 支持,作为同一任务 API 上的单独模型 id:ray-3.2/image-to-video。它的输入 schema 不同(它接收一张参考图),所以复用本请求体之前先探测一下——见图生视频模型页面。

我的生成很慢或看起来卡住了。什么情况算正常? 视频任务会运行几分钟。在你的轮询循环中保留非终态的 data.status 并等待——预留 10–15 分钟的截止时间,或者使用带 "when": "final" 的 callback,让 hiapi 在终态时通知你,而不是你自己猜一个间隔。

立即开始构建持久 AI 产物

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

阅读 API 文档