Article cover for Extended an AI video and the join stutters? No frame repeats — the motion breaks for half a second

Extended an AI video and the join stutters? No frame repeats — the motion breaks for half a second

We measured the cat-and-paper-boat seam frame by frame. The portrait clip does not repeat the previous action: it barely moves for half a second before continuing.

Published
Updated

Short version: a plain join does stutter — just not the way you think.

Here is what happened. The cat-and-paper-boat clip (the whole story is in Making a video with AI: a paper boat comes for a stray cat) was generated in three takes, each one seeded with the last frame of the take before it. Seedance 2.5 honours that very well; the compositions on both sides of a seam are nearly glued together. The director watched 02 and 03 and said: "The first frames of 03 look like they overlap the tail of 02 — see how to handle that when you cut."

So we really did look, frame by frame. Verdict: no overlap. Not one frame repeats. And yet it does stick.

What "stuck" actually is: half a second of dead water

Take the first 240 frames of 03 and match each one against the last 240 frames of 02. If the timelines truly overlapped, the correspondence would draw a slope: frame 10 of 03 looks like frame −30 of 02, frame 20 like frame −20, and so on. What we got was a flat line. Every early frame of 03 looks most like the last frame of 02, and the similarity only decays over time. Nothing is re-enacted.

What is really going on is obvious once you watch what each take is doing:

  • End of 02: the paper boat spends about five seconds unfolding into a rainbow six-pointed star.
  • Start of 03: the star folds back into a boat, the boat lifts off, and the cat follows it into the street.

The fold is not a rewind; it is the wind-up before lift-off. The problem is the first 0.5 s of 03, which barely moves. We call this near-still opening slow-start dead water. Join these takes raw and the audience sees: star opens to the top, freezes for half a second, then folds. That pause explains why this seam felt stuck even though the action did not repeat.

Seam comparison for Cat Mobile 02 to 03. Top row is the raw join, where the first half second of 03 barely moves; bottom row removes the first 30 frames and adds a 0.1 s dissolve; the curve below shows per-frame motion for both cuts.

The same 02→03 seam. Top row, raw join: 03 barely moves for about half a second. Bottom row: 30 frames cut plus a 0.1 s dissolve. The curve underneath is per-frame motion; the half second where the red line drops into the shaded band is the dead water.

Same second of footage, looping at half speed. Left is the raw join, which pauses after the seam; right is the final cut, which keeps going. At half speed that half second becomes a whole one, and the eye cannot miss it.

Before you cut: make sure the footage is not lying to you

We had not planned to write this section. One sentence forced it: "I thought the originals were 60 fps — why did it come out 30?"

It had not. The file was true 60. The 30 came from CapCut, which reports its project timeline rate, not the footage. But that sentence made us go back and measure all three takes, and the measuring found two real problems.

Method first. A video has three "frame rates", and they are not the same thing:

Frame rate What it is Who can change it
Container fps The number in the mp4 header Anyone, any tool, any value
Frame density Frame count ÷ duration; the container really holds this many frames Interpolation, repackaging
Effective fps What actually moves once you discard frames nearly identical to the previous one Only the pixels themselves

Pack 30 fps content into a 60 fps container and the first two numbers dutifully say 60. Only the third one tells the truth.

You cannot detect padded frames by counting "frames with diff equal to zero". Once a duplicated frame is re-encoded it picks up compression noise; the diff lands between 0.02 and 0.15, and any absolute threshold misses it. We look at phase structure instead: within every P frames a fixed number do not move, and that periodic signature survives compression. Measured: padded footage shows an odd/even phase difference of 7.5×, real footage 1.1×. No judgement call needed.

The two things we found:

Take Frames Near-still frames Reading
cat_mobile_01 722 2 (0.3%) clean 60
cat_mobile_02 1020 137 (13.4%) stalled frames; effective smoothness around 52 fps
cat_mobile_03 1082 1 (0.1%) clean 60

The 13.4% of stalled frames in 02 always come in pairs, 8 to 12 frames apart, with normal frames on either side. We interpreted that irregular spacing as a defect in this take rather than the fixed-period pattern of a frame-rate conversion. We did not regenerate: the stalls were hard to see in this moving shot (and because the boss's tokens are finite). We therefore cannot say whether regenerating would have cleared them.

The second finding was more embarrassing. The landscape 03 turned out to be 854×480, 24 fps, 433 frames. It was the preview download. Generation platforms usually offer a preview and an HD file, and the names can be identical. Join the preview and you upscale 3.7× into mush; bringing 24 fps into a 60 fps timeline also requires filling in frames. Neither operation recovers the missing source detail or frames. Back to the platform, download again. That check is now the first step of our process, no exceptions.

Only three kinds of seam, and they are cut in opposite ways

Get the class wrong and the fix makes things worse, so classify before you cut:

Type Signature Treatment
Different shot The first frame of 03 is about as similar to every frame of 02 as two unrelated pictures Hard cut; do not add a transition
Composition continuation The first frame of 03 matches the last frame of 02, and the correspondence curve afterwards is a flat line Cut the dead water, short dissolve
True overlap The correspondence curve is a slope; 03 re-enacts 02 Cut the re-enacted stretch

The key is that correspondence curve, and it needs a control group: the median MAE of random pairings. Without it you cannot tell whether "MAE 11.6" is similar or not. In the portrait batch, the first frame of 03 against the last frame of 02 scores 11.6 with a control median of 46.6 — that is similar; the 01→02 seam sits around 50 across the board, the same as the control — that is a shot change, meant to be a hard cut, leave it alone.

A single-frame comparison cannot separate composition continuation from true overlap, and their cuts are opposites: one trims the head of the new take, the other trims the tail of the old one.

Use the ratio to find cut candidates, then judge the motion

When the composition continues across the seam, the motion ratio helps us decide whether to trim and how many frames to remove:

Motion in the 0.6 s after the seam ÷ motion in the 0.6 s before it.

Below 0.75, check for a pause; above 1.4, check for a sudden acceleration. These are inspection cues, not pass/fail limits. Choose the cut for smooth playback, rather than trimming more frames just to get the ratio closest to 1.

The portrait numbers were 0.54 uncut and 1.45 with 30 frames cut. We kept the 30-frame trim to remove the opening half-second pause and let the action continue, not to force the ratio below 1.4.

We learned this the hard way. The landscape footage looked identical to the portrait. Following the portrait logic we looked only at 03's own curve — "low then high", must be slow-start — and worked out a cut of 54 frames.

The answer was 0.

Landscape 02→03 No cut Cut 30 Cut 54
After ÷ before 0.93 0.99 1.59

The landscape 02 simply ends slowly (motion 0.48; the portrait is 0.83), so 03 opening at 0.45 is a match, not dead water; the climb to 2.0 afterwards is not "slow-start ending", it is the cat actually starting to follow the boat. Same curve, different baseline, opposite conclusion. Two batches that look the same needed 30 and 0; you cannot copy one onto the other. That one is on us.

Even at a cut of 0, keep a 0.1 s cross-dissolve. A continued take differs from the previous tail in texture and lighting (MAE usually 10 to 13), so a hard cut flashes; since the composition matches, the dissolve does not ghost.

Three FFmpeg landmines

The join is encoded in a single pass with nothing written to disk in between, so there is no second generation of quality loss. But the filter chain has three traps:

  1. The output of concat must go through fps=60,settb=AVTB before xfade. Otherwise you get Error reinitializing filters, a message that never mentions timebase — and each step runs fine on its own, only the chain dies.
  2. Every audio stream needs aformat to unify the sample format. Otherwise the AAC encoder returns -22 Invalid argument and looks broken.
  3. A wrong xfade offset does not error. FFmpeg exits 0 and puts the transition at the wrong time; you only find out on playback. The first two fail loudly and are easy to trace; this one fails silently. So the script reads durations with ffprobe, computes the offset, and prints it.

Verify after cutting, and not just the headers

  • Duration reconciliation: the output duration equals the sum of the takes minus the seconds cut minus the dissolve, within a few frames. Portrait: 12.033 + 17.020 + 18.033 − 0.5 − 0.1 = 46.49, actual 46.50.
  • Seam frame grabs: pull a few frames either side of each seam and look at them side by side — no ghosting on the dissolve, continuity across the hard cut.
  • Effective fps: measure the output again; it should match the sources. The portrait output has 2 duplicate frames in 2,789.
  • Segment-wise audio: run volumedetect at several points along the clip for silences and clipping. Its output is at info level; -v error shows nothing.

Frame grabs and motion curves are not the same as having watched it play through.

The tools are open source

The three scripts — footage QC, seam diagnosis, the join — and every rule above are in the public Curtoom video-clip-stitching skill, one line to install for Claude Code or Codex. Honestly, the whole thing started with the director saying "wait, I thought you could do this with ffmpeg?" — it was ffmpeg the entire way, no editor opened.

Storyboards govern what happens before generation; for writing panels so shots connect, see Use a simple storyboard to make every shot connect; for the panel-by-panel check of the eight-panel storyboard against the final video, see Does an AI video really read the storyboard?. This article only cares about the 0.5 s after you have the three takes in hand.

SERIESCreate Video with AI4 articles
  1. 01Create Video with AI: your prompt is your video
  2. 02Create Video with AI: start with text, an image or a script?
  3. 03Create Video with AI: use a simple storyboard to connect every shot
  4. 04AI Video Character Consistency Starts with a Character Sheet
RECOMMENDED
TutorialPrompt Engineering for Seedance 2.5: A Previz-to-Video TemplateTutorialPrompt Engineering for MiniMax H3: A Previz-to-Video Template From 246 Clips

Cookie preferences

Your choice applies to Alchemint Article in this browser. You can change it here at any time.