视频生成 API
OpenAI 兼容的视频生成端点,支持 grok-video-3 系列。SSE 流式响应,每个请求生成一段视频。
请求
POST /v1/videos
请求头
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
Accept: text/event-stream
也可以使用 x-api-key 头(Anthropic SDK 风格)。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 视频模型名称,见下方"支持的模型" |
prompt | string | ✅ | 视频描述,最长 32000 字符 |
image_url | string | ❌ | 起始帧参考图,启用图生视频。两种格式:HTTPS URL 或 Base64 Data URI |
aspect_ratio | string | ❌ | 画面比例,可选 1:1、16:9、9:16、4:3、3:4、3:2、2:3 |
size | string | ❌ | 分辨率,可选 720P 或 1080P |
seconds | integer | ❌ | 时长,可选 6、10、15(也可通过模型名直接指定) |
支持的模型
| 模型 | 时长 | 单价 | 用途 |
|---|---|---|---|
grok-video-3 | 默认 6 秒 | $0.04 | 短视频,最快出图 |
grok-video-3-10s | 10 秒 | $0.04 | 中等长度 |
grok-video-3-15s | 15 秒 | $0.04 | 长视频 |
实时定价以 /pricing 为准。
响应(SSE 流式)
视频生成耗时约 60-120 秒。响应是 text/event-stream 格式,包含进度事件和最终结果:
data: {"id":"vg_xxx","object":"video.queued","progress":0,"model":"grok-video-3","created":1778079019}
data: {"id":"vg_xxx","object":"video.progress","progress":15,"model":"grok-video-3","created":1778079019}
data: {"id":"vg_xxx","object":"video.progress","progress":33,"model":"grok-video-3","created":1778079019}
... (中间 progress 事件省略) ...
data: {"id":"vg_xxx","object":"video.uploading","progress":100,"model":"grok-video-3","created":1778079019}
data: {"id":"vg_xxx","object":"video.completed","url":"https://api.picklyone.com/api/videos/file?id=vg_xxx","thumbnail_url":"https://api.picklyone.com/api/videos/thumbnail?id=vg_xxx","duration_seconds":6,"size":"720P","aspect_ratio":"16:9","content_length":4015867,"model":"grok-video-3","created":1778079019}
data: [DONE]
事件类型
| object | 含义 |
|---|---|
video.queued | 已接受请求,开始生成 |
video.progress | 生成进度(0-100) |
video.uploading | 上游生成完成,正在转存到 Picklyone 存储 |
video.completed | 全部完成,包含视频 URL |
video.completed 字段
| 字段 | 说明 |
|---|---|
url | 视频下载链接(永久存储,需带 Authorization 访问) |
thumbnail_url | 缩略图链接(如可用) |
content_length | 视频字节数 |
duration_seconds | 时长 |
size / aspect_ratio | 实际输出参数 |
model、created、id | 元信息 |
错误事件
请求过程中如出现错误,最后一个事件是错误对象(不再发 [DONE]):
data: {"error":{"message":"...","code":"upstream_error","type":"video_error"}}
图生视频
grok-video-3 系列支持以参考图为起始帧生成视频。两种入参方式都支持,Picklyone 会自动转换:
方式 A:HTTPS URL(最简单)
{
"model": "grok-video-3",
"prompt": "animate this scene with gentle camera movement",
"image_url": "https://example.com/photo.jpg",
"aspect_ratio": "16:9"
}
Picklyone 会服务端代下载图片并自动 base64 转码后转发给底层模型。
注意事项:
- 必须是 HTTPS URL(HTTP / 私网地址 / localhost 一律拒绝)
- 图片大小 ≤ 10 MB
- 支持格式:
image/jpeg、image/png、image/webp、image/gif - 部分公开图床(Wikimedia、Imgur 等)有反爬保护,可能返回 403 / 429。这种情况改用方式 B
方式 B:Base64 Data URI(最稳定)
{
"model": "grok-video-3",
"prompt": "animate this scene",
"image_url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA..."
}
跳过服务端代下载这一步,绕过任何源站反爬限制,最推荐。
提示:base64 字符串最大可达 13 MB(10 MB 原图 × 4/3)。请求体上限 16 MB。
完整示例
Curl
curl -N -X POST "https://api.picklyone.com/v1/videos" \
-H "Authorization: Bearer pk_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"model": "grok-video-3-10s",
"prompt": "A cute orange tabby kitten playing with a red yarn ball on a wooden floor",
"aspect_ratio": "16:9",
"size": "720P"
}'
Python
import requests
import json
API_KEY = "pk_live_xxxxxxxxxxxxxxxx"
response = requests.post(
"https://api.picklyone.com/v1/videos",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"Accept": "text/event-stream",
},
json={
"model": "grok-video-3",
"prompt": "A panda eating bamboo in a forest, slow zoom",
"aspect_ratio": "16:9",
},
stream=True,
timeout=300, # 视频生成耗时长,至少 5 分钟
)
video_url = None
for line in response.iter_lines():
if not line or not line.startswith(b"data: "):
continue
payload = line[6:].strip()
if payload == b"[DONE]":
break
event = json.loads(payload)
if "error" in event:
raise RuntimeError(f"Generation failed: {event['error']}")
obj = event.get("object")
if obj == "video.progress":
print(f"Progress: {event['progress']}%")
elif obj == "video.completed":
video_url = event["url"]
print(f"Video URL: {video_url}")
# 下载视频(注意:URL 需要授权访问)
if video_url:
video = requests.get(
video_url,
headers={"Authorization": f"Bearer {API_KEY}"},
stream=True,
)
with open("output.mp4", "wb") as f:
for chunk in video.iter_content(chunk_size=8192):
f.write(chunk)
print("Saved to output.mp4")
Node.js / TypeScript
const API_KEY = "pk_live_xxxxxxxxxxxxxxxx";
const response = await fetch("https://api.picklyone.com/v1/videos", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
Accept: "text/event-stream",
},
body: JSON.stringify({
model: "grok-video-3",
prompt: "A serene lake at sunset with mountains in the background",
aspect_ratio: "16:9",
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
let buffer = "";
let videoUrl: string | null = null;
outer: while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const data = line.slice(6).trim();
if (data === "[DONE]") break outer;
const event = JSON.parse(data);
if (event.error) throw new Error(event.error.message);
if (event.object === "video.progress") {
console.log(`Progress: ${event.progress}%`);
} else if (event.object === "video.completed") {
videoUrl = event.url;
console.log("Video URL:", event.url);
}
}
}
// 下载视频
if (videoUrl) {
const r = await fetch(videoUrl, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const buf = Buffer.from(await r.arrayBuffer());
require("fs").writeFileSync("output.mp4", buf);
}
图生视频示例(Base64)
import base64, requests, json
with open("input.jpg", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
response = requests.post(
"https://api.picklyone.com/v1/videos",
headers={
"Authorization": "Bearer pk_live_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Accept": "text/event-stream",
},
json={
"model": "grok-video-3",
"prompt": "animate this scene with gentle motion",
"image_url": f"data:image/jpeg;base64,{b64}",
},
stream=True,
timeout=300,
)
# ... 同上面的事件处理逻辑
计费方式
视频模型采用按次计费:
- 每段视频固定价格(见上方"支持的模型")
- 失败请求(参数验证失败、上游错误、流式中断等)自动退款,不收费
- 实际扣费明细见 API 调用日志
错误码
| HTTP | code | 说明 |
|---|---|---|
| 400 | invalid_request | 参数验证失败(无效 model / prompt / aspect_ratio 等) |
| 400 | invalid_image_url | image_url 失败:状态码非 2xx / 非 HTTPS / 不支持的图片类型 / 超过 10MB / SSRF 拦截 |
| 400 | image_input_not_supported | 该模型不支持图生视频,去掉 image_url 字段后重试 |
| 401 | invalid_api_key | API Key 无效或缺失 |
| 402 | insufficient_balance | 余额不足 |
| 403 | MODEL_ACCESS_DENIED | 该模型对你的账号或 API Key 不开放 |
| 403 | ip_not_allowed | API Key 的 IP 白名单不包含当前来源 IP |
| 404 | model_not_found | 模型不存在 |
| 413 | request_too_large | 请求体超过 16 MB |
| 429 | rate_limit_exceeded | 视频请求频率超限 |
| 502 | upstream_error | 上游服务异常(自动退款) |
| 502 | stream_error | 流式响应中断(自动退款) |
| 503 | billing_unavailable | 计费服务暂时不可用 |
重要说明
- 耗时较长:单次生成 60-120 秒,请把客户端请求超时设到至少 5 分钟
- Heartbeat 机制:上游静默超过 25 秒时,Picklyone 会发
{progress:0, heartbeat:true}心跳事件保活,请客户端忽略不视为正常进度 - 视频持久化:生成的视频和缩略图永久保存在 Picklyone 存储上,URL 长期有效
- 下载需要授权:访问
url/thumbnail_url必须带Authorization: Bearer头 - 图生视频局限:底层视频模型(xAI Grok)对图片有内部审核策略,部分图片会返回
image_input_not_supported。这种情况可换图或改纯文生视频 - 失败自动退款:所有错误路径都会取消预扣费,账单页不会出现失败请求的扣费记录
相关端点
- 聊天补全:Chat Completions API
- 图片生成:Image Generation API
- 图片编辑(图生图):Image Edits API