Grok Video API 接入文档

Grok 视频生成 API 的完整接入说明,包括模型列表、创建任务、状态查询、视频内容下载保存、图生视频参数、错误排查和 JavaScript 示例。

基础信息

GEThttps://img.gpt88.cc/v1/models
POSThttps://img.gpt88.cc/v1/videos/generations
GEThttps://img.gpt88.cc/v1/videos/{id}
GEThttps://img.gpt88.cc/v1/videos/{id}/content
  • Base URLstring必填
    https://img.gpt88.cc。
  • 鉴权方式string必填
    Authorization: Bearer <YOUR_API_KEY>。
  • 请求格式string必填
    application/json。
  • 响应格式string必填
    JSON。
  • 任务类型string必填
    异步任务。创建成功后先返回 task_id,再轮询查询。

获取 API Key

请在 Agent API Keys 创建或复制 API Key。调用时放入请求头:

auth-headerbash
Authorization: Bearer <YOUR_API_KEY>

不要把 API Key 写进前端页面、移动端安装包或公开仓库。推荐只在你的后端服务里转发请求。

查询可用模型

list-models.shbash
curl -X GET "https://img.gpt88.cc/v1/models" \
  -H "Authorization: Bearer <YOUR_API_KEY>"
  • idstring必填
    模型 ID,例如 grok-image-video。
  • objectstring必填
    固定为 "model"。
  • createdinteger
    模型上架时间戳,Unix 秒。
  • owned_bystring
    模型归属 provider,例如 xai。
  • capabilitiesstring[]
    支持能力,例如 video / image / streaming。
  • modalitiesstring[]
    支持模态,例如 video、image。

创建视频任务

接口:

POSThttps://img.gpt88.cc/v1/videos/generations
  • modelstring必填
    模型 ID,例如 grok-image-video 或 grok-video-1.5。
  • promptstring必填
    视频提示词。
  • secondsinteger
    视频秒数,默认建议 4。
  • aspect_ratiostring
    画幅比例,默认建议 16:9。
  • resolutionstring
    清晰度,建议 720p 或 480p。
  • image_urlsarray<string>
    参考图 URL 或 base64 data URL 列表。
  • imagesarray<string>
    兼容字段,含义与 image_urls 相同。不要和 image_urls 同时传。
  • input_referenceobject | string
    单参考图字段,可传 { "image_url": "..." }。
  • reference_imagesarray<string>
    多参考图字段。不要和 input_reference 同时传。

参数建议

  • seconds:grok-image-video 的文生视频和单图生视频建议使用 4、6、8、10、12、15;多参考图建议使用 4、6、8、10。
  • 时长规则:grok-image-video 文生视频和单图生视频最长支持 15s;多参考图最长支持 10s,超过会自动按 10s 处理。
  • aspect_ratio:grok-image-video 推荐 1:1、16:9、9:16、4:3、3:4、3:2、2:3;grok-video-1.5 仅建议 16:9 或 9:16。
  • resolution:常用 720p 和 480p。如果你做批量素材,可优先低分辨率;如果要封面或主视觉,优先高分辨率。
  • 图片要求:参考图最好使用公网可直接访问的 HTTPS 直链,或者完整的 base64 data URL。
curl -X POST "https://img.gpt88.cc/v1/videos/generations" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-image-video",
    "prompt": "A cinematic shot of a red sports car driving through rainy neon streets at night",
    "seconds": 6,
    "aspect_ratio": "16:9",
    "resolution": "720p"
  }'

请求示例

6.1 文生视频

text-to-video.shbash
curl -X POST "https://img.gpt88.cc/v1/videos/generations" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-image-video",
    "prompt": "A cinematic shot of a red sports car driving through rainy neon streets at night",
    "seconds": 6,
    "aspect_ratio": "16:9",
    "resolution": "720p"
  }'

6.2 单参考图生视频

single-reference-image.shbash
curl -X POST "https://img.gpt88.cc/v1/videos/generations" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-image-video",
    "prompt": "Animate the product with a slow rotating camera, soft studio light, premium commercial style",
    "seconds": 6,
    "aspect_ratio": "9:16",
    "resolution": "720p",
    "image_urls": [
      "https://example.com/product.png"
    ]
  }'

单参考图场景下,你也可以使用 input_reference,例如:

single-reference-image.jsonjson
{
  "model": "grok-image-video",
  "prompt": "Animate the product with a slow rotating camera",
  "seconds": 6,
  "aspect_ratio": "9:16",
  "resolution": "720p",
  "input_reference": {
    "image_url": "https://example.com/product.png"
  }
}

6.3 多参考图生视频

multi-reference-image.shbash
curl -X POST "https://img.gpt88.cc/v1/videos/generations" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-image-video",
    "prompt": "Create a smooth product showcase video using these references, luxury lighting, clean background",
    "seconds": 10,
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "image_urls": [
      "https://example.com/ref-1.png",
      "https://example.com/ref-2.png"
    ]
  }'

多参考图时,请不要同时传 input_reference 和 reference_images。 如果你要控制单个商品在多个角度之间切换,建议先整理好图片顺序,再提交任务。

6.4 grok-video-1.5 单图生视频

grok-video-1.5.shbash
curl -X POST "https://img.gpt88.cc/v1/videos/generations" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-video-1.5",
    "prompt": "Use the reference image as the main subject and create a smooth cinematic motion",
    "seconds": 4,
    "aspect_ratio": "16:9",
    "resolution": "480p",
    "image_urls": [
      "https://example.com/reference.png"
    ]
  }'

创建响应

创建成功后会返回视频任务对象。关键字段是 id、request_id 和兼容旧格式的 task_id:

create-response.jsonjson
{
  "id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "object": "video",
  "model": "grok-image-video",
  "status": "queued",
  "progress": 0,
  "created_at": 1780000000
}
  • idstring必填
    任务唯一 ID。
  • request_idstring必填
    上游请求 ID。兼容字段;优先保存 id 作为 OpenAI 兼容接口的查询 ID。
  • task_idstring
    旧版任务接口可能返回的任务 ID;新格式不一定在顶层返回。
  • objectstring必填
    固定为 "video"。
  • modelstring必填
    实际使用的模型 ID。
  • statusstring必填
    任务状态,例如 queued。
  • progressinteger | string必填
    任务进度,常见为百分比字符串。
  • created_atinteger
    创建时间戳,Unix 秒。

OpenAI 兼容响应优先保存:video_id = response.id || response.request_id || response.task_id

查询任务状态

推荐使用 OpenAI 兼容的视频资源路径,根据创建响应中的 id 查询。不要把响应里的相对路径直接当成完整 URL; 需要在前面拼接你的 Base URL。

poll-task.shbash
curl --fail-with-body --max-redirs 0 \
  "https://img.gpt88.cc/v1/videos/video_gpt88_v1_dmlkZW9fYmY2OTEwODkwYmEwNGRjNThiODI4NWMzMTMzN2QwMTI" \
  -H "Authorization: Bearer $GPT88_API_KEY"

生成中的旧格式响应:

poll-progress.jsonjson
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "IN_PROGRESS",
    "progress": "30%",
    "result_url": "",
    "fail_reason": ""
  }
}

兼容旧任务接口的成功响应:

poll-success-legacy.jsonjson
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "SUCCESS",
    "progress": "100%",
    "result_url": "https://example.com/generated-video.mp4",
    "fail_reason": ""
  }
}

兼容旧任务接口的失败响应:

poll-failure-legacy.jsonjson
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "status": "FAILURE",
    "progress": "100%",
    "result_url": "",
    "fail_reason": "Image URL could not be fetched: Fetching image failed with HTTP status 400 Bad Request."
  }
}
  • codestring必填
    通常为 success。
  • messagestring必填
    接口消息。
  • data.task_idstring必填
    任务 ID。
  • data.statusstring必填
    任务状态:SUBMITTED / QUEUED / IN_PROGRESS / NOT_START / SUCCESS / FAILURE。
  • data.progressstring必填
    进度字符串,例如 30% 或 100%。
  • data.result_urlstring
    成功后的临时视频直链。
  • data.fail_reasonstring
    失败原因。

当前 OpenAI 兼容视频资源的成功响应:

video-status-completed.jsonjson
{
  "id": "video_gpt88_v1_dmlkZW9fYmY2OTEwODkwYmEwNGRjNThiODI4NWMzMTMzN2QwMTI",
  "model": "grok-imagine-video",
  "object": "video",
  "progress": 100,
  "request_id": "video_bf6910890ba04dc58b8285c31337d012",
  "status": "completed",
  "url": "/v1/videos/video_bf6910890ba04dc58b8285c31337d012/content",
  "video": {
    "duration": 6,
    "task_id": "video_bf6910890ba04dc58b8285c31337d012",
    "url": "/v1/videos/video_bf6910890ba04dc58b8285c31337d012/content"
  },
  "video_url": "/v1/videos/video_bf6910890ba04dc58b8285c31337d012/content"
}
  • idstring必填
    OpenAI 兼容的视频 ID,例如 video_gpt88_v1_...。用于继续查询和下载。
  • request_idstring
    上游原始请求 ID。通常不需要自行拼接到 OpenAI 兼容接口中。
  • objectstring必填
    固定为 "video"。
  • modelstring必填
    实际使用的模型 ID。
  • statusstring必填
    状态为 completed 时表示可获取成品;失败通常为 failed。
  • progressinteger
    进度百分比,例如 100。
  • urlstring
    视频内容路径或完整 URL。可能是相对路径。
  • video_urlstring
    视频内容路径或完整 URL,与 url 类似。
  • video.urlstring
    嵌套视频对象中的内容路径。
  • video.durationnumber
    视频时长,单位秒。
  • 新格式以顶层 status == "completed" 判断完成;失败时通常为 failed、cancelled 或 expired。
  • 旧格式以 data.status == "SUCCESS" 且 data.result_url 非空判断完成。
  • 处理中状态可能是 queued、in_progress,或旧格式的 SUBMITTED、QUEUED、IN_PROGRESS、NOT_START。

查询内容并保存视频

当状态为 completed 后,可以调用内容接口获取视频二进制。内容接口返回的是视频文件流,不是 JSON, 所以需要使用 -o、write_bytes 或 writeFile 保存。

GEThttps://img.gpt88.cc/v1/videos/{id}/content

你提供的响应中,url、video_url 和 video.url 都指向同一个内容路径。 若字段是以 /v1/ 开头的相对路径,请拼接 https://img.gpt88.cc;更稳定的方式是直接调用/v1/videos/{id}/content 并携带同一个 API Key。

download-video.shbash
curl --fail-with-body --max-redirs 0 \
  "https://img.gpt88.cc/v1/videos/video_gpt88_v1_dmlkZW9fYmY2OTEwODkwYmEwNGRjNThiODI4NWMzMTMzN2QwMTI/content" \
  -H "Authorization: Bearer $GPT88_API_KEY" \
  -o generated-video.mp4
download-video.pypython
import os
from pathlib import Path
import requests

base_url = "https://img.gpt88.cc"
video_id = "video_gpt88_v1_dmlkZW9fYmY2OTEwODkwYmEwNGRjNThiODI4NWMzMTMzN2QwMTI"
headers = {"Authorization": f"Bearer {os.environ['GPT88_API_KEY']}"}

status = requests.get(
    f"{base_url}/v1/videos/{video_id}",
    headers=headers,
    timeout=30,
)
status.raise_for_status()
payload = status.json()

if payload.get("status") != "completed":
    raise RuntimeError(f"video is not ready: {payload}")

content = requests.get(
    f"{base_url}/v1/videos/{video_id}/content",
    headers=headers,
    timeout=120,
)
content.raise_for_status()
Path("generated-video.mp4").write_bytes(content.content)
print("saved generated-video.mp4")
download-video.mjstypescript
import { writeFile } from "node:fs/promises";

const baseUrl = "https://img.gpt88.cc";
const videoId = "video_gpt88_v1_dmlkZW9fYmY2OTEwODkwYmEwNGRjNThiODI4NWMzMTMzN2QwMTI";
const headers = { Authorization: "Bearer " + process.env.GPT88_API_KEY };

const statusResponse = await fetch(baseUrl + "/v1/videos/" + videoId, { headers });
const status = await statusResponse.json();
if (!statusResponse.ok || status.status !== "completed") {
  throw new Error("video is not ready: " + JSON.stringify(status));
}

const contentResponse = await fetch(baseUrl + "/v1/videos/" + videoId + "/content", { headers });
if (!contentResponse.ok) throw new Error("download failed: " + contentResponse.status);
await writeFile("generated-video.mp4", Buffer.from(await contentResponse.arrayBuffer()));
console.log("saved generated-video.mp4");

JavaScript 示例

grok-video.tstypescript
const BASE_URL = 'https://img.gpt88.cc'
const API_KEY = process.env.GPT88_API_KEY

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

function validateVideoRequest({ model, imageUrls }) {
  if (model === 'grok-video-1.5' && imageUrls.length !== 1) {
    throw new Error('grok-video-1.5 only supports exactly one reference image.')
  }

  if (model === 'grok-image-video' && imageUrls.length > 7) {
    throw new Error('grok-image-video supports at most 7 reference images.')
  }
}

async function createVideo({
  model = 'grok-image-video',
  prompt,
  seconds = 4,
  aspectRatio = '16:9',
  resolution = '720p',
  imageUrls = [],
}) {
  validateVideoRequest({ model, imageUrls })

  const body = {
    model,
    prompt,
    seconds,
    aspect_ratio: aspectRatio,
    resolution,
  }

  if (imageUrls.length > 0) {
    body.image_urls = imageUrls
    if (imageUrls.length >= 2 && Number(body.seconds) > 10) {
      body.seconds = 10
    }
  }

  const createResponse = await fetch(\`\${BASE_URL}/v1/videos/generations\`, {
    method: 'POST',
    headers: {
      Authorization: \`Bearer \${API_KEY}\`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  })

  const created = await createResponse.json()
  if (!createResponse.ok) {
    throw new Error(\`Video request failed: \${JSON.stringify(created)}\`)
  }

  const videoId = created.id || created.request_id || created.task_id
  if (!videoId) {
    throw new Error(\`No video id returned: \${JSON.stringify(created)}\`)
  }

  for (let i = 0; i < 60; i += 1) {
    await sleep(5000)

    const pollResponse = await fetch(\`\${BASE_URL}/v1/videos/\${encodeURIComponent(videoId)}\`, {
      headers: {
        Authorization: \`Bearer \${API_KEY}\`,
      },
    })

    const result = await pollResponse.json()
    if (!pollResponse.ok) {
      throw new Error(\`Video poll failed: \${JSON.stringify(result)}\`)
    }

    const status = String(result.status || result.data?.status || '').toLowerCase()
    const completed = ['completed', 'complete', 'done', 'success', 'succeeded'].includes(status)
    if (completed) {
      const contentResponse = await fetch(\`\${BASE_URL}/v1/videos/\${encodeURIComponent(videoId)}/content\`, {
        headers: {
          Authorization: \`Bearer \${API_KEY}\`,
        },
      })
      if (!contentResponse.ok) {
        throw new Error(\`Video download failed: \${contentResponse.status}\`)
      }

      const file = Buffer.from(await contentResponse.arrayBuffer())
      const { writeFile } = await import('node:fs/promises')
      await writeFile(\`generated-\${videoId}.mp4\`, file)
      return {
        video_id: videoId,
        file: \`generated-\${videoId}.mp4\`,
        raw_response: result,
      }
    }

    if (['failed', 'failure', 'cancelled', 'canceled', 'expired'].includes(status)) {
      throw new Error(\`Video generation failed: \${result.error?.message || result.fail_reason || JSON.stringify(result)}\`)
    }
  }

  throw new Error(\`Video generation timeout: \${videoId}\`)
}

常见错误

  • 401:API Key 缺失或错误,检查 Authorization: Bearer <YOUR_API_KEY>。
  • 403:权限、额度或分组限制,检查账号余额、令牌权限和可用模型。
  • 400 prompt is required:prompt 为空。
  • 400 model field is required:model 为空或模型 ID 写错。
  • 400 only supports exactly one reference image:grok-video-1.5 没有传图或传了多张图。
  • 图片抓取失败:图片 URL 无法被服务端访问,换成真实直链或 base64。
  • 任务 FAILURE:上游生成失败、图片不可访问或参数不支持,读取 data.fail_reason。
  • 轮询超时:保留 id 或 request_id,稍后继续查询,不要重复提交生成任务。
  • 下载返回 JSON 而不是视频:检查是否调用了 /v1/videos/{id}/content,并确认请求头带有 API Key。
  • 404 或视频 ID 无效:优先使用响应里的 id 查询;不要把 video.duration 或 task_id 当作视频 ID。

接入注意事项

  • 不要把模型 ID 写死成单个模型,建议通过 GET /v1/models 动态读取。
  • 默认推荐使用 grok-image-video。
  • grok-video-1.5 当前仅用于单参考图生视频。
  • grok-image-video 文生视频和单图生视频最长 15 秒,多参考图最长 10 秒。
  • grok-image-video 多参考图最多 7 张;多参考图请求超过 10 秒会自动按 10 秒处理。
  • grok-video-1.5 只支持单图生视频,最长 15 秒。
  • 新格式的最终视频路径通常在 url、video_url 或 video.url;也可以直接调用 /v1/videos/{id}/content 保存。
  • 旧格式的最终视频 URL 在 data.result_url 字段中;返回相对路径时先拼接 Base URL。
  • 任务失败时可能会出现 progress: 100 或 "100%",这是正常结束状态,请以状态字段判断结果。