Animate a still image into video
Image-to-video takes a frame you already approve of and adds motion. Because you supply the first frame, you control composition, subject and style completely — which makes it far more predictable than text-to-video, and much cheaper to iterate on.
- Clip length
- 5 s or 8 s
- Frame rate
- 32 fps
- Typical wait
- ~3 min
For a 5 s clip on a warm worker
Generate the still first
Video is the most expensive operation on the platform and the slowest, so never let a user burn a clip on a composition they have not seen. Generate a still, let them approve it, then animate that exact frame.
This also gives you a much better product: users iterate on the cheap step and commit on the expensive one.
curl https://api.fastgencloud.com/v1/images/generations \
-H "Authorization: Bearer $FASTGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "general-image",
"prompt": "a lighthouse on a cliff at dusk, low cloud, long lens, cinematic",
"size": "1216x832"
}'Animate it
The prompt here describes motion, not content — the content is already fixed by the frame. Aspect ratio is preserved from your start frame.
curl https://api.fastgencloud.com/v1/videos/generations \
-H "Authorization: Bearer $FASTGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "image-to-video",
"image": "https://…/approved-frame.png",
"prompt": "slow push in, low cloud drifting, beam sweeping across the frame",
"duration": 5,
"webhook_url": "https://your.app/hooks/fastgen"
}'Writing motion prompts
- Camera first: "slow push in", "slow pan left", "static locked-off shot"
- Then subject motion: "hair moving in the wind", "steam rising from the cup"
- Then ambient: "drifting clouds", "rain streaks on glass", "flickering neon"
- Less is more — asking for several simultaneous large movements is the fastest way to get warping
- An empty prompt is valid and gives subtle ambient motion, which is often exactly right for backgrounds
Use a webhook, not a poll loop
A 5 second clip takes on the order of three minutes on a warm worker, and longer from cold. That is far past any serverless request timeout, so the job must be a background job in your architecture too.
Register webhook_url on submit and verify the signature on receipt. The header is X-FastGen-Signature: t=<unix>,v1=<hex>, where v1 is an HMAC-SHA256 over `${t}.${rawBody}` using your webhook secret.
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, header, rawBody) {
const parts = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));
const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest();
const given = Buffer.from(parts.v1, "hex");
if (expected.length !== given.length) return false;
// reject anything older than 5 minutes to prevent replays
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
return timingSafeEqual(expected, given);
}Cost and retention
Video bills per second of output, so an 8 second clip costs 8x the per-second rate and a 5 second clip 5x. Failed jobs refund automatically.
Output URLs live for up to 7 days. Download the file and re-host it if it is going anywhere durable — do not hand a 7-day URL to a customer.
Frequently asked questions
- Is there a text-to-video endpoint?
- No, and for most products that is the right call. Generating the still first costs a fraction of a clip and gives you complete control over composition before you commit to the expensive step.
- What resolution and frame rate do I get?
- Roughly 720p class at 32 fps, in whatever aspect ratio your start frame uses.
- Can I make clips longer than 8 seconds?
- Not in a single call — durations are 5 or 8 seconds. Generate several clips and cut them together if you need more, using the last frame of one as the start frame of the next.
- Why did my clip come back warped?
- Usually too much requested motion, or a soft start frame. Simplify the motion prompt to one camera move plus one subject movement, and animate the sharpest frame you have.
Related
Start generating
Create an account, add a prepaid balance, and call the API with a key from the console. No subscription, no minimum, no per-seat pricing.
Get an API key