搜索

搜索 HiAPI 模型、工具和资源。

返回博客
教程

PixVerse V6 文生视频 API:一个能跑通的 curl 与 Python 示例

hiapipixverse-v6Video API教程Task API

用 pixverse-v6/text-to-video 在 hiapi 生成一段视频,本质上就是一次 POST /v1/tasks 加一轮轮询——和平台上每一个生成类模型用的异步任务模式完全一样。本文给你可直接复制的 curl 和 Python 示例、端点真正会校验的输入字段,以及我实际跑通一次生成时记录下来的任务生命周期和踩的坑。

开始前需要什么

  • 一个 hiapi API key。在控制台里创建,然后用请求头 Authorization: Bearer sk-<你的 key> 带上。请求头格式见鉴权文档。
  • model id 是 pixverse-v6/text-to-video。保留中间的斜杠——它是 id 的一部分,不是 URL 路径。
  • curl 不需要装任何东西;Python 示例只用到标准库加 requests。

PixVerse V6 文生视频把一段文本提示词变成 1–15 秒、360p–1080p 的视频片段。它走统一的异步任务接口:提交任务 → 轮询结果 → 在输出 URL 过期前把视频下载走。

最小可跑请求(curl)

把任务提交到 POST /v1/tasks:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<你的 key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "pixverse-v6/text-to-video",
    "input": {
      "prompt": "清晨阳光下,一只红色的狐狸小跑着穿过新雪,电影质感,慢动作",
      "aspect_ratio": "16:9",
      "duration": 5,
      "resolution": "720p"
    }
  }'

返回里拿到一个任务 id:

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

然后轮询 GET /v1/tasks/<taskId>,直到 data.status 变成 success:

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-.... \
  -H "Authorization: Bearer sk-<你的 key>"

成功后,成品视频的 URL 在 data.output[0].url:

{
  "code": 200,
  "data": {
    "status": "success",
    "storage": "temp",
    "output": [
      { "type": "video", "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1793036664 }
    ]
  },
  "message": "success"
}

这个输出 URL 是临时的——它带一个 expireAt 时间戳(实测是生成后 7 天)。请立刻把 .mp4 下载下来、存到你自己的对象存储,不要直接热链这个地址。

同样的流程(Python)

import time, requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<你的 key>", "Content-Type": "application/json"}

def create_task():
    payload = {
        "model": "pixverse-v6/text-to-video",
        "input": {
            "prompt": "清晨阳光下,一只红色的狐狸小跑着穿过新雪,电影质感,慢动作",
            "aspect_ratio": "16:9",
            "duration": 5,
            "resolution": "720p",
        },
    }
    r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    data = r.json()
    task_id = (data.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"创建失败: {data}")
    return task_id

def wait_for(task_id, timeout_s=600):
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        try:
            r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
            task = (r.json().get("data") or {})
        except requests.RequestException:
            time.sleep(5)          # 单次网络抖动不该让整个轮询中止
            continue
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"任务失败: {task.get('error')}")
        time.sleep(5)              # 还在排队/渲染——用同一个 task_id 继续轮询
    raise TimeoutError(task_id)

task_id = create_task()
url = wait_for(task_id)
video = requests.get(url, timeout=120).content
open("out.mp4", "wb").write(video)
print("已保存 out.mp4")

轮询循环只对 success 和 fail 两个终态做判断,其它状态一律继续等——这样无论渲染途中报告的是 handling 还是 archiving,代码都不会误判。关键一点:如果某一次轮询请求本身报错,睡一下再用保存好的同一个 task_id 重新查,不要重新提交任务——重新提交会再渲染一次、再扣一次费。

pixverse-v6/text-to-video 真正校验的参数

下面这些是端点实际接受的字段。每一个我都通过给它发一个非法值、读回它自己的校验报错来确认过,并和模型文档做了交叉核对:

字段类型取值 / 范围默认值说明
promptstring1–2048 字节 UTF-8(1 个汉字 = 3 字节,约 682 字)—必填。
aspect_ratioenum16:9、4:3、1:1、3:4、9:16、2:3、3:2、21:916:9注意它支持 21:9(超宽)和 2:3/3:2。
durationinteger1–155单位秒,必须是整数,不能是字符串。
resolutionenum360p、540p、720p、1080p720p输出分辨率。
generate_audiobooleantrue / falsefalse是否同时生成背景音乐、音效和对白;默认关闭,要音频得显式打开。
negative_promptstring最多 2048 字节 UTF-8—可选;想要避开的内容。
seedinteger任意整数—可选;同 seed + 同 prompt 可复现同一结果。
styleenumanime、3d_animation、clay、comic、cyberpunk无可选的风格预设,留空保持自然画风。

如果要用回调而不是轮询,input 同级还可以带一个 callback 对象:url(HTTPS 回调地址)+ when(目前只有 final,即任务终态时回调)。

生产环境写法

  • 这是一个封闭 schema。 任何不在上表里的字段都会被直接拒绝,报 invalid input: <root>: additional properties '<字段>' not allowed。这其实是好事:拼错或臆想出来的字段会在提交时就响亮地失败,而不是被悄悄忽略。
  • duration 是整数,这点和平台上某些收字符串("6")的视频模型不一样。发 "5" 会得到 invalid input: duration: got string, want integer;越界值会直接把边界告诉你,比如 duration: maximum: got 999, want 15、duration: minimum: got 0, want 1。
  • 报错一次只报一个字段,envelope 是扁平的:{"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: aspect_ratio: value must be one of ..."}。修掉它报的字段再重发,下一个非法字段(如果有)会在下一次调用时冒出来。
  • 任务失败时 HTTP 仍然是 200。 失败信息在响应体的 data.status: "fail" 里,要判断的是这个 status 字段,而不是 HTTP 状态码。
  • 轮询还是回调? 轻量脚本用轮询最简单;要规模化、不想一直挂着连接,就用 callback。无论哪种,拿到 output[0].url 都要立刻下载——URL 带 expireAt,过期后会变成 404。

实测记录:我真的跑了一次

这篇不是只做了只读探针——我用一个真实请求把完整生命周期跑通了一遍,记录如下:

  • 创建:上面那个 720p / 5 秒 / 16:9 的请求发出去,立刻返回 {"code":200,"data":{"taskId":"tk-hiapi-01M5AM..."},"message":"success"}。注意 taskId 是 tk-hiapi- 前缀的字符串,不是 UUID。
  • 轮询:GET /v1/tasks/<id> 的 data.status 依次经过 handling → archiving → success,整条 5 秒片子从创建到完成大约 74 秒。
  • 输出:终态里 data.output[0] 是 {"type":"video","url":"https://temp.hiapi.ai/....mp4","expireAt":...,"artifactId":"...","storage":"temp"}。expireAt 减去创建时间正好是 604800 秒,也就是 7 天。
  • 产物:对那个输出 URL 做 HEAD,拿到 content-type: video/mp4、大小约 2.2 MB,确认是一个有效的 mp4 文件。

关于音频的一个纠正值得单独记:我分别用非法值探过几个相邻字段名——generate_audio 报 got string, want boolean(说明它是一个合法的布尔字段),而 sound、audio 都报 additional properties not allowed(不存在)。也就是说,音频是通过 generate_audio 这个开关控制的,默认 false;定价页上也相应有「Sound On / Sound Off」两档。本次实测我没有打开 generate_audio,所以产出的是一段无声片。

我没有对画面质量做主观评价(本次只核实了请求契约、任务生命周期和产物是合法 mp4),这部分请你用自己的提示词实际生成后判断。

费用怎么算

pixverse-v6/text-to-video 按秒计费(计费因子就是 duration),时长越长越贵;分辨率越高、以及打开 generate_audio 走「Sound On」档,每秒单价都会更高。具体的每秒费率以定价页上的实时数据为准,批量生成前先过一眼。

相关链接

常见问题

duration 是秒还是帧? 秒——1 到 15 之间的任意整数,默认 5。

能生成带声音的视频吗? 能。把 generate_audio 设为 true,模型会连背景音乐、音效和对白一起生成;默认是 false(无声)。开启音频会走更贵的计费档,详见定价页。

提示词能写多长? 上限是 2048 字节 UTF-8。中文一个字算 3 字节,所以大约 682 个汉字封顶。

它和图生视频有什么区别? 本端点(pixverse-v6/text-to-video)只从文本提示词出发。图生视频是另一个 model id,接收一张起始图、把它动起来——想让一张现成画面动起来而不是凭空生成,就用那个。

为什么我的请求报 "additional properties not allowed"? 你传了一个不在 schema 里的字段。输入只接受 prompt、aspect_ratio、duration、resolution、generate_audio、negative_prompt、seed、style 这几个。

现在就用 HiAPI 生成

选一个模型,输入你的提示词,直接查看生成结果。

HiAPI Blog

相关文章

HiAPI

现在就用 HiAPI 生成

开始生成