AI Gateway Video Extension
Continue an existing video from its last frame. Describe what happens next and the model generates new footage that picks up where the source video left off.
Every model here also runs as a background job instead of one long-lived request. See asynchronous generation below.
Grok Imagine Video (by SpaceXAI) can extend existing videos using text prompts. Provide a source video URL and describe the scene that continues from the last frame.
To edit an existing video instead of extending it, see Video editing.
Browse the latest Grok video models on the AI Gateway Models page.
Only spacexai/grok-imagine-video supports extension. The spacexai/grok-imagine-video-1.5 and spacexai/grok-imagine-video-1.5-preview models support image-to-video only.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Prompt describing what should happen next in the video |
duration | number | No | Length of the extension segment only, not total output (1 to 10 seconds). Defaults to 6 |
providerOptions.spacexai.mode | 'extend-video' | Yes | Routes the request to video extension instead of editing |
providerOptions.spacexai.videoUrl | string | Yes | URL of the source video to extend |
providerOptions.spacexai.pollIntervalMs | number | No | How often to check task status. Defaults to 5000 |
providerOptions.spacexai.pollTimeoutMs | number | No | Maximum wait time. Defaults to 600000 (10 minutes) |
Generate a source video, then extend it using the ephemeral URL from provider metadata:
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
// Step 1: Generate source video
const source = await generateVideo({
model: 'spacexai/grok-imagine-video',
prompt: 'A cat sitting on a sunlit windowsill, tail gently swishing.',
duration: 5,
aspectRatio: '16:9',
providerOptions: {
spacexai: { pollTimeoutMs: 600000 },
},
});
const sourceUrl = source.providerMetadata?.spacexai?.videoUrl as string;
// Step 2: Extend from last frame
const extended = await generateVideo({
model: 'spacexai/grok-imagine-video',
prompt: 'The cat turns its head, notices a butterfly, and leaps off.',
duration: 6,
providerOptions: {
spacexai: {
mode: 'extend-video',
videoUrl: sourceUrl,
pollTimeoutMs: 600000,
},
},
});
fs.writeFileSync('extended.mp4', extended.videos[0].uint8Array);Extend from a fixed source URL:
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'spacexai/grok-imagine-video',
prompt:
'The cat continues walking slowly through the dandelions as the breeze picks up.',
duration: 5,
providerOptions: {
spacexai: {
mode: 'extend-video',
videoUrl: 'https://example.com/source-video.mp4',
pollTimeoutMs: 600000,
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);Pass a webhook factory and the SDK registers your URL with the job instead of polling for it. The factory returns that URL and a received promise it waits on, then it fetches the videos itself.
const result = await generateVideo({
model: gateway.videoModel('spacexai/grok-imagine-video'),
prompt: 'The cat turns its head, notices a butterfly, and leaps off.',
duration: 6,
providerOptions: {
spacexai: {
mode: 'extend-video',
// Already a hosted URL, which is what the asynchronous flow needs.
videoUrl: 'https://example.com/source-video.mp4',
},
},
webhook: async () => ({
url: callbackUrl,
received: waitForDelivery(token),
}),
poll: { timeoutMs: 10 * 60 * 1000 },
});The start request AI Gateway persists is capped at 300 KiB, so pass your source video as a hosted URL on this flow rather than inline data.
token, callbackUrl, and waitForDelivery come from webhook-driven completion, which also covers the receiver, signature verification, and the payload shape.
Was this helpful?