HiAPI
博客

教程

如何通过 HiAPI API 调用 hailuo-2.3/text-to-video:curl、Python 与可运行的请求示例

2026年11月3日
极简封面图:浅藕紫色与墨黑色两块纯色平面以一道清晰的硬边相接,边缘有一条细紫缝,构图庄重平静。

hailuo-2.3/text-to-video 端点做什么

如果你有一个文本提示词,并希望据此生成一段短视频片段,hailuo-2.3/text-to-video 就是你要找的端点。它接收一段自然语言提示词,用来描述场景、主体以及你希望看到的运动;随后返回生成的视频片段。该模型针对短篇幅输出做了调优,因此当你要求一个紧凑、自成一体的瞬间,而不是一段长篇叙事时,它的效果最佳。

在 HiAPI 上,调用方式与其他异步生成端点遵循相同的模式:你发送请求,服务接受任务,然后你轮询直到结果就绪。这意味着该端点非常适合后端流水线——内容工具、原型生成器、批处理任务,或任何需要按需获取几秒钟视频、而无需人工坐在视频编辑器前的场景。

请求携带一个提示词和少量生成控制参数;响应携带任务标识符,随后是完成视频的 URL。你无需管理 GPU 或模型权重——HiAPI 负责计算,并返回输出链接。如果你用过其他文本转视频 API,整体形态会让你感到熟悉,但 hailuo-2.3 的提示词风格更奖励对物理运动的思考,而不仅仅是视觉描述(后文会详细说明)。

前置条件与 API 凭据

在首次调用之前,请确保准备好三样东西:

  • 来自你的 HiAPI 账户的 API 密钥。像对待密码一样对待它:不要纳入版本控制,从环境变量加载,如果泄露就轮换。
  • 一个 HTTP 客户端。下面的 shell 示例只需要 curl。Python 示例需要 Python 3.8+ 以及 requests 库(pip install requests)。
  • HiAPI API 基础 URL。所有请求都发送到 HiAPI API 主机,端点路径为 hailuo-2.3/text-to-video。你通过在 Authorization 请求头中发送 bearer token 来进行认证。

将密钥设置到环境变量中,这样它就不会出现在你的代码里:

export HIAPI_API_KEY="your_api_key_here"

在 Python 中,你可以用 os.environ["HIAPI_API_KEY"] 读取它。在 curl 中,你将使用 $HIAPI_API_KEY 引用同一个变量。

还有一件事需要提前决定:生成的视频将存放在哪里。API 返回输出的 URL,该 URL 应当被及时获取并存储到你自己的存储桶或文件系统中——不要构建一个假定该 URL 是永久资产的流水线。

使用 curl 的可运行请求

下面是一个完整的 curl 调用,用于提交文本转视频任务。请将提示词替换为你自己的场景描述。请求体是 JSON,关键字段是提示词以及控制时长和输出形态的生成参数。

curl -X POST "https://api.hiapi.ai/v1/hailuo-2.3/text-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "一颗玻璃弹珠沿木质斜坡滚下,加速后落到石质地面上,弹跳两次后静止",
    "duration": 6
  }'

成功提交后会返回一个包含任务标识符的 JSON 对象。大致如下:

{
  "id": "job_abc123",
  "status": "queued"
}

关键部分是 id。生成不会同步完成——端点将任务加入队列并立即返回。保存好 id;你将用它轮询状态,并最终获取视频 URL。

如果遇到认证错误,请检查密钥是否在同一 shell 会话中导出。如果遇到校验错误,请检查 JSON 请求体格式是否正确、提示词是否存在。429 响应表示你发送请求过快,应当退避——生产环境部分会详细说明。

Python 中的同一调用

Python 版本做同样的事情,但封装在一个可复用函数中,方便你放入流水线。它提交任务并返回任务标识符。

import os
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def submit_text_to_video(prompt: str, duration: int = 6) -> str:
    """提交一个 hailuo-2.3/text-to-video 任务并返回其任务 id。"""
    api_key = os.environ["HIAPI_API_KEY"]
    response = requests.post(
        f"{HIAPI_BASE}/hailuo-2.3/text-to-video",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={"prompt": prompt, "duration": duration},
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["id"]


if __name__ == "__main__":
    job_id = submit_text_to_video(
        "一颗玻璃弹珠沿木质斜坡滚下,加速后落到石质地面上,弹跳两次后静止"
    )
    print("submitted job:", job_id)

有几个细节值得保留:

  • raise_for_status() 会将非 2xx 响应转为异常,这正是流水线中想要的行为。在提交阶段大声失败,好过轮询一个从未创建的任务。
  • 提交请求的 timeout 故意设置得很短。提交应当很快;长时间的等待发生在轮询阶段,而不是这里。
  • duration 参数 是独立参数,这样调用方可以请求更短或更长的片段,而无需重复构建请求的逻辑。

一旦该函数返回,你就拥有了继续状态轮询所需的一切。

为 6-10 秒片段编写运动物理提示词

短片段不留情面。在六到十秒内,你无法建立角色、构建世界并完成情节收束——因此最有效的提示词是描述一个单一连续动作,并带有清晰的物理后果。把提示词想象成一个瞬间的镜头描述,而不是一个故事。

以主体和动作开头

从什么在移动、它在做什么开始。"一颗玻璃弹珠沿木质斜坡滚下" 立刻给模型提供了主体、材质和行进方向。像 "一个美丽的场景" 这样模糊的开头则什么也没给它,无从动画化。

描述力,而不仅仅是外观

运动物理提示意味着说出起作用的力:重力、摩擦、动量、重量、弹性。滚动、加速、弹跳、静止、摆动、倾倒、溅起、撕裂 等词暗示了一个物理模型。对于弹跳的物体,说明弹跳多少次以及最终停在哪里。对于下落的物体,说明它落在什么上,以及是破碎、凹陷还是反弹。

让镜头明确且简单

固定镜头或一次缓慢的镜头运动通常就足够短片段了。如果镜头和主体都做复杂的事情,片段会变得杂乱,运动看起来就像噪音。只在镜头类型对动作重要时才指明它——特写、广角、跟拍。

构建事件弧线

6–10 秒片段的一个有用模板是:铺垫 → 动作 → 后果。弹珠在斜坡顶端;它滚下并加速;它落下、弹跳两次并静止。这条弧线给模型提供了开头、中间和结尾,且都适配片段长度。避免要求多个不相关的动作;一个描述充分的物理事件,读起来远好于三个半途而废的事件。

最后,保持提示词具体。材质、光照和表面纹理帮助模型为运动提供依据——木上的弹珠与冰上的弹珠行为不同,说明这一点能引导结果。

通过轮询处理异步任务

生成需要时间,因此该端点是异步的。提交任务后你会收到一个 id;然后你轮询状态端点,直到任务达到终态。健壮的轮询循环要处理三件事:间隔、超时和错误暴露。

import time
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def wait_for_video(job_id: str, api_key: str, interval: float = 3.0, max_wait: float = 600.0) -> str:
    """轮询直到任务完成,并返回输出视频 URL。"""
    deadline = time.time() + max_wait
    url = f"{HIAPI_BASE}/hailuo-2.3/text-to-video/{job_id}"

    while time.time() < deadline:
        response = requests.get(
            url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        data = response.json()
        status = data.get("status")

        if status == "completed":
            return data["output"]["video_url"]
        if status in ("failed", "cancelled"):
            raise RuntimeError(f"任务 {job_id} 以状态 {status} 结束:{data.get('error')}")

        time.sleep(interval)

    raise TimeoutError(f"任务 {job_id} 未在 {max_wait} 秒内完成")

关于该循环的说明:

  • 按间隔轮询,不要用紧凑循环。 检查之间间隔几秒就足够了,可以避免冲击 API。
  • 始终限制总等待时间。 卡住的任务不应永远挂起工作进程。这里的 max_wait 值较为保守;请根据你的片段长度和队列状况进行调整。
  • 将 failed 视为真实分支。 暴露错误载荷,而不是盲目重试——提示词或参数问题不会自行修复。
  • 返回视频 URL,而不是原始响应。 该函数的调用方不应需要了解响应结构。

对于更重的工作负载,将提交和轮询步骤放在不同的工作进程中:一个工作进程将任务入队并存储任务 ID,另一个负责轮询和下载。这样就将请求延迟与生成时间解耦。

下载与存储输出

一旦轮询返回视频 URL,就获取字节并写入持久位置。要及时执行:返回的 URL 是交付链接,不是永久资产存储。以流式方式下载,而不是将整个文件加载到内存中;先写入临时路径再重命名,这样部分下载永远不会看起来像已完成文件。

import os
import tempfile
import requests


def download_video(video_url: str, dest_path: str) -> None:
    """以原子方式将完成的视频流式写入 dest_path。"""
    os.makedirs(os.path.dirname(dest_path) or ".", exist_ok=True)
    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(dest_path) or ".")
        try:
            with os.fdopen(fd, "wb") as f:
                for chunk in response.iter_content(chunk_size=1 << 16):
                    f.write(chunk)
            os.replace(tmp_path, dest_path)
        except Exception:
            if os.path.exists(tmp_path):
                os.unlink(tmp_path)
            raise


api_key = os.environ["HIAPI_API_KEY"]
video_url = wait_for_video("job_abc123", api_key)
download_video(video_url, f"out/{'job_abc123'}.mp4")

几个实用选择:

  • 按任务 ID 命名文件。 这给你一个稳定、抗冲突的键,并让将文件关联回产生它的请求变得轻而易举。
  • 将元数据与视频一起存储。 将原始提示词、时长和时间戳保存在附属 JSON 或数据库中。六个月后,你会想知道某个片段是由什么产生的。
  • 生产环境中上传到对象存储。 写入本地磁盘对原型来说没问题;真实流水线应将文件推送到你的存储桶并记录对象键,这样视频能在工作进程重启后存活。

生产环境提示与常见故障模式

大多数首次集成都会在同样几处地方出问题。以下是需要注意的事项。

重试正确的事情

对瞬态故障重试——网络错误、超时、429 和 5xx 响应——使用指数退避和抖动。不要对 4xx 校验错误重试;格式错误的提示词或错误参数每次都会以同样方式失败。如果生成任务本身失败,暴露错误并审慎决定是否重新提交。

分离提交与轮询

在生产环境中,提交和轮询应是不同步骤,通常在不同进程中。提交成功后立即将任务 ID 存入队列或数据库。如果工作进程崩溃,你可以恢复轮询,而不是丢失任务。

处处设置超时

提交请求、状态轮询和文件下载都应各自有超时。下载步骤缺少超时是工作进程挂起的经典原因。

将提示词保持在模型优势范围内

在六到十秒范围内请求单一、物理上合理的动作。当提示词要求过多时,你会得到一个运动浑浊的杂乱片段。如果输出质量不一致,先缩短提示词并简化动作,再考虑更改参数。

正确处理凭据

从环境变量或密钥管理器加载 API 密钥,绝不从已提交的文件加载。每个环境使用不同密钥,这样泄露的开发密钥无法触及生产环境。

警惕 URL 过期假设

生产环境中最常见的错误,是把返回的视频 URL 当作永久链接,并在数月后直接在用户界面中渲染它。将下载并重新托管文件作为任务的一部分,并存储你自己的 URL。

有了这些习惯,集成就很小:提交、轮询、下载、存储。

立即开始构建持久 AI 产物

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

阅读 API 文档