Skip to content
Dashboard

Flux 3

FLUX 3 is a new multimodal foundation model that learns from images, videos, and audio within a unified architecture. Your use is subject to Black Forest Labs's Terms & Privacy Policies.

Video Gentext-to-videoimage-to-videovideo-editing
import { experimental_generateVideo as generateVideo } from 'ai';
const result = await generateVideo({
model: 'bfl/flux-3-video',
prompt: 'A serene mountain lake at sunrise.'
});
Read docs

Getting started

Generate videos with Flux 3 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: 'bfl/flux-3-video',
prompt: 'A white kitten chases a butterfly across a sunlit garden.',
});
// 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

Load the supported top-level parameters: prompt, duration, aspectRatio, and resolution. The {width}x{height} resolution is mapped onto the hd/fhd tier by its shorter side.

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: 'bfl/flux-3-video',
prompt: 'A white kitten chases a butterfly across a sunlit garden.',
duration: 8,
aspectRatio: '16:9',
resolution: '1920x1080',
poll: {
intervalMs: 2000,
timeoutMs: 600000,
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);
ParameterTypeRequiredDescription
promptstringNoText description of the video to generate.
durationnumberNoVideo length in seconds. 5-20 seconds.
aspectRatiostringNoAspect ratio ('21:9', '2:1', '16:9', '4:3', '1:1', '3:4', '9:16').
prompt.imagestringNoURL or base64 image to open the clip with, switching the call to image-to-video. Equivalent to a frameImages entry with frameType: "first_frame".
resolutionstringNoOutput size as {width}x{height}, mapped onto the hd or fhd tier by its shorter side. Set providerOptions.blackForestLabs.resolution to pick the tier directly.
frameImagesArray<{ image: string; frameType: 'first_frame' | 'last_frame' }>NoImages that open and close the clip. A last_frame without a first_frame is dropped with a warning.
inputReferencesArray<{ data: string; mediaType: string }>NoA single MP4 to continue from, as { data, mediaType: "video/mp4" }. FLUX 3 has no reference-image input, so an image here is ignored with a warning.
poll{ intervalMs?: number; timeoutMs?: number }NoPolling for the asynchronous job. Defaults to a 2000 ms interval and a 600000 ms (10 minute) timeout. FLUX 3 has no poll provider options.
generateAudiobooleanNoAudio is generated by default, so this only has to be set to turn it off.

Input limits

InputFormatsSourcesMax countMax sizeLimits
Imageurl, base6410
Videomp4url, base641

Provider options

Pass FLUX 3 options under providerOptions.blackForestLabs. The tier and ratio set here take precedence over their top-level equivalents, and auto is only available on the provider option.

Learn more in the AI SDK Black Forest Labs video docs.

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: 'bfl/flux-3-video',
prompt: 'A white kitten chases a butterfly across a sunlit garden.',
duration: 8,
providerOptions: {
blackForestLabs: {
resolution: 'fhd',
aspectRatio: 'auto',
safetyTolerance: 2,
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Pass FLUX 3 options under providerOptions.blackForestLabs in your generateVideo call. The chef slug is bfl, but the provider reads its options from blackForestLabs.

ParameterTypeRequiredDescription
resolution'hd' | 'fhd'NoOutput resolution tier. Defaults to hd; fhd is finished by the video upsampler. Takes precedence over the top-level resolution.
aspectRatio'21:9' | '2:1' | '16:9' | '4:3' | '1:1' | '3:4' | '9:16' | 'auto'NoAspect ratio of the generated video. Takes precedence over the top-level aspectRatio, and unlike it can be set to auto (the API default), which infers the ratio from the prompt and any conditioning media.
keyframesArray<string | [number, string]>NoOne to ten images pinning the clip, as URLs or base64 strings, or as [seconds, image] pairs in chronological order. One opens the clip, two open and close it, and extras are spaced evenly between; three or more untimed images require an explicit duration. Takes precedence over prompt.image and frameImages.
safetyTolerancenumberNoModeration strictness from 0 (strictest) to 4. Defaults to 2. Sexual content is capped at 3 and hate content at 2 regardless of the request, and any request carrying conditioning media is capped at 2.
draftbooleanNoRender a fast, lower-quality preview instead of the finished video. Defaults to false.
draftCachestringNoEncrypted draft-cache bundle from a prior draft generation, which switches the request to draft-enhance mode. Either the base64-encoded .bin or its download URL while the link is still valid.
version'latest'NoModel version to pin. Only latest is available today.

First and last frame

Open on one image and close on another with frameImages. A first_frame on its own animates a starting image; a last_frame without one is dropped with a warning.

first-last-frame.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'bfl/flux-3-video',
prompt: 'The kitten crosses the garden and settles under the bench.',
duration: 8,
frameImages: [
{ image: 'https://example.com/start.jpg', frameType: 'first_frame' },
{ image: 'https://example.com/end.jpg', frameType: 'last_frame' },
],
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Timed keyframes

Pin images to specific seconds with [seconds, image] pairs in chronological order. Untimed images work too — one opens the clip, two open and close it — but three or more untimed keyframes require an explicit duration.

keyframes.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'bfl/flux-3-video',
prompt: 'The cat, then the dog, then the owl each take a turn in the room.',
duration: 12,
providerOptions: {
blackForestLabs: {
keyframes: [
[0, 'https://example.com/cat.png'],
[4.5, 'https://example.com/dog.png'],
[9, 'https://example.com/owl.png'],
],
},
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Video continuation

Continue from the final frames of an existing MP4 by passing it in inputReferences with an explicit media type. FLUX 3 accepts a single video, and continuation cannot be combined with keyframes.

video-continuation.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const result = await generateVideo({
model: 'bfl/flux-3-video',
prompt: 'The camera keeps pushing forward as the fog lifts.',
duration: 8,
inputReferences: [
{ data: 'https://example.com/clip.mp4', mediaType: 'video/mp4' },
],
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);

Draft, then enhance

Preview with draft: true, then replay the same generation at full quality by passing the returned bundle back as draftCache. The bundle pins the original mode, prompt, seed, and media, so an enhance call takes an empty prompt and no other options besides safetyTolerance. Both calls are billed.

draft-enhance.ts
import { experimental_generateVideo as generateVideo } from 'ai';
import fs from 'node:fs';
import 'dotenv/config';
async function main() {
const draft = await generateVideo({
model: 'bfl/flux-3-video',
prompt: 'A white kitten chases a butterfly across a sunlit garden.',
duration: 6,
providerOptions: {
blackForestLabs: { draft: true },
},
});
const draftCacheUrl = (
draft.providerMetadata.blackForestLabs?.videos as
| Array<{ draftCache?: string }>
| undefined
)?.[0]?.draftCache;
// The download URL expires, so send the base64 `.bin` for anything but an
// immediate follow-up.
const response = await fetch(draftCacheUrl!);
const draftCache = Buffer.from(await response.arrayBuffer()).toString('base64');
const result = await generateVideo({
model: 'bfl/flux-3-video',
prompt: '',
providerOptions: {
blackForestLabs: { draftCache },
},
});
// Save the generated video
fs.writeFileSync('output.mp4', result.videos[0].uint8Array);
console.log('Video saved to output.mp4');
}
main().catch(console.error);