Back to the blog
Try siriusly.ai

Longer Videos with Gemini Omni: Last-Frame Chaining, Explained

Gemini Omni renders in fixed 4, 6, 8 or 10-second bursts - there is no "give me 30 seconds" option. Here's the technique that strings those bursts into one continuous shot anyway, and the prompt rules that keep the character, outfit and background from drifting between them.

Gemini Omni is one of the few video models that renders lip-synced speech and picture in a single pass, which is what makes it useful for anything that needs a person talking to camera. It is also hard-capped at 10 seconds per generation. Ask the API for a 10-second clip and you get exactly that back - ask for 30 and it silently rounds down to the nearest value it actually supports (4, 6, 8 or 10 seconds). There is no parameter that unlocks a longer single render, because the model was never trained to hold a shot together for longer than that.

That would make Gemini Omni useless for anything longer than a single breath, except that a 10-second cap on one generation is not the same as a 10-second cap on the finished video. The workaround - chaining chunks together by feeding each one's last frame into the next - is what turns a model that only knows how to render 10 seconds into one that can render a minute. It is also exactly how siriusly.ai's Studio builds every reel longer than a single chunk, so this post is as much a description of what already ships as it is a how-to.

Or skip straight to the result

siriusly.ai's Studio already runs this whole pipeline - chunk planning, last-frame extraction, drift-controlled prompts, lossless merge - behind one "generate" button.

Try it free

Why Gemini Omni Has a Hard Ceiling

Every video diffusion model renders a fixed number of frames per pass - that budget is set at training time, not something a bigger prompt or a higher tier unlocks. Gemini Omni's is short because it is also doing something most video models don't: generating the speech audio and the lip movement together, in the same pass, so the two can never drift apart the way a separately-dubbed track does. That joint generation is expensive, and the model's usable window for it tops out at 10 seconds. The API reflects this directly - it accepts a duration argument, but only four values are valid:

Requested durationWhat Omni actually renders
1-4s4s
5-6s6s
7-8s8s
9s and up10s (the ceiling)

Anything you ask for above 10 seconds still comes back as a single 10-second clip. If your script needs 25 seconds of a creator talking into camera, one generation call cannot get you there - full stop. The fix is not a bigger request. It's more requests, stitched so the seams don't show.

The Naive Fix (And Why It Looks Like a Jump Cut)

The obvious first attempt is to generate three separate 10-second clips from the same character prompt - "person X, wearing outfit Y, in setting Z, saying sentence 1" / "...saying sentence 2" / "...saying sentence 3" - and glue them together afterwards. This does not work, because a fresh generation call has no memory of the previous one. The model reads your reference image and your text prompt and produces its own interpretation of both, every single time. Across three calls you get three independent interpretations: the hair falls slightly differently, the shirt is a marginally different shade, the camera is a few degrees off, the room's lighting shifted. None of it is wrong in isolation - it's just not the same take.

Play those three clips back to back and the eye catches it instantly, even if no single frame looks broken. It reads as a jump cut where none was intended, which is the opposite of what a continuous UGC-style talking-head video needs.

Last-Frame Chaining, Step by Step

The fix is to stop asking the model to imagine the character fresh on every chunk, and instead show it exactly where the last chunk left off:

  1. Generate chunk 1 from your actual reference image - the character portrait, the product photo, whatever anchors the identity - with the first slice of your script.
  2. Extract the very last frame of chunk 1's output video as a still image.
  3. Generate chunk 2 using only that extracted frame as the reference image, with a prompt that tells the model this clip continues from it rather than starting fresh, and the next slice of the script.
  4. Repeat for chunk 3, chunk 4, and so on, always chaining off the previous chunk's last frame.
  5. Concatenate every chunk into one file once they've all rendered.

The reference image for chunk N+1 is a photograph of the exact pose, expression, lighting and background that chunk N ended on - not a redrawn approximation of them. The model isn't being asked to remember anything; it's being shown the answer and asked to keep going from there. That's the entire trick, and it's the same idea behind frame-interpolation and video-to-video continuation techniques elsewhere - Gemini Omni just makes it necessary because of how short its native window is.

A fresh generation call has no memory of the previous one. Chaining works because you stop relying on the model's memory and start handing it a photograph instead.

The Two ffmpeg Commands That Do the Actual Work

Both steps - grabbing the last frame and gluing the final chunks together - are one ffmpeg call each, and neither needs the video model's cooperation.

1. Extract the last frame

Seek to one second before end-of-file, then pull exactly one frame at maximum quality. Seeking from the end rather than decoding the whole file is what keeps this fast even on longer clips:

Shell
ffmpeg -sseof -1 -i chunk.mp4 \
  -update 1 -q:v 1 -frames:v 1 \
  -y reference_frame.jpg

-sseof -1 seeks to the last second of the file, -frames:v 1 takes exactly one frame, and -q:v 1 asks for the best JPEG quality ffmpeg can produce - a soft or compressed reference frame is one more way for the next chunk to drift, so it's worth not cutting corners here.

2. Merge the finished chunks

Once every chunk has rendered, stitch them with ffmpeg's concat demuxer and a stream copy - no re-encoding, so there's no quality loss and no re-render time on a step that's purely mechanical:

Shell
echo "file 'chunk_0.mp4'" >  list.txt
echo "file 'chunk_1.mp4'" >> list.txt
echo "file 'chunk_2.mp4'" >> list.txt

ffmpeg -f concat -safe 0 -i list.txt \
  -c copy -movflags +faststart \
  -y final.mp4

-c copy is the important flag: it copies the encoded video and audio streams byte-for-byte instead of decoding and re-encoding them, which is both instant and lossless. -movflags +faststart moves the file's index to the front so the result starts playing immediately in a browser instead of waiting on the whole file to download first - worth doing on anything you're about to embed or preview.

The Part That Actually Prevents Drift

Extracting and feeding forward the last frame gets you 80% of the way there. The other 20% - the difference between a chain that holds together for a minute and one that visibly mutates by chunk three - comes down to two prompt-level decisions.

One reference image, not two

It's tempting to keep sending the original character portrait alongside the extracted last frame on every chunk, on the theory that it "helps" the model stay on-model. In practice it does the opposite: two reference images of the same person pull the generation in two directions at once, because the model has to reconcile a professionally-lit portrait against a mid-scene video frame, and it settles somewhere between them. Across several chunks that averaging compounds and the character visibly drifts toward a generic middle ground.

Two references (portrait + last frame): the model reconciles two different lightings, two different framings, two "true" appearances of the same person. Each chunk nudges toward an average of the two, and the average shifts a little further every hop.

One reference (last frame only): the last frame already encodes the face, outfit, background and lighting exactly as the story stands. It's a strictly better single source of truth than a portrait shot in different conditions ever was.

Use the identity portrait for chunk 1 only. From chunk 2 onward, the previous chunk's last frame is the only image you attach.

Tell the model it's continuing, not starting

The prompt text matters as much as the image. A prompt written as if this were a fresh scene ("a person wearing a blue shirt, standing in a kitchen, says...") gives the model permission to reinterpret the shirt, the kitchen and the pose from scratch, even with the right image attached. A continuation prompt should say, in effect: this image is the final frame of the previous clip - keep going from exactly here. Lock down, explicitly, the three things that are cheapest for the model to quietly redesign:

  • Outfit - garment type, colour, pattern and fit, worn exactly as shown. Say "do not restyle" outright; leaving it implied is where wardrobes drift first.
  • Background - same room, same objects, same lighting, camera locked off. Otherwise the model treats a slight pan or a relit corner as a valid creative choice.
  • Anything held in-frame - a product, a cup, a phone. Describe it as something that's been sitting within reach the whole time, not something entering fresh each chunk, or it will visibly teleport in and out between clips.

Planning a Chunk Schedule for a Target Duration

Because Omni only renders 4, 6, 8 or 10-second increments, hitting an arbitrary target length means picking a combination of those that adds up close to it, then trimming the small remainder after the merge. The greedy approach - always cut the largest allowed chunk that still leaves at least one minimum-length chunk (4s) for the remainder - keeps the chunk count low without ever leaving a sliver too short to generate:

Worked example - a 23.7 second target

23.7s doesn't divide evenly into 4/6/8/10s pieces, so the plan takes the largest chunk that still leaves room for a valid remainder:

ChunkRequested lengthCovers
110s0.0s - 10.0s
28s10.0s - 18.0s
35.7s (rounds up to 6s, trimmed after merge)18.0s - 23.7s

Every chunk except the last renders at exactly one of the four allowed lengths, since Omni generates those precisely. The last chunk is requested at whatever allowed length covers the true remainder, then the merged output is trimmed back to the exact target - the only point in the whole pipeline where a duration mismatch needs correcting.

How Much Chaining a Video Can Take Before It Shows

Last-frame chaining doesn't have a hard limit built into it - there's no rule that says chunk 7 is impossible. What it has instead is compounding drift: extracting a frame and generating from it is a lossy round-trip, closer to a JPEG re-save than a perfect copy, and each hop adds a little more of it. Lighting can warm or cool slightly, fine details in a pattern can simplify, a facial expression can settle toward neutral. On a single hop none of it is visible. By hop five or six - 40 to 60 seconds of chained Omni chunks at max length - it usually is, at least to someone watching closely.

In practice that puts the useful range for pure last-frame chaining at somewhere between 20 and 60 seconds, depending on how demanding the scene is: a static waist-up talking head holds up longer than a scene with a product changing hands or a background full of fine detail. Past that, the better move is either accepting a hard cut to a new setup (a real edit, not a drift artifact) or handing continuity to a purpose-built video-to-video pass instead of another generation hop.

Common Mistakes

Sending both the character photo and the last frame on every chunk. Feels safer, actively causes the drift it's meant to prevent. See "one reference image, not two" above.

Fix: identity portrait for chunk 1 only. Last frame only, from chunk 2 on.

Re-describing the character fresh in every chunk's prompt. Gives the model implicit permission to redesign the outfit, the room and the framing even with the right reference image attached.

Fix: write a continuation prompt that states the image is the previous clip's final frame and explicitly locks outfit, background and any held object.

Re-encoding when merging chunks. A transcode pass on every merge is slow and throws away quality on a step that's purely mechanical.

Fix: concat demuxer with -c copy. It's instant and lossless because it copies the encoded streams as-is.

Shipping the merged file without trimming. Because generations are quantized to 4/6/8/10s, the merged video usually overshoots the target duration by up to a few seconds.

Fix: trim the final merged output back to the true target length as the last step, not each individual chunk.

FAQs

Does this work with other video models, or only Gemini Omni?

The technique is model-agnostic - any image-to-video model that accepts a reference frame can be chained the same way. Gemini Omni just makes it necessary sooner, since its 10-second ceiling is shorter than most. Models with native image-conditioning (Wan, Veo, Seedance and others) all support the same last-frame handoff.

Can I chain in an image that isn't the literal last frame - like a frame from a second earlier?

You can, and it's occasionally useful for papering over a bad final frame (a blink, a motion blur), but it introduces a small time gap the next chunk has to silently absorb. The literal last frame keeps the handoff exact.

Why not just generate one long video with a different model that supports it natively?

Some models do support longer native durations, but usually by giving up something else - Omni's simultaneous speech-and-lip-sync generation being the clearest example. Chaining lets you keep the property that made you pick the shorter model in the first place, instead of trading it away for length.

Does audio need any special handling across the chain?

Since Omni generates speech and video together in one pass, each chunk's audio is already synced to its own lip movements - concatenating the video streams concatenates matching audio for free. If you're dubbing a separately-generated voice track over the top instead, time it against the merged video's real duration, not the sum of the individually-requested chunk lengths, since the last chunk's requested length and its trimmed length can differ.

How does siriusly.ai handle this today?

Exactly as described above: the Studio plans a chunk schedule for your chosen reel length, generates chunk 1 from your character or product reference, extracts each chunk's last frame with the same ffmpeg call shown here, and submits every following chunk with that frame as the sole reference and a continuation prompt that locks outfit, background and any product in frame. The chunks are merged with a stream copy and trimmed to the target length before you ever see the result.

None of this is exotic - it's a still-frame extraction, a careful prompt, and a lossless concat. What makes it work is doing all three consistently, on every chunk, instead of skipping the boring parts because the video model did the hard-looking part already.

§ End · July 31, 2026
Was this useful?

Skip the pipeline.
We already built it.

siriusly.ai chains Gemini Omni, Wan and Seedance chunks automatically - last-frame continuity, prompt drift-control and all - so you just write a brief.

Start free