AI Gateway Reference-to-Video Generation
Generate a completely new video scene featuring characters from reference media.
Every model here also runs as a background job instead of one long-lived request. See asynchronous generation below.
This is different from image-to-video, which animates an existing image. With reference-to-video, the reference images only show the model what your characters look like. They don't become the video content. Instead, your prompt describes a completely new scene, and the model generates that scene from scratch with your characters in it.
For example, you could provide photos of a cat and a dog, then prompt "character1 and character2 have a conversation in a cafe." The model creates that cafe scene from scratch, using the reference images only to understand what the characters look like.
The provider-agnostic inputReferences field is the recommended way to pass references. It accepts an array of images or videos. Each entry is a URL, a base64-encoded string, or a Buffer, or an object that pairs the data with an explicit media type:
inputReferences: [
'https://example.com/cat.png',
{ data: 'https://example.com/scene.mp4', mediaType: 'video/mp4' },
];Providers route each reference by its media type and treat untyped references as images. Use the object form with a mediaType (for example, 'video/mp4') to pass a video reference by URL, since providers can't infer the type from a bare URL. Providers that accept only image references ignore video references with a warning.
The syntax you use in the prompt to refer to each reference stays provider-specific:
| Provider | Prompt syntax | Reference types |
|---|---|---|
| Wan | character1, character2, … | Images and videos |
| Seedance 2.5 | [Image 1], [Video 1], … | Images and videos |
| Grok Imagine Video | <IMAGE_1>, <IMAGE_2>, … | Images only |
| KlingAI | None. Describe the scene directly in the prompt | Images only |
| Google Veo 3.1 | None. Describe how reference assets appear in the scene | Images only |
If you also pass frameImages, the model ignores inputReferences and emits a warning, since first and last frames take priority.
For Seedance multi-reference image generation on image-to-video models, see Seedance multi-reference images.
Veo 3.1 can incorporate reference images into a generated video. The references guide assets and style in the scene you describe in the prompt. They are not used as the first frame.
Browse the latest Veo video models on the AI Gateway Models page.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Scene description for the generated video |
inputReferences | Array<image> | No | Reference images as base64-encoded strings or Buffers that guide assets and style in the scene. HTTPS URLs are not supported |
duration | 4 | 6 | 8 | No | Video length in seconds. Defaults to 8 |
aspectRatio | string | No | Aspect ratio ('16:9', '9:16'). Defaults to '16:9' |
resolution | string | No | Resolution ('1280x720' for 720p, '1920x1080' for 1080p). Defaults to 720p |
generateAudio | boolean | No | Generate audio alongside the video |
providerOptions.vertex.referenceImages | array | No | Legacy alternative to inputReferences. Used when inputReferences is omitted |
providerOptions.vertex.enhancePrompt | boolean | No | Use Gemini to enhance prompts. Defaults to true |
providerOptions.vertex.negativePrompt | string | No | What to discourage in the generated video |
providerOptions.vertex.personGeneration | 'dont_allow' | 'allow_adult' | 'allow_all' | No | Whether to allow person generation. Defaults to 'allow_adult' |
providerOptions.vertex.pollIntervalMs | number | No | How often to check task status. Defaults to 5000 |
providerOptions.vertex.pollTimeoutMs | number | No | Maximum wait time. Defaults to 600000 (10 minutes) |
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'google/veo-3.1-generate-001',
prompt:
'The video opens with a medium shot of a woman in a high-fashion flamingo dress walking through a lagoon',
inputReferences: [
fs.readFileSync('dress.png'),
fs.readFileSync('glasses.png'),
fs.readFileSync('woman.png'),
],
duration: 8,
aspectRatio: '16:9',
generateAudio: true,
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);If you omit inputReferences, you can still pass references through the legacy providerOptions.vertex.referenceImages key.
KlingAI image-to-video models support reference-to-video when you pass inputReferences. The model combines the reference images into a new scene described by your prompt. Do not pass a separate start frame or frameImages alongside inputReferences.
Browse the latest KlingAI video models on the AI Gateway Models page.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Scene description. Max 2500 characters. |
inputReferences | Array<image> | No | Reference images. URLs, base64 strings, or buffers. Passing them selects reference-to-video behavior. |
aspectRatio | string | No | Aspect ratio ('16:9', '9:16', '1:1'). Defaults to '16:9'. |
duration | number | No | Video length in seconds. 5 or 10 for v2.x, 3-15 for v3.0. Defaults to 5. |
providerOptions.klingai.mode | 'std' | 'pro' | No | 'std' for standard quality. 'pro' for professional quality. Defaults to 'std'. |
providerOptions.klingai.negativePrompt | string | No | What to avoid in the video. Max 2500 characters. |
providerOptions.klingai.cfgScale | number | No | Prompt adherence (0-1). Higher = stricter. Defaults to 0.5. Not supported on v2.x. |
providerOptions.klingai.pollIntervalMs | number | No | How often to check task status. Defaults to 5000. |
providerOptions.klingai.pollTimeoutMs | number | No | Maximum wait time. Defaults to 600000 (10 minutes). |
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: 'The two characters meet and walk together through a sunny park',
inputReferences: [
'https://example.com/character-1.png',
'https://example.com/character-2.png',
],
aspectRatio: '16:9',
duration: 5,
providerOptions: {
klingai: {
mode: 'std',
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);Wan's reference-to-video models can incorporate multiple characters from reference media into a generated video. References must be URLs (use Vercel Blob for local files). Use character1, character2, etc. in your prompt to refer to each reference.
Browse the latest Wan video models on the AI Gateway Models page.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Scene description using character1, character2, etc. to reference each character |
inputReferences | Array<image | video> | No | Reference images or videos. The first entry maps to character1, the second to character2, and so on. Supports 0-5 images and 0-3 videos, max 5 total |
resolution | string | No | '1280x720' or '1920x1080' |
duration | number | No | 2-10 seconds |
providerOptions.alibaba.referenceUrls | string[] | No | Legacy alternative to inputReferences. Array of reference URLs, used when inputReferences is omitted |
generateAudio | boolean | No | Generate audio. Standard models default to true, flash models default to false |
providerOptions.alibaba.negativePrompt | string | No | What to avoid in the video. Max 500 characters |
providerOptions.alibaba.shotType | 'single' | 'multi' | No | 'single' for continuous shot. 'multi' for multiple camera angles |
providerOptions.alibaba.watermark | boolean | No | Add watermark to the video. Defaults to false |
providerOptions.alibaba.pollIntervalMs | number | No | How often to check task status. Defaults to 5000 |
providerOptions.alibaba.pollTimeoutMs | number | No | Maximum wait time. Defaults to 600000 (10 minutes) |
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'alibaba/wan-v2.6-r2v',
prompt: 'character1 and character2 have a friendly conversation in a cozy cafe',
resolution: '1920x1080',
duration: 4,
// References can be images or videos
inputReferences: [
'https://example.com/cat.png',
'https://example.com/dog.png',
],
providerOptions: {
alibaba: {
shotType: 'single',
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);If you omit inputReferences, you can still pass references through the legacy providerOptions.alibaba.referenceUrls key.
If you have local files, upload them to Vercel Blob first:
import { experimental_generateVideo as generateVideo } from 'ai';
import { put } from '@vercel/blob';
import fs from 'node:fs';
const catImage = fs.readFileSync('./cat.png');
const { url: catUrl } = await put('cat.png', catImage, { access: 'public' });
const dogImage = fs.readFileSync('./dog.png');
const { url: dogUrl } = await put('dog.png', dogImage, { access: 'public' });
const result = await generateVideo({
model: 'alibaba/wan-v2.6-r2v',
prompt: 'character1 and character2 play together in a sunny garden',
resolution: '1280x720',
duration: 4,
inputReferences: [catUrl, dogUrl],
providerOptions: {
alibaba: {
shotType: 'single',
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);Grok Imagine Video can generate a new scene from reference images. The references guide visual elements in the output. They are not used as the first frame. Use <IMAGE_1>, <IMAGE_2>, and so on in your prompt to refer to each reference.
To edit or extend an existing video instead, see Video editing and Video extension.
Browse the latest Grok video models on the AI Gateway Models page.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Scene description. Use <IMAGE_1>, <IMAGE_2>, etc. to refer to each reference |
inputReferences | Array<image> | No | Reference images. URLs or buffers. Passing them selects reference-to-video mode |
duration | number | No | Video length in seconds (1-15) |
aspectRatio | string | No | Aspect ratio ('16:9', '9:16', '1:1', and others) |
providerOptions.spacexai.mode | 'reference-to-video' | No | Selects reference-to-video mode explicitly. Auto-selected when inputReferences is passed |
providerOptions.spacexai.referenceImageUrls | string[] | No | Legacy alternative to inputReferences. Used when inputReferences is omitted |
providerOptions.spacexai.resolution | '480p' | '720p' | No | Video resolution. Defaults to '480p' |
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) |
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'spacexai/grok-imagine-video',
prompt:
'The comic cat from <IMAGE_1> and the comic dog from <IMAGE_2> ' +
'are having a playful chase through a sunlit park. ' +
'Cinematic slow-motion, warm afternoon light.',
inputReferences: [
'https://example.com/comic-cat.png',
'https://example.com/comic-dog.png',
],
duration: 8,
aspectRatio: '16:9',
providerOptions: {
spacexai: {
pollTimeoutMs: 600000,
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);If you omit inputReferences, you can still pass references through providerOptions.spacexai.referenceImageUrls with providerOptions.spacexai.mode: 'reference-to-video'.
Seedance 2.5 can generate a new scene from a mix of image and video references. Use [Image 1], [Image 2], and [Video 1], [Video 2], and so on in your prompt to refer to each reference, in the order you pass them.
Browse the latest Seedance video models on the AI Gateway Models page.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Scene description. Use [Image 1], [Video 1], etc. to refer to each reference |
inputReferences | Array<image | video> | No | Reference images and videos. Tag each URL reference with an explicit mediaType |
aspectRatio | string | No | Aspect ratio (e.g., '16:9', '9:16') |
duration | number | No | Video length in seconds |
generateAudio | boolean | No | Generate audio alongside the video |
providerOptions.bytedance.referenceImages | string[] | No | Legacy alternative to inputReferences for image reference URLs. Used when inputReferences is omitted |
providerOptions.bytedance.referenceVideos | string[] | No | Legacy alternative to inputReferences for video reference URLs. Used when inputReferences is omitted |
providerOptions.bytedance.pollIntervalMs | number | No | How often to check task status. Defaults to 5000 |
providerOptions.bytedance.pollTimeoutMs | number | No | Maximum wait time. Defaults to 600000 (10 minutes) |
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
const result = await generateVideo({
model: 'bytedance/seedance-2.5',
prompt:
'Replace the cat in [Video 1] with the lion from [Image 1]. The lion lies down and gently interacts with the girl in a warm and tender way.',
aspectRatio: '16:9',
duration: 12,
inputReferences: [
{ data: 'https://example.com/lion.jpg', mediaType: 'image/jpeg' },
{ data: 'https://example.com/cat-video.mp4', mediaType: 'video/mp4' },
],
generateAudio: true,
providerOptions: {
bytedance: {
pollTimeoutMs: 600000,
},
},
});
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);If you omit inputReferences, you can still pass references through the legacy providerOptions.bytedance.referenceImages and providerOptions.bytedance.referenceVideos keys.
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('alibaba/wan-v2.6-r2v'),
prompt: 'character1 and character2 have a friendly conversation in a cozy cafe',
duration: 4,
// Hosted URLs, not inline bytes: the start request is capped at 300 KiB.
inputReferences: [
'https://example.com/cat.png',
'https://example.com/dog.png',
],
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 references 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?