Model Capabilities

Video Generation

Generate videos from text prompts, animate still images, or edit existing videos with natural language. The API supports configurable duration, aspect ratio, and resolution for generated videos — with the SDK handling the asynchronous polling automatically.


Quick Start

Generate a video with a single API call:

import xai_sdk

client = xai_sdk.Client()

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",
    duration=10,
    aspect_ratio="16:9",
    resolution="720p",
)

print(response.url)

Video generation is an asynchronous process that typically takes up to several minutes to complete. The exact time varies based on:

  • Prompt complexity — More detailed scenes require additional processing
  • Duration — Longer videos take more time to generate
  • Resolution — Higher resolutions (720p vs 480p) increase processing time
  • Video editing — Editing existing videos adds overhead compared to image-to-video or text-to-video

How it works

Under the hood, video generation is a two-step process:

  1. Start — Submit a generation request and receive a request_id
  2. Poll — Repeatedly check the status using the request_id until the video is ready

The xAI SDK's generate() method abstracts this entirely — it submits your request, polls for the result, and returns the completed video response. You don't need to manage request IDs or implement polling logic. For long-running generations, you can customize the polling behavior with timeout and interval parameters, or handle polling manually for full control over the generation lifecycle.

REST API users must implement this two-step flow manually:

Step 1: Start the generation request

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",
    "prompt": "A glowing crystal-powered rocket launching from Mars"
  }'

Response:

JSON

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

Step 2: Poll for the result

Use the request_id to check the status. Keep polling every few seconds until the video is ready:

Bash

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

The response includes a status field with one of these values:

StatusDescription
pendingVideo is still being generated
doneVideo is ready
expiredRequest has expired

Response (when complete):

JSON

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

Videos are returned as temporary URLs — download or process them promptly.


Generate Videos from Images

Transform a still image into a video by providing a source image along with your prompt. The model animates the image content based on your instructions.

import base64
import xai_sdk

client = xai_sdk.Client()

# Load image from file and encode as base64
with open("landscape.jpg", "rb") as f:
    image_data = base64.b64encode(f.read()).decode("utf-8")

response = client.video.generate(
    prompt="Animate the clouds drifting across the sky and add gentle swaying to the trees",
    model="grok-imagine-video",
    image_url=f"data:image/jpeg;base64,{image_data}",
)

print(response.url)

You can provide the source image as:

  • A public URL pointing to an image
  • A base64-encoded data URI (e.g., data:image/jpeg;base64,...)

The demo below shows this in action — hold to animate a still image:

Time-lapse
Loading video…
Hold to animate
Playing
import xai_sdkclient = xai_sdk.Client()response = client.video.generate(    prompt="Generate a slow and serene time-lapse",    model="grok-imagine-video",    image_url="https://docs.x.ai/assets/api-examples/video/milkyway-still.png",    duration=12,)print(response.url)

Edit Existing Videos

Edit an existing video by providing a source video along with your prompt. The model understands the video content and applies your requested changes.

  • The maximum length of the input video provided via the video_url parameter is 8.7 seconds.
  • The duration, aspect_ratio, and resolution parameters are not supported for video editing — the output retains the duration and aspect ratio of the input, and matches its resolution (capped at 720p).

The demo below shows video editing in action — grok-imagine-video delivers high-fidelity edits with strong scene preservation, modifying only what you ask for while keeping the rest of the video intact:

Video preview
Press play
import xai_sdkclient = xai_sdk.Client()response = client.video.generate(    prompt="Give the woman a silver necklace",    model="grok-imagine-video",    video_url="https://data.x.ai/docs/video-generation/portrait-wave.mp4",)print(response.url)

Concurrent Requests

When you need to generate multiple videos or apply several edits to the same source video, use AsyncClient with asyncio.gather to fire requests concurrently. Since video generation and editing are long-running processes, running requests in parallel is significantly faster than issuing them sequentially.

The example below applies all three edits from the interactive demo above — adding a necklace, changing the outfit color, and adding a hat — concurrently:

Python

import asyncio
import xai_sdk

async def edit_concurrently():
    client = xai_sdk.AsyncClient()

    source_video = "https://example.com/balcony-scene.mp4"

    # Each request applies a different edit to the same video
    prompts = [
        "Give the woman a silver necklace",
        "Change the color of the woman's outfit to red",
        "Give the woman a wide-brimmed black hat",
    ]

    # Fire all edit requests concurrently
    tasks = [
        client.video.generate(
            prompt=prompt,
            model="grok-imagine-video",
            video_url=source_video,
        )
        for prompt in prompts
    ]

    results = await asyncio.gather(*tasks)

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

asyncio.run(edit_concurrently())

Configuration

The video generation API lets you control the output format of your generated videos. You can specify the duration, aspect ratio, and resolution to match your specific use case.

Duration

Control video length with the duration parameter. The allowed range is 1–15 seconds.

Video editing does not support custom duration. The edited video retains the duration of the original, which is capped at 8.7 seconds.

Aspect Ratio

RatioUse case
1:1Social media, thumbnails
16:9 / 9:16Widescreen, mobile, stories (default: 16:9)
4:3 / 3:4Presentations, portraits
3:2 / 2:3Photography

For image-to-video generation, the output defaults to the input image's aspect ratio. If you specify the aspect_ratio parameter, it will override this and stretch the image to the desired aspect ratio.

Video editing does not support custom aspect_ratio — the output matches the input video's aspect ratio.

Resolution

ResolutionDescription
720pHD quality
480pStandard definition, faster processing (default)

Video editing does not support custom resolution. The output resolution matches the input video's resolution, capped at 720p (e.g., a 1080p input will be downsized to 720p).

Example

import xai_sdk

client = xai_sdk.Client()

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

print(f"Video URL: {response.url}")
print(f"Duration: {response.duration}s")

Customize Polling Behavior

When using the SDK's generate() method, you can control how long to wait and how frequently to check for results using the timeout and interval parameters:

ParameterDescriptionDefault
timeoutMaximum time to wait for the video to complete10 minutes
intervalTime between status checks100 milliseconds

Python

from datetime import timedelta
import xai_sdk

client = xai_sdk.Client()

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

print(response.url)

If the video isn't ready within the timeout period, a TimeoutError is raised. For even finer control, use the manual polling approach with start() and get().


Handle Polling Manually

For fine-grained control over the generation lifecycle, use start() to initiate generation and get() to check status.

The get() method returns a response with a status field. Import the status enum from the SDK:

import time
import xai_sdk
from xai_sdk.proto import deferred_pb2

client = xai_sdk.Client()

# Start the generation request
start_response = client.video.start(
    prompt="A cat lounging in a sunbeam, tail gently swishing",
    model="grok-imagine-video",
    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.PENDING:
        print("Still processing...")
        time.sleep(5)

The available status values are:

Proto ValueDescription
deferred_pb2.DeferredStatus.PENDINGVideo is still being generated
deferred_pb2.DeferredStatus.DONEVideo is ready
deferred_pb2.DeferredStatus.EXPIREDRequest has expired

Response Details

The xAI SDK exposes additional metadata on the response object beyond the video URL.

Moderation — Check whether the generated video passed content moderation:

Python

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

Duration — Get the actual duration of the generated video:

Python

print(f"Duration: {response.duration} seconds")

Model — Get the actual model used (resolving any aliases):

Python

print(f"Model: {response.model}")

Pricing

Video generation uses per-second pricing. Longer videos cost more, and both duration and resolution affect the total cost.

For full pricing details on the grok-imagine-video model, see the model page.


Limitations

  • Maximum duration: 15 seconds for generation, 8.7 seconds for editing input videos
  • URL expiration: Generated URLs are ephemeral and should not be relied upon for long-term storage
  • Resolutions: 480p or 720p
  • Content moderation: Videos are subject to content policy review