TL;DR
grok-imagine-1.5-lite/text-to-video 可把文字提示词变成带音频的1–15秒视频,提供480p、720p和1080p档位。本文介绍HiAPI请求示例、输入参数、任务结果查询与预算。
720p请求5秒为$0.215;各档预算见Grok Lite价格指南。
1. 要完成什么,需要准备什么
目标:发送文字提示词,获得可下载的带音频MP4视频。
需要HiAPI API Key,可在控制台创建,并只保存在服务端。请求通过Authorization: Bearer头认证,下方调用都需要认证。
使用HiAPI /v1/tasks接口:提交任务后保存data.taskId,再查询结果或接收回调。提交响应不包含已完成的视频。
2. 最小调用示例
先创建任务,再查询结果。
创建任务(curl)
先设置环境变量 HIAPI_API_KEY 和持久的业务键 HIAPI_JOB_KEY;同一业务任务保持原键和原请求体,示例之间请求体不同时不要复用键。已有任务先设 HIAPI_TASK_ID,直接查询,不再次提交。curl 只用于已确认的新任务;提交响应丢失时先找回原任务,不能因为超时或错误就重跑 POST。
if [ -n "${HIAPI_TASK_ID:-}" ]; then
curl --connect-timeout 10 --max-time 30 \
-H "Authorization: Bearer ${HIAPI_API_KEY:?Set HIAPI_API_KEY}" \
"https://api.hiapi.ai/v1/tasks/${HIAPI_TASK_ID}"
else
curl --connect-timeout 10 --max-time 30 -s -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer ${HIAPI_API_KEY:?Set HIAPI_API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${HIAPI_JOB_KEY:?Set a stable business key}" \
-d '{
"model": "grok-imagine-1.5-lite/text-to-video",
"input": {
"prompt": "A red fox trots across fresh snow at dawn, breath steaming, soft morning light, gentle ambient wind. Cinematic, natural colors. No text.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}
}'
fi
将model放在请求顶层,生成参数放在input内。修改示例时保留这个结构。
提交成功后返回data.taskId。下面仅示意返回结构,ID为占位符:
{ "code": 200, "data": { "taskId": "TASK_ID" }, "message": "success" }
查询结果(Python)
Python 将请求指纹和 taskId 保存在本地 .hiapi-jobs;保留此目录,不靠更换业务键或删除状态重试。拿到 ID 后立即打印并保存;文件保存失败时将打印的 ID 设为 HIAPI_TASK_ID。已有 ID、查询中断或下载失败都续查原任务;提交结果不明则停下恢复。先看具体 error code/message,不按 HTTP 状态自动重新提交;处理中保留原键、原请求体与 ID,冲突核对原请求体,只有明确的新业务任务才用新键。这里没有无限期幂等保证。300 秒轮询、120 秒下载等待是客户端本地限制,网络连接/读取另设超时,不是生成耗时承诺。
def generate(prompt, duration=5, resolution="720p", aspect_ratio="16:9"):
import hashlib
import json
import os
import time
from pathlib import Path
from urllib.parse import quote
import requests
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
"Content-Type": "application/json"}
KEY = os.environ["HIAPI_JOB_KEY"].strip()
if not KEY:
raise ValueError("Set a stable HIAPI_JOB_KEY for this business task")
payload = {
"model": "grok-imagine-1.5-lite/text-to-video",
"input": {"prompt": prompt, "duration": duration, "resolution": resolution, "aspect_ratio": aspect_ratio},
}
fingerprint = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
state_path = Path(".hiapi-jobs") / (hashlib.sha256(KEY.encode()).hexdigest() + ".json")
state_path.parent.mkdir(exist_ok=True)
recovery_id = os.environ.get("HIAPI_TASK_ID", "").strip()
if state_path.exists():
saved = json.loads(state_path.read_text(encoding="utf-8"))
if saved["fingerprint"] != fingerprint:
raise RuntimeError("Request changed for this key; compare the original body before continuing")
else:
saved = {"fingerprint": fingerprint, "taskId": None}
# Exclusive creation records intent BEFORE POST; concurrent starts fail closed.
with state_path.open("x", encoding="utf-8") as f:
json.dump(saved, f)
saved["new_local_job"] = True
task_id = saved.get("taskId")
if task_id and recovery_id and task_id != recovery_id:
raise RuntimeError("Recovery ID conflicts with saved taskId")
if not task_id:
task_id = recovery_id
if not task_id and not saved.get("new_local_job"):
raise RuntimeError("Submission outcome unknown; recover the original taskId, do not submit again")
if not task_id:
try:
response = requests.post(BASE, headers={**HEADERS, "Idempotency-Key": KEY},
json=payload, timeout=(10, 30))
response.raise_for_status()
task_id = response.json()["data"]["taskId"]
if not isinstance(task_id, str) or not task_id:
raise ValueError("Missing taskId")
except (requests.RequestException, ValueError, KeyError, TypeError):
raise RuntimeError("Submission stopped; inspect the specific error safely and recover before resubmitting") from None
print(f"taskId={task_id}", flush=True)
# If saving fails, use the printed ID as HIAPI_TASK_ID; never repeat POST.
state_tmp = state_path.with_suffix(".json.tmp")
state_tmp.write_text(json.dumps({"fingerprint": fingerprint, "taskId": task_id}), encoding="utf-8")
state_tmp.replace(state_path)
deadline = time.monotonic() + 300
query_url = f"{BASE}/{quote(task_id, safe='')}"
while time.monotonic() < deadline:
try:
response = requests.get(query_url, headers=HEADERS, timeout=(10, 30))
except requests.RequestException:
time.sleep(5)
continue
if response.status_code == 429 or response.status_code >= 500:
time.sleep(5)
continue
response.raise_for_status()
task = response.json()["data"]
if task["status"] == "fail":
raise RuntimeError(f"Task failed; inspect data.error safely and retain taskId={task_id}")
if task["status"] == "success":
video_url = next(item["url"] for item in task["output"] if item.get("type") == "video")
break
time.sleep(5)
else:
raise TimeoutError(f"Local waiting limit reached; resume taskId={task_id}")
# Download failure resumes this same task on the next run.
part = state_path.with_suffix(".mp4.part")
output = state_path.with_suffix(".mp4")
with requests.get(video_url, stream=True, timeout=(10, 60)) as response:
response.raise_for_status()
download_deadline = time.monotonic() + 120
with part.open("wb") as f:
for chunk in response.iter_content(1024 * 1024):
if time.monotonic() > download_deadline:
raise TimeoutError(f"Download limit reached; resume taskId={task_id}")
f.write(chunk)
part.replace(output)
print(f"Saved {output}; taskId={task_id}")
generate("A red fox trots across fresh snow at dawn, gentle ambient wind. Cinematic.")
可用输入参数
生成参数放在input中,不要加入seed、negative_prompt或motion_mode等不支持的字段;镜头和动作要求写进提示词。
| 字段 | 类型 | 必填 | 可用值 |
|---|---|---|---|
prompt | string | 是 | 1–4096字符 |
duration | integer | 否 | 1–15整数秒;默认6 |
resolution | string | 否 | 480p、720p、1080p;默认720p |
aspect_ratio | string | 否 | 16:9、4:3、3:2、1:1、2:3、3:4、9:16;默认16:9 |
本文的文生视频模型没有auto取值。同系列图生视频没有aspect_ratio字段,画幅大致跟随输入图。文生请求建议显式填写比例。
data.status为success时,从data.output找到type: "video"的项目并保存地址;fail时检查data.error,其他状态继续查询。
下面保留模型已有的参考视频,画面主题是梯田上空的玻璃热气球。它是独立样例,不是上面代码中狐狸提示词的输出:
<video controls playsinline preload="metadata" poster="https://static.hiapi.ai/model-covers/2026/10/19/1792425451841-544b99c4d63dae99-1792123103877-544b99c4d63dae99-grok-imagine-1-5-lite-t2v-poster.webp" style="max-width:100%;border-radius:8px"> <source src="https://static.hiapi.ai/model-previews/2026/10/19/1792425556819-c6d78e4247cbe7d7-1792123102637-c6d78e4247cbe7d7-grok-imagine-1-5-lite-t2v.mp4" type="video/mp4"> </video>3. 接入业务前的处理
使用回调接收结果。 脚本可以轮询;服务端可添加callback接收任务终态通知,避免一直占用请求等待。任务进入终态后,平台向指定地址POST任务详情:
{
"model": "grok-imagine-1.5-lite/text-to-video",
"input": { "prompt": "...", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9" },
"callback": { "url": "https://your.app/hooks/hiapi", "when": "final" }
}
此任务类型的when使用"final"。回调可能重试,处理端按taskId去重,重复通知只处理一次。
保存成功结果。 任务成功后下载视频并转存到自己的存储,应用使用保存后的地址;不要假定返回地址有固定保留期限。
按请求时长计费。 duration乘请求分辨率的单价:480P每秒$0.029、720P每秒$0.043、1080P每秒$0.20。720P请求5秒为$0.215,1080P请求5秒为$1.00,480P请求1秒为$0.029。1080P单价约为720P的4.65倍,按实际分辨率需求选择。当前价格见价格页。
处理报错。 提交返回HTTP 400时,检查请求结构、必填提示词、整数时长及上表取值,并将返回错误与请求信息一同保存。
已接收的任务若在后续失败,详情中的data.status会是fail,并提供data.error。查询时需检查任务状态,不能仅凭HTTP状态码判断任务成功。
4. 如何检查结果
- 确认任务到达
success,且输出中包含视频。 - 检查下载文件的真实尺寸与时长;请求档位不能证明每种比例都输出固定像素尺寸。
- 单独听审音频。提示词里的风声、台词或音乐是创作要求,不能据此认定成片已生成或准确同步。
- Python示例中的300秒是客户端等待上限,不是生成耗时保证;超时后继续查询已保存的同一个任务ID。
5. Lite与标准Grok Imagine视频API
根据输入与所需参数选择接口:
grok-imagine-1.5-lite/text-to-video(本文):480p / 720p / 1080p,1–15秒,对应每秒$0.029 / $0.043 / $0.20。grok-imagine/text-to-video:已列480p / 720p / 1080p单价为每秒$0.0114 / $0.0214 / $0.057142。差异见对比指南;Grok文生视频中不只有Lite提供1080p价格档。
已有静态图时,使用grok-imagine-1.5-lite/image-to-video,传入一个image_url。它与Lite文生视频每秒价相同,但每次请求另加$0.015输入图费:720p请求5秒共$0.230。用法见图生视频指南。
6. 相关页面
常见问题
必须轮询,还是也能用回调?
两种方式都可以。脚本轮询GET /v1/tasks/{taskId};服务端可配置callback.url与when: "final",按taskId去重。
请求体应该怎么组织?
model放在顶层,生成字段放在input内:{"model": "...", "input": { ... }}。
可以关闭音频吗?
请求参数没有音频关闭字段;需要无声成片时可在后期移除音轨。具体音效仍需听审确认。
应该怎么保存结果?
成功后下载视频并自行转存,本文不为结果地址设定固定过期时间。
480p请求1秒多少钱?
按本文文生视频单价为$0.029;720p请求5秒的示例为$0.215。




