跳转到内容

模型能力

视频生成

使用 Grok 视频模型根据文本提示生成视频。API 支持配置时长、宽高比和分辨率,SDK 会自动处理异步轮询。在 grok-imagine-video-1.5 上,文本到视频支持原生 1080p。

快速开始

通过一次 API 调用生成视频:

python
import os
import xai_sdk

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

response = client.video.generate(
    prompt="A glowing crystal-powered rocket launching from the red dunes of Mars, ancient alien ruins lighting up in the background as it soars into a sky full of unfamiliar constellations",
    model="grok-imagine-video-1.5",
    duration=10,
    aspect_ratio="16:9",
    resolution="720p",
)

print(response.url)
python
import os
import time
import requests

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.environ['XAI_API_KEY']}",
}

response = requests.post(
    "https://api.x.ai/v1/videos/generations",
    headers=headers,
    json={
        "model": "grok-imagine-video-1.5",
        "prompt": "A glowing crystal-powered rocket launching from the red dunes of Mars, ancient alien ruins lighting up in the background as it soars into a sky full of unfamiliar constellations",
        "duration": 10,
        "aspect_ratio": "16:9",
        "resolution": "720p",
    },
)

request_id = response.json()["request_id"]

# Poll until the video is ready
while True:
    result = requests.get(
        f"https://api.x.ai/v1/videos/{request_id}",
        headers={"Authorization": headers["Authorization"]},
    )
    data = result.json()
    if data["status"] == "done":
        print(data["video"]["url"])
        break
    elif data["status"] == "expired":
        print("Request expired")
        break
    time.sleep(5)
javascript
import { xai } from "@ai-sdk/xai";
import { experimental_generateVideo as generateVideo } from "ai";

const result = await generateVideo({
    model: xai.video("grok-imagine-video-1.5"),
    prompt: "A glowing crystal-powered rocket launching from the red dunes of Mars, ancient alien ruins lighting up in the background as it soars into a sky full of unfamiliar constellations",
    duration: 10,
    aspectRatio: "16:9",
    providerOptions: {
        xai: { resolution: "720p" },
    },
});

const videoUrl = result.providerMetadata?.xai?.videoUrl;
console.log(videoUrl);
bash
# Start the video generation request
REQUEST_ID=$(curl -s -X POST https://api.x.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "A glowing crystal-powered rocket launching from the red dunes of Mars, ancient alien ruins lighting up in the background as it soars into a sky full of unfamiliar constellations",
    "duration": 10,
    "aspect_ratio": "16:9",
    "resolution": "720p"
  }' | jq -r '.request_id')

# Poll until the video is ready
while true; do
  RESULT=$(curl -s https://api.x.ai/v1/videos/$REQUEST_ID \
    -H "Authorization: Bearer $XAI_API_KEY")
  STATUS=$(echo "$RESULT" | jq -r '.status')
  if [ "$STATUS" = "done" ]; then
    echo "$RESULT" | jq -r '.video.url'
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "Request $STATUS"; echo "$RESULT" | jq .
    break
  fi
  sleep 5
done

视频生成是一个异步过程,通常需要几分钟才能完成。具体时间取决于:

  • 提示复杂度 — 更详细的场景需要额外的处理
  • 时长 — 更长的视频需要更多生成时间
  • 分辨率 — 更高的分辨率(1080p 对比 480p)会增加处理时间
  • 视频编辑 — 与图像转视频或文本转视频相比,编辑现有视频会增加额外开销

视频工作流

使用与您想要创建的视频输出类型相匹配的页面:

工作原理

底层来看,视频生成是一个两步过程:

  1. 开始 — 提交生成请求并获取一个 request_id
  2. 轮询 — 使用 request_id 重复检查状态,直到视频准备就绪

xAI SDK 的 generate()extend() 方法完全抽象了这一过程;它们提交您的请求、轮询结果并返回完成后的视频响应。您无需管理请求 ID 或实现轮询逻辑。对于长时间运行的生成,您可以自定义轮询行为,使用超时和间隔参数,或手动处理轮询以完全控制生成生命周期。

REST API 用户必须手动实现这个两步流程:

步骤 1:开始生成请求

bash
curl -X POST https://api.x.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "A glowing crystal-powered rocket launching from Mars"
  }'

响应:

json
{"request_id": "d97415a1-5796-b7ec-379f-4e6819e08fdf"}

步骤 2:轮询结果

使用 request_id 检查状态。每隔几秒轮询一次,直到视频准备就绪:

bash
curl -X GET "https://api.x.ai/v1/videos/{request_id}" \
  -H "Authorization: Bearer $XAI_API_KEY"

响应包含一个 status 字段,其值如下之一:

状态描述
pending视频仍在生成中
done视频已准备就绪
expired请求已过期
failed视频生成失败

完成时的响应:

json
{
  "status": "done",
  "video": {
    "url": "https://vidgen.x.ai/.../video.mp4",
    "duration": 8,
    "respect_moderation": true
  },
  "model": "grok-imagine-video-1.5"
}

视频作为临时 URL 返回。当您需要时直接访问 xAI 托管的 URL,或者如果需要保留副本,请及时下载/处理它。

配置

视频生成 API 让您可以控制生成视频的输出格式。您可以指定时长、宽高比、分辨率以及(在参考转视频中)预设语音,以匹配您的特定用例。

时长

使用 duration 参数控制视频长度。允许的范围是 1-15 秒。

视频编辑不支持自定义 duration。编辑后的视频保留原始时长,上限为 8.7 秒。

宽高比

比例用途
1:1社交媒体、缩略图
16:9 / 9:16宽屏、移动设备、故事(默认:16:9
4:3 / 3:4演示文稿、肖像
3:2 / 2:3摄影

对于图像转视频生成,输出默认为输入图像的宽高比。如果您指定 aspect_ratio 参数,它将覆盖此设置并将图像拉伸到所需的宽高比。

视频编辑不支持自定义 aspect_ratio — 输出与输入视频的宽高比一致。

分辨率

分辨率描述
1080p全高清质量
720p高清质量
480p标准清晰度,更快的处理速度(默认)

注意: 1080pgrok-imagine-video-1.5 上支持文本转视频和图像转视频。参考转视频上限为 720p。

视频编辑不支持自定义分辨率。输出分辨率与输入视频的分辨率一致,上限为 720p(例如,1080p 输入将缩小到 720p)。

音频

WARNING

参考音频目前仅在美国对可信合作伙伴可用。。

grok-imagine-video-1.5 上,参考转视频 可以通过 reference_audios 携带语音。语音来自内置列表,通过 voice_id 命名;您无法上传自己的音频片段:

属性描述
Source预设的 voice_id(例如 {"voice_id": "eve"}),与文本转语音来自同一列表。标识符不区分大小写
Limit每个请求最多 3 个语音
Prompt按索引引用语音:<AUDIO_0><AUDIO_1><AUDIO_2>

生成的视频默认包含音轨。

示例

python
import os
import xai_sdk

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

response = client.video.generate(
    prompt="Timelapse of a flower blooming in a sunlit garden",
    model="grok-imagine-video-1.5",
    duration=10,
    aspect_ratio="16:9",
    resolution="720p",
)

print(f"Video URL: {response.url}")
print(f"Duration: {response.duration}s")
python
import os
import time
import requests

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.environ['XAI_API_KEY']}",
}

response = requests.post(
    "https://api.x.ai/v1/videos/generations",
    headers=headers,
    json={
        "model": "grok-imagine-video-1.5",
        "prompt": "Timelapse of a flower blooming in a sunlit garden",
        "duration": 10,
        "aspect_ratio": "16:9",
        "resolution": "720p",
    },
)

request_id = response.json()["request_id"]

while True:
    result = requests.get(
        f"https://api.x.ai/v1/videos/{request_id}",
        headers={"Authorization": headers["Authorization"]},
    )
    data = result.json()
    if data["status"] == "done":
        print(f"Video URL: {data['video']['url']}")
        print(f"Duration: {data['video']['duration']}s")
        break
    elif data["status"] == "expired":
        print("Request expired")
        break
    time.sleep(5)
javascript
import { xai } from "@ai-sdk/xai";
import { experimental_generateVideo as generateVideo } from "ai";

const result = await generateVideo({
    model: xai.video("grok-imagine-video-1.5"),
    prompt: "Timelapse of a flower blooming in a sunlit garden",
    duration: 10,
    aspectRatio: "16:9",
    providerOptions: {
        xai: { resolution: "720p" },
    },
});

const videoUrl = result.providerMetadata?.xai?.videoUrl;
console.log(videoUrl);
bash
# Start the video generation request
REQUEST_ID=$(curl -s -X POST https://api.x.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "Timelapse of a flower blooming in a sunlit garden",
    "duration": 10,
    "aspect_ratio": "16:9",
    "resolution": "720p"
  }' | jq -r '.request_id')

# Poll until the video is ready
while true; do
  RESULT=$(curl -s https://api.x.ai/v1/videos/$REQUEST_ID \
    -H "Authorization: Bearer $XAI_API_KEY")
  STATUS=$(echo "$RESULT" | jq -r '.status')
  if [ "$STATUS" = "done" ]; then
    echo "$RESULT" | jq -r '.video.url'
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "Request $STATUS"; echo "$RESULT" | jq .
    break
  fi
  sleep 5
done

请求模式

视频生成端点支持多种模式,由设置的字段决定。每个请求只能激活一种模式:

模式REST API 字段AI SDK 形状描述
文本转视频promptprompt: "..."仅从文本提示生成视频。
图像转视频prompt + imageprompt: { image, text }使用提供的图像作为起始帧生成视频。
参考转视频prompt + reference_imagesreference_audiosprompt: "..." + providerOptions.xai.{ mode: "reference-to-video", referenceImageUrls }由参考图像和/或在 grok-imagine-video-1.5 上的预设语音引导生成视频。
编辑视频/v1/videos/edits + videoprompt: "..." + providerOptions.xai.{ mode: "edit-video", videoUrl }根据提示修改现有视频。
扩展视频/v1/videos/extensions + videoprompt: "..." + providerOptions.xai.{ mode: "extend-video", videoUrl }从现有视频的最后一帧扩展。

以下组合不被允许,将返回 400 Bad Request 错误:

  • image + reference_images — 使用其中一个
  • 在 AI SDK 中混合 mode 值 — 每个请求只支持 "edit-video""extend-video""reference-to-video" 中的一个

当您省略 mode 时,AI SDK 使用标准生成。

自定义轮询行为

使用 SDK 的 generate()extend() 方法时,您可以控制等待时间和检查结果的频率:

Python SDKAI SDK (providerOptions.xai)描述默认值
timeoutpollTimeoutMs等待视频完成的最长时间10 分钟
intervalpollIntervalMs状态检查之间的时间间隔100 毫秒
python
import os
from datetime import timedelta
import xai_sdk

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

response = client.video.generate(
    prompt="Epic cinematic drone shot flying through mountain peaks",
    model="grok-imagine-video-1.5",
    duration=15,
    timeout=timedelta(minutes=15),  # Wait up to 15 minutes
    interval=timedelta(seconds=5),  # Check every 5 seconds
)

print(response.url)
javascript
import { xai } from "@ai-sdk/xai";
import { experimental_generateVideo as generateVideo } from "ai";

const result = await generateVideo({
    model: xai.video("grok-imagine-video-1.5"),
    prompt: "Epic cinematic drone shot flying through mountain peaks",
    duration: 15,
    providerOptions: {
        xai: {
            pollTimeoutMs: 15 * 60 * 1000,  // Wait up to 15 minutes
            pollIntervalMs: 5 * 1000,        // Check every 5 seconds
        },
    },
});

const videoUrl = result.providerMetadata?.xai?.videoUrl;
console.log(videoUrl);

如果视频在超时期间内未准备就绪,Python SDK 会引发 TimeoutError,AI SDK 通过其 AbortSignal 中止。为了更精细的控制,请使用手动轮询方法;Python SDK 提供 start()get() 方法,而 AI SDK 支持自定义 abortSignal 以实现取消。

手动处理轮询

为了对生成生命周期进行细粒度控制,使用 start()extend_start() 分别启动生成/扩展请求,使用 get() 检查状态。

get() 方法返回一个包含 status 字段的响应。从 SDK 导入状态枚举:

python
import os
import time
import xai_sdk
from xai_sdk.proto import deferred_pb2

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

# Start the generation request
start_response = client.video.start(
    prompt="A cat lounging in a sunbeam, tail gently swishing",
    model="grok-imagine-video-1.5",
    duration=5,
)

print(f"Request ID: {start_response.request_id}")

# Poll for results
while True:
    result = client.video.get(start_response.request_id)
    
    if result.status == deferred_pb2.DeferredStatus.DONE:
        print(f"Video URL: {result.response.video.url}")
        break
    elif result.status == deferred_pb2.DeferredStatus.EXPIRED:
        print("Request expired")
        break
    elif result.status == deferred_pb2.DeferredStatus.FAILED:
        print("Video generation failed")
        break
    elif result.status == deferred_pb2.DeferredStatus.PENDING:
        print("Still processing...")
        time.sleep(5)
python
import os
import time
import requests

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {os.environ['XAI_API_KEY']}",
}

# Step 1: Start generation
response = requests.post(
    "https://api.x.ai/v1/videos/generations",
    headers=headers,
    json={
        "model": "grok-imagine-video-1.5",
        "prompt": "A cat lounging in a sunbeam, tail gently swishing",
        "duration": 5,
    },
)

request_id = response.json()["request_id"]
print(f"Request ID: {request_id}")

# Step 2: Poll for results
while True:
    result = requests.get(
        f"https://api.x.ai/v1/videos/{request_id}",
        headers={"Authorization": headers["Authorization"]},
    )
    data = result.json()

    if data["status"] == "done":
        print(f"Video URL: {data['video']['url']}")
        break
    elif data["status"] == "expired":
        print("Request expired")
        break
    elif data["status"] == "failed":
        print("Video generation failed")
        break
    else:
        print("Still processing...")
        time.sleep(5)
javascript
// Step 1: Start generation
const response = await fetch("https://api.x.ai/v1/videos/generations", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.XAI_API_KEY}`,
    },
    body: JSON.stringify({
        model: "grok-imagine-video-1.5",
        prompt: "A cat lounging in a sunbeam, tail gently swishing",
        duration: 5,
    }),
});

const { request_id } = await response.json();
console.log(`Request ID: ${request_id}`);

// Step 2: Poll for results
while (true) {
    const result = await fetch(`https://api.x.ai/v1/videos/${request_id}`, {
        headers: { "Authorization": `Bearer ${process.env.XAI_API_KEY}` },
    });

    const data = await result.json();

    if (data.status === "done") {
        console.log(`Video URL: ${data.video.url}`);
        break;
    } else if (data.status === "expired") {
        console.log("Request expired");
        break;
    } else if (data.status === "failed") {
        console.log("Video generation failed");
        break;
    } else {
        console.log("Still processing...");
        await new Promise(resolve => setTimeout(resolve, 5000));
    }
}
bash
# Step 1: Start generation
REQUEST_ID=$(curl -s -X POST https://api.x.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "A cat lounging in a sunbeam, tail gently swishing",
    "duration": 5
  }' | jq -r '.request_id')

echo "Request ID: $REQUEST_ID"

# Step 2: Poll for results
while true; do
  RESULT=$(curl -s https://api.x.ai/v1/videos/$REQUEST_ID \
    -H "Authorization: Bearer $XAI_API_KEY")
  STATUS=$(echo "$RESULT" | jq -r '.status')
  if [ "$STATUS" = "done" ]; then
    echo "$RESULT" | jq -r '.video.url'
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "Request $STATUS"; echo "$RESULT" | jq .
    break
  fi
  echo "Still processing..."
  sleep 5
done

可用的状态值如下:

Proto 值描述
deferred_pb2.DeferredStatus.PENDING视频仍在生成中
deferred_pb2.DeferredStatus.DONE视频已准备就绪
deferred_pb2.DeferredStatus.EXPIRED请求已过期
deferred_pb2.DeferredStatus.FAILED视频生成失败

错误处理

使用 SDK 的 generate()extend() 方法时,视频生成失败会引发 VideoGenerationError 异常。此异常包含描述问题的 codemessage。从 xai_sdk.video 导入它:

python
import os
import xai_sdk
from xai_sdk.video import VideoGenerationError

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

try:
    response = client.video.generate(
        prompt="A cat lounging in a sunbeam, tail gently swishing",
        model="grok-imagine-video-1.5",
        duration=5,
    )
    print(response.url)
except VideoGenerationError as e:
    print(f"Error code: {e.code}")
    print(f"Error message: {e.message}")

VideoGenerationError 异常具有以下属性:

属性类型描述
codestr标识失败原因的错误代码
messagestr描述失败的可读消息

手动轮询时,失败的生成返回 status: "failed" 和一个 error 对象:

json
{
  "status": "failed",
  "error": {
    "code": "invalid_argument",
    "message": "Prompt cannot be empty. Please provide a prompt."
  }
}

可能的 error.code 值如下:

代码含义如何处理
invalid_argument请求输入无效,例如不支持的时长、无效的图像或视频输入、过长的提示、冲突的请求模式或被内容审核阻止的内容。修复请求参数或输入媒体,然后提交新请求。
permission_deniedAPI 密钥或团队没有请求的视频操作权限。确认 API 密钥属于正确的团队,并且该团队对请求的功能有访问权限。
failed_precondition请求的操作对所选模型或设置不可用,例如视频编辑、视频扩展或模型无法处理的请求分辨率。更改模型、模式、分辨率或其他请求设置。
service_unavailable视频生成暂时过载。稍后重试请求。
internal_error服务因内部故障无法完成生成。重试请求。如果错误持续存在,请使用 request_id 联系 xAI 支持。

身份验证错误、缺失的模型和速率限制在创建视频作业之前作为标准 API 错误同步返回,因此它们不会出现在失败视频结果的 error.code 字段中。

您可以将其与 TimeoutError 处理结合使用,以实现全面的错误覆盖:

python
import os
import xai_sdk
from xai_sdk.video import VideoGenerationError

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

try:
    response = client.video.generate(
        prompt="A cat lounging in a sunbeam, tail gently swishing",
        model="grok-imagine-video-1.5",
        duration=5,
    )
    print(response.url)
except VideoGenerationError as e:
    print(f"Generation failed [{e.code}]: {e.message}")
except TimeoutError:
    print("Generation timed out — try increasing the timeout or simplifying the prompt")

响应详情

SDK 响应包含生成的视频和提供商特定的元数据。在 AI SDK 中,xAI 托管的输出 URL 在 providerMetadata.xai.videoUrl 中可用。

python
if response.respect_moderation:
    print(response.url)
else:
    print("Video filtered by moderation")

print(f"Duration: {response.duration} seconds")
print(f"Model: {response.model}")
javascript
const result = await generateVideo({
    model: xai.video("grok-imagine-video-1.5"),
    prompt: "A futuristic city skyline at dusk",
    duration: 5,
});

console.log(result.providerMetadata?.xai?.videoUrl);

并发请求

当您需要生成多个视频时,并发运行请求。这对于比较提示或创建多个变体特别有用。

python
import os
import asyncio
import xai_sdk

async def generate_concurrently():
    client = xai_sdk.AsyncClient(api_key=os.getenv("XAI_API_KEY"))

    prompts = [
        "A cat sitting on a sunlit windowsill, tail gently swishing.",
        "A dog sprinting through a field of tall grass at golden hour.",
        "A hummingbird hovering near a red flower in slow motion.",
    ]

    tasks = [
        client.video.generate(
            prompt=prompt,
            model="grok-imagine-video-1.5",
            duration=5,
        )
        for prompt in prompts
    ]

    results = await asyncio.gather(*tasks)

    for prompt, result in zip(prompts, results):
        print(f"{prompt}: {result.url}")

asyncio.run(generate_concurrently())

相关

本文档为 docs.x.ai 全站中文翻译,由 AI 自动翻译生成。代码示例请以原文为准。