Skip to content
Dashboard

Kling v3.0 Image-to-Video

Kling v3.0 Image-to-Video is a v3.0-generation Kling image-to-video model with first/last frame control, physics-aware motion, native audio, and up to 1080p output at durations up to 15 seconds. Your use is subject to Kling AI's Terms & Privacy Policies.

image-to-videomulti-shotaudio-generation
import { experimental_generateVideo as generateVideo } from 'ai';
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: 'A serene mountain lake at sunrise.'
});
Read docs

Getting started

Generate videos with Kling v3.0 Image-to-Video using the experimental_generateVideo function from AI SDK 6 or later. AI Gateway handles routing and polls until the video is ready.

Install the AI SDK (pnpm add ai dotenv), create an API key from the API Keys page, and set it as AI_GATEWAY_API_KEY in your environment. Full setup is covered in the video generation quickstart.

index.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/cat.png',
text: 'The cat slowly turns its head and blinks',
},
providerOptions: {
klingai: {
mode: 'std',
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Top-level parameters

Exercise the supported top-level parameters: prompt.image, prompt.text, and duration.

top-level-params.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/cat.png',
text: 'The cat slowly turns its head and blinks',
},
duration: 5,
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);
ParameterTypeRequiredDescription
prompt.imagestringYesURL of the image to animate.
prompt.textstringNoDescription of the motion or animation. Max 2500 characters.
durationnumberNoVideo length in seconds. 3-15 seconds.
resolutionstringNoResolution ('1280x720', '1920x1080', '3840x2160').
aspectRatiostringNoAspect ratio ('16:9', '9:16', '1:1').
generateAudiobooleanNoGenerate synchronized audio with the video.
frameImagesArray<{ image: string | Buffer; frameType: 'first_frame' | 'last_frame' }>NoFirst and last frames of the clip. A first_frame entry replaces prompt.image and wins when both are set, and adding a last_frame interpolates between the two. Video is not accepted and is ignored with a warning.
inputReferencesArray<string | Buffer>NoReference images that the model combines into a new scene, which switches the call to reference-to-video. Images only — a video reference is ignored with a warning. Cannot be combined with prompt.image, frameImages, or imageTail.

Input limits

InputFormatsSourcesMax countMax sizeLimits
TextUp to 2500 characters
Imagejpg, jpeg, pngurl, base64, buffer310 MB≥300px · aspect 2:5–5:2

Provider options

Load the always-compatible KlingAI options under providerOptions.klingai. The mutually exclusive feature controls — first/last frame (frameImages), reference-to-video (inputReferences), motion brush (dynamicMasks / staticMask), cameraControl, and voice/multi-shot — are shown in their own examples below.

provider-options.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/cat.png',
text: 'The cat slowly turns its head and blinks',
},
duration: 5,
generateAudio: true,
providerOptions: {
klingai: {
mode: 'pro',
negativePrompt: 'blurry, low quality',
cfgScale: 0.5,
watermarkEnabled: true,
pollIntervalMs: 5000,
pollTimeoutMs: 600000,
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Pass KlingAI-specific options under providerOptions.klingai in your generateVideo call.

ParameterTypeRequiredDescription
mode'std' | 'pro'No'std' for standard quality. 'pro' for professional quality. Defaults to 'std'.
negativePromptstringNoWhat to avoid in the video. Max 2500 characters.
cfgScalenumberNoPrompt adherence (0-1). Higher = stricter. Defaults to 0.5. Not supported on v2.x.
voiceListarrayNoVoice IDs for speech. Max 2 voices. Requires generateAudio: true. Cannot coexist with elementList.
multiShotbooleanNoEnable multi-shot generation. Requires v3.0+.
shotType'customize' | 'intelligence'NoStoryboard method, required when multiShot is true. 'customize' takes the shots from multiPrompt; 'intelligence' lets the model segment the main prompt. Requires v3.0+.
multiPromptArray<{ index: number; prompt: string; duration: string }>NoPer-shot details, required when multiShot is true and shotType is 'customize'. Up to 6 shots, each prompt max 512 characters, and the shot durations must sum to the total duration. Requires v3.0+.
elementListarrayNoReference elements for element control. Up to 3 elements. Requires v3.0+. Cannot coexist with voiceList.
imageTailstring | BufferNoThe last frame (ending image). Same format requirements as prompt.image. Legacy alternative to the top-level frameImages, used only when frameImages is omitted.
cameraControl.typestringNoCamera movement type: 'simple', 'down_back', 'forward_up', 'right_turn_forward', or 'left_turn_forward'.
cameraControl.configobjectNoMovement configuration. Required when type is 'simple'. Set one of horizontal, vertical, pan, tilt, roll, or zoom in range [-10, 10] and leave the others at 0.
staticMaskstringNoMask image for areas that should remain static.
dynamicMasksarrayNoArray of dynamic mask configurations (up to 6). Each has mask (image for areas that should move) and trajectories (motion path coordinates, 2-77 points for a 5s video).
watermarkEnabledbooleanNoGenerate a watermarked result alongside the video.
pollIntervalMsnumberNoHow often to check task status. Defaults to 5000.
pollTimeoutMsnumberNoMaximum wait time. Defaults to 600000 (10 minutes).

Base64 image encoding

When passing an image as base64 (for example prompt.image), submit only the raw base64 string. Do not include a data:image/png;base64, prefix.

Mutually exclusive features

First/last frame (frameImages), reference-to-video (inputReferences), motion brush (dynamicMasks / staticMask), and camera control (cameraControl) cannot be combined. Use only one of these per request.

The top-level parameters win over their provider-option equivalents: a first_frame in frameImages overrides prompt.image, and a last_frame overrides providerOptions.klingai.imageTail.

Passing inputReferences switches the model to reference-to-video, which ignores prompt.image, frameImages, and imageTail.

voiceList cannot coexist with elementList.

Audio and voice

Set generateAudio: true to enable audio.

Reference voices in your prompt with the <<<voice_1>>> syntax, where the number matches the order of entries in voiceList. You can use up to 2 voices per video, and voice generation requires generateAudio: true.

Multi-shot generation

Multi-shot generation requires v3.0+. Set multiShot: true with shotType: 'customize' and a multiPrompt array, where each entry has an index (shot order, starting from 1), a prompt, and a duration (in seconds, as a string).

When using multiPrompt, the top-level prompt is typically left empty because each shot supplies its own prompt.

First and last frame

Generate a video that transitions between a starting and ending image, interpolating the motion between the two. Pass both frames through the top-level frameImages, tagging one first_frame and one last_frame. Mutually exclusive with motion brush and camera control.

first-last-frame.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const firstFrame = fs.readFileSync('start.png');
const lastFrame = fs.readFileSync('end.png');
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: 'Smooth transition between the two scenes',
frameImages: [
{ image: firstFrame, frameType: 'first_frame' },
{ image: lastFrame, frameType: 'last_frame' },
],
providerOptions: {
klingai: {
mode: 'pro',
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Reference to video

Combine reference images into a brand-new scene described by your prompt. Passing inputReferences selects reference-to-video, so leave out prompt.image, frameImages, and imageTail — the references guide what the characters look like rather than becoming the video content.

reference-to-video.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
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',
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Camera control

Control camera movement during generation. Use a preset movement type or 'simple' with a config that sets one axis (others stay at 0).

camera-control.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/landscape.png',
text: 'A serene mountain landscape',
},
providerOptions: {
klingai: {
mode: 'std',
cameraControl: {
type: 'simple',
config: {
zoom: 5,
horizontal: 0,
vertical: 0,
pan: 0,
tilt: 0,
roll: 0,
},
},
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Motion brush

Control which parts of the image move and how using mask images. Mutually exclusive with first/last frame and camera control.

motion-brush.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/scene.png',
text: 'A ball bouncing across the scene',
},
providerOptions: {
klingai: {
mode: 'std',
dynamicMasks: [
{
mask: 'https://example.com/ball-mask.png',
trajectories: [
{ x: 100, y: 200 },
{ x: 200, y: 300 },
{ x: 300, y: 200 },
{ x: 400, y: 300 },
],
},
],
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Voice generation

Add speech using voice IDs. Requires generateAudio: true. Reference voices in the prompt with the <<<voice_1>>> syntax.

voice-generation.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/person.png',
text: 'The person<<<voice_1>>> says: "Hello, welcome to my channel"',
},
generateAudio: true,
providerOptions: {
klingai: {
mode: 'std',
voiceList: [{ voiceId: 'your_voice_id' }],
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Multi-shot generation

Generate videos with multiple storyboard shots, combining a start frame image with per-shot prompts. Requires Kling v3.0+ models.

multi-shot-i2v.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'klingai/kling-v3.0-i2v',
prompt: {
image: 'https://example.com/start-frame.png',
text: '',
},
aspectRatio: '16:9',
duration: 10,
generateAudio: true,
providerOptions: {
klingai: {
mode: 'pro',
multiShot: true,
shotType: 'customize',
multiPrompt: [
{
index: 1,
prompt: 'The character looks up at the sky.',
duration: '4',
},
{
index: 2,
prompt: 'A bird flies across the frame.',
duration: '3',
},
{
index: 3,
prompt: 'The character smiles and waves.',
duration: '3',
},
],
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);