Back to blog
Video18 min read

First-Frame and Last-Frame Control in AI Video

First-frame and last-frame control, verified per vendor: three different field shapes, what pinning both ends costs, and 27 copy-paste prompts for chaining clips into one sequence.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: First-frame and last-frame control means supplying the still that opens a clip, the still that closes it, or both, so the model fills only the motion between two fixed points. Every vendor implements it with a different field shape. Below: the exact mechanism per vendor, what pinning both ends costs, and how to chain clips into one sequence.

Before anything else: Prompt Architects writes the prompt. It generates neither the image nor the video. Everything below is text and field names you paste into whichever model actually renders.

What Is First-Frame and Last-Frame Control, Exactly?

A request parameter, not a prompt technique.

You supply an image for the frame that opens the clip, an image for the frame that closes it, or both, and the model is asked to fill in only what happens between them. That is narrower and more reliable than describing a shot in words, because the two endpoints are pixels the model has to match rather than a description it has to interpret. It is the closest thing any of these vendors publish to a hard constraint on a generation.

It is easy to confuse with two things this site already covers in depth. Video transition prompts is about what happens at a cut or inside one shot, camera moves, named edits, and the one vendor that documents multi-shot syntax. Image to video prompts is about writing the text that accompanies a single still. This page sits underneath both: the mechanics of the pinning parameter itself, across every vendor that documents it, and the habit of using it across more than one clip instead of one.

What Does Each Vendor Actually Call It?

Eleven vendor surfaces, three underlying shapes. Copy the shape, not the field name, or you send a well-formed request to the wrong vendor and get a 400 you cannot read.

Runway's own /v1/image_to_video endpoint is the cleanest place to see the split, because one endpoint serves thirteen models and publishes a separate request schema for each. Runway states it outright: "Request body: one of 13 shapes, selected by model. Only the fields listed under a given model are valid." (docs.dev.runwayml.com/api.md, accessed 2 September 2026.) Five branches take a first frame only. Eight take first and last.

Runway branch (model value)First frameLast frame
gen4.5YesNo
gen4_turboYesNo
happyhorse_1_0YesNo
gemini_omni_flashYesNo
grok_imagine_1_5YesNo
veo3.1YesYes
veo3.1_fastYesYes
hailuo3YesYes
seedance2YesYes
seedance2_fastYesYes
seedance2_miniYesYes
seedance2_5YesYes
wan3YesYes

Same vendor, same endpoint, same position field. The enum belongs to the model, not to Runway.

Off Runway's own endpoint, at each vendor's native API, the same idea splits into three genuinely different shapes.

A named pair. Two separate keys, one per end. Google's Gemini API passes the first frame as image and the last as lastFrame, inside config. Lightricks' LTX-2.5 uses image_uri and last_frame_uri. Luma's Ray 3.2 uses start_frame and end_frame, each accepting the same ImageRef shape as a reference image on an image request.

A tagged item inside one array. A single list of inputs, and each entry carries a type or role that says which end it belongs to. Kling's 3.0 Omni spec sets contents[].type to an enum including first_frame and last_frame. Alibaba's Wan 2.7 does the same with media[].type. BytePlus documents a role field on Seedance images, set to first_frame or last_frame (docs.byteplus.com/en/docs/ModelArk/1520757, accessed 2 September 2026). Runway's own position field, on the eight branches above, is this same shape.

A plain array where order carries the meaning. No field name at all. Vidu Q3's start-end2video endpoint takes an images array and documents it as "Two images: first is start frame, second is end frame." (platform.vidu.com/docs/start-end-to-video.md.) Pika 2.5's Pikaframes spec is the same idea generalised: images takes "2-5 ordered keyframe image URLs. Consecutive pairs become transitions." (dev.pika.art/llms/pika/pikaframes/image-to-video.)

Two vendors sit outside this table entirely. Sora 2 does not document a last-frame input of any kind. xAI's Grok Imagine documents image as a first frame for generation, and a separate extension endpoint that continues a clip "from its last frame" automatically, meaning the model's own output, not one you choose. That is a materially different feature from anything above: it is not conditioning, it is continuation, and no supplied still is involved.

Frame-conditioning mechanics across four shapes, verified at each vendor's own documentation, 2 September 2026.
FeatureSeedance 2.5Kling 3.0 OmniLuma Ray 3.2Vidu Q3
Field shapeTagged item, `role`Tagged item, `contents[].type`Named pair, `start_frame`/`end_frame`Positional array, `images[0]`/`images[1]`
Last frame aloneNot documentedDocumented as not supported yetYes, either alone is validNo, the endpoint requires two
Returns the last frame for youYes, `return_last_frame`NoNoNo
Cost of pinning both endsNot documentedNot documentedDrops the clip to 5sRequires matched aspect ratio

Pin what you have (copy-paste)

# 1 — Runway Gen-4.5 — first frame only
(API: promptImage position "first". This branch has no last-frame field.)
A single continuous take, static camera. A locksmith bends over a workbench
under a warm desk lamp, sorting brass keys by size into a wooden tray. Hands
move steadily; nothing else in frame moves.
# 2 — Grok Imagine 1.5 — first frame only
(API: image.file_id, no last-frame input documented.)
Pan slowly across a greenhouse aisle at golden hour, tomato vines heavy with
fruit on both sides, dust motes visible in the low side light.
# 3 — Sora 2 — first frame only
(API: input_reference. No last-frame field is documented for Sora 2.)
The camera holds on a rooftop garden at dusk, string lights just switching on
one by one along the fence line, city haze softening the skyline behind.
# 4 — Veo 3.1 (Gemini API) — first and last frame
(API: image = the opening still, config.lastFrame = the closing still.)
The lamp on the workbench dims to nothing as the last key drops into the
tray. Hold the same framing and the same warm color temperature throughout.
# 5 — Veo 3.1, via Runway's endpoint — same model, different shape
(API: promptImage as an array of two objects, position "first" and "last".
Same operation as #4, incompatible request shape.)
Continue the greenhouse pan into a still frame: the aisle now empty, the low
side light unchanged, dust settled.
# 6 — Kling 3.0 Omni — first and last frame
(API: contents[] with two entries, type "first_frame" and type "last_frame".)
The rooftop string lights finish switching on one by one, ending on a wide,
static, fully lit shot with no figure in frame and no camera movement.
# 7 — Kling 3.0 Omni — multi-shot, combined with a pinned last frame
(API: settings.multi_shot true, plus contents[] carrying the last_frame
entry. Shot syntax controls the middle; the last_frame entry still fixes
the end.)
shot 1, 3, A wide shot of a locksmith's shop window at dusk, sign light
just switching on;
shot 2, 2, A close shot of the sign steadying to a constant glow, no
flicker remaining.
# 8 — Seedance 2.5 (BytePlus) — first and last frame
(API: two images, role "first_frame" and role "last_frame".)
A single espresso shot begins pulling into a white cup on a steel counter,
warm tungsten light from frame left. End on the cup full, crema settled,
the portafilter still locked in, hands withdrawn from frame.
# 9 — Wan 2.7 (Alibaba) — first and last frame
(API: media[] with type "first_frame" and type "last_frame".)
A paper boat drifts down a rain gutter in an alley, grey daylight, handheld
micro-shake. End on the boat lodged against a drain grate, still upright.
# 10 — Hailuo 3, via Runway's endpoint — first and last frame
(API: promptImage array, position "first" and "last". A fourth vendor
reachable through the same shape as #5 and #9.)
A tide pool fills slowly as the water rises over bare rock, late afternoon
light. End on the pool full and still, sky reflected on the surface.
# 11 — LTX-2.5 — first and last frame
(API: image_uri = opening still, last_frame_uri = closing still. Supplying
last_frame_uri blocks the automatic-duration mode; pass an explicit duration.)
A single seed on damp soil pushes up a pale green shoot over the shot. End
on the shoot upright, two small leaves unfurled, dew visible on the leaves.
# 12 — LTX-2.5 — pinned frames plus a named camera move
(API: image_uri, last_frame_uri, and camera_motion "dolly_in". The named
move and the pinned end frame are independent fields, not a conflict.)
A dolly in toward a chessboard mid-game, one hand hovering over a knight.
End on the knight set down two squares over, hand withdrawn from frame.
# 13 — Luma Ray 3.2 — first and last frame
(API: video.start_frame, video.end_frame. Not available at duration "10s";
use "5s" when either field is set.)
A candle burns down at a locked-off angle, warm light dimming as the wax
pool widens. End on the flame guttering to a thin thread of smoke.
# 14 — Vidu Q3 — start-end2video
(API: images = [start_frame_url, last_frame_url], in that order. Aspect
ratio between the two must fall within 0.8 to 1.25 of each other.)
A single kite climbs against a pale sky, wind visible in the tail ribbons.
End on the kite steady and small at altitude, string taut toward camera.
# 15 — Vidu Q3 — matched-ratio pair, tighter framing
(API: same images array as #14. Crop both stills to identical dimensions
before upload; Vidu's 0.8-1.25 tolerance is on ratio, not exact pixels.)
A single moth circles a porch light in full dark. End on the moth settled
on the bulb housing, wings folded, light steady behind it.
# 16 — Pika 2.5 Pikaframes — two keyframes
(API: images = [start_url, end_url], the minimum for this endpoint.)
Prompt applied to the whole transition: a block of ice on a sunlit
windowsill melts steadily into a shallow puddle, condensation forming on
the glass behind it.
# 17 — Grok Imagine 1.5 — workaround for no last-frame field
(API: image.file_id only. Since there is no last-frame input, the end
state has to be carried entirely in the text.)
Pan across the greenhouse aisle at golden hour and settle on a static wide
shot of the empty aisle at the far end, dust motes gone, light noticeably
lower than at the start.

How Do You Chain Frames Into a Continuity Workflow?

By deciding what the last frame of clip A has to look like before you generate clip A, because that decision is also the first frame of clip B.

The workflow is the same regardless of which vendor's field names you use:

  1. Generate or pick the still you want to open on. Write the accompanying prompt to describe motion and time, not the still's contents; image to video prompts covers that half in depth.
  2. Before you generate the clip, decide what its final frame needs to contain for the next clip to start there: same framing scale, same light direction, same subject position class, nothing mid-motion that would look broken as a still.
  3. Write that decision into the prompt as an instruction about the end state, not just the action. "Ends with the cup full, crema settled, hands withdrawn" gives the model a target frame; "she makes coffee" does not.
  4. Where the vendor hands the frame back to you directly, take it. BytePlus documents return_last_frame on Seedance: set it true and the finished task carries last_frame_url alongside the video. Feed that URL straight into the next clip's first-frame field. Where a vendor does not offer this, export the last frame from the finished clip yourself.
  5. Repeat down the chain. To close it into a loop, make the final clip's designed last frame match the very first clip's opening still.

A three-clip chain, one continuous scene, using Seedance's own frame-return mechanism throughout:

# 18 — Seedance 2.5 — chain, clip A
(API: first_frame = a generated still of the counter, empty. Set
return_last_frame true to carry the ending forward.)
A wide shot of an empty espresso counter at opening time, steam already
rising faintly from the group head, cool morning light through a side
window. End on a barista's hands entering frame right, reaching for a cup.
# 19 — Seedance 2.5 — chain, clip B
(API: first_frame = clip A's returned last_frame_url. return_last_frame
true again.)
Continue from the supplied first frame. The barista places the cup under
the group head and starts the shot pulling, same cool window light, camera
static. End on the shot finished, cup full, hands withdrawing from frame.
# 20 — Seedance 2.5 — chain, clip C, closing the loop
(API: first_frame = clip B's returned last_frame_url. last_frame = the
same still used to open clip A, closing the sequence.)
Continue from the supplied first frame. The finished cup is carried out of
frame right; the counter empties again, steam still faintly rising from
the group head, matching the opening shot exactly.

Choreographing more than two points (copy-paste)

# 21 — Luma Ray 3.2 — multi-keyframe, three anchors
(API: video.keyframes[], an array of ImageRefs pinned at chosen positions;
mutually exclusive with start_frame/end_frame and loop.)
A rocket sits on the pad under floodlights, then clears the tower, then
becomes a bright point against a darkening sky. Hold a locked vertical
framing throughout; only scale and light change.
# 22 — Pika 2.5 Pikaframes — four ordered keyframes
(API: images = [url1, url2, url3, url4]. Prompt applies to every
transition; raise transition_duration_s for a slower build between two
adjacent frames.)
A pour-over coffee setup assembles itself: empty dripper, ground coffee
added, water poured in a slow spiral, finished cup lifted away. Same
overhead angle and same window light across all four stages.
# 23 — Wan 2.7 — video continuation
(API: media[] with type "first_clip", pointing at a previously generated
video rather than a still image.)
Continue the previous clip. The paper boat, now lodged against the drain
grate, is lifted free by a gust and continues downstream, same grey light
and same handheld camera character as the clip it extends.

What Should the Two Stills Actually Look Like Before You Feed Them In?

Matched, not just similar.

Everything above assumes you already have two clean stills. In practice the two are often made separately, sometimes in different sessions or different image tools, and they rarely agree on lens character, light direction or color grade even when the subject matches. No vendor documents how a video model resolves that disagreement when it conditions on both. The safest assumption, based on our own testing rather than any vendor's published behaviour, is that it does not resolve it cleanly: the clip tends to drift toward whichever end the model's priors favour, which is a variant of the same effect Seedance's own reference-image guidance points at when it says there is no need to re-describe details a reference already shows. Style is one of those details, and an unstated style clash is still a clash.

The fix is to write the two still-image prompts as a pair, not as two independent requests. Share the lens, light source and color-temperature language between them, and change only what should visibly change.

# 24 — Still-image pair, opening frame (any still-image model)
A 35mm-equivalent shot, shallow depth of field, single warm tungsten key
light from frame left, slight film grain. A ceramic mug sits on a wooden
table, steam rising, background soft and dark.
# 25 — Still-image pair, closing frame (same still-image model)
A 35mm-equivalent shot, shallow depth of field, single warm tungsten key
light from frame left, slight film grain. The same mug now sits empty on
the same wooden table, background soft and dark, no steam.
# 26 — Still-image pair, opening frame — product scene
A flat studio product shot, soft top light, pale grey seamless background,
no visible shadow edge. An unopened cardboard shipping box centered in
frame.
# 27 — Still-image pair, closing frame — product scene
A flat studio product shot, soft top light, pale grey seamless background,
no visible shadow edge. The same box now open, packing paper folded back,
the product visible inside.

Where Does Frame Conditioning Stop Working?

At the edges you pinned, and nowhere past them.

Pinning both ends fixes where a shot starts and where it ends. It does not hand you control of what happens in between. No vendor in this survey publishes a way to steer the interpolation path itself; that is entirely the model's own decision, shaped only by whatever motion you describe in the prompt text. If the middle matters as much as the ends, Luma's multi-keyframe path is the one documented exception here, because it lets you pin interior positions too, not just two.

The one place documentation itself gets ahead of the feature: Kling's own spec calls last-frame-only generation unsupported "yet," which is the single hedge word in this entire survey. Everything else marked "not documented" in the tables above is genuinely unknown, not a quiet roadmap item. Re-check before you build a workflow around an absence turning into a feature.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.

Create An Account