AI Video Output FPS Doesn't Match What You Requested

Asked for 24fps cinematic, got 30fps? 60fps slow-mo judders everywhere but the model preview? Find which stage flipped the rate with ffprobe and lock it end-to-end.

Fastest fix: run ffprobe your_clip.mp4 and compare r_frame_rate to avg_frame_rate. If they differ, the clip is variable frame rate (VFR) and your editor and player disagree about its rate. Re-encode to constant frame rate at the rate you actually want with ffmpeg -i input.mp4 -fps_mode cfr -r 24 -c:v libx264 -crf 18 output.mp4, then set your editor’s project rate to match before you import. That clears most “wrong FPS” reports.

You set the model to “24fps cinematic.” The export lands on your timeline and the file inspector says 30fps. Or the video plays back fine in the model’s web preview but stutters everywhere else. Or you requested 60fps for a slow-motion shot and got a smooth-but-wrong 24fps clip where the model faked the extra frames in time. AI video frame rate looks like a clean numeric parameter, but it gets reinterpreted at four stages: the model’s native generation rate, the temporal interpolation step, the export muxer, and finally whatever editor or player you load it into.

This article maps where the FPS gets rewritten, how to detect which stage flipped it, and how to lock the frame rate end-to-end so the output matches the request. Commands below were checked against ffmpeg/ffprobe 7.x as of June 2026.

Which bucket are you in

Use this to jump to the right fix instead of trying everything.

SymptomMost likely stageGo to
Metadata says 30 but motion looks like ~15 unique framesModel native rate + interpolationCause 1, Fix Steps 1-2
Requested 24, file reads 23.976 or 25Export muxer roundingCause 2, Fix Step 3
Plays fine in player, drifts/sync-slips in editorVFR vs CFR mismatchCause 3, Fix Step 3
Asked for 60, got 30 (or smooth-but-fake 60)Rate above model’s maxCause 4, Fix Steps 1, 5
Clip looks right alone, wrong on the timelineEditor project rate overrideCause 5, Fix Step 4
”Slow motion” baked in, can’t re-time in postSlow-mo ramp baked at generationCause 6, Fix Step 5
Rate changed only after uploadPlatform re-encodeCause 7, Fix Step 7

Common causes

Ordered by hit rate, highest first.

1. Model generates at a fixed native rate, then interpolates to your requested rate

Most current models generate at one or two native rates internally, then temporally interpolate to the FPS you requested. The interpolation is not free: it introduces ghosting, double-edges, and motion that does not match real footage at that rate. As of June 2026 the common defaults are:

ModelTypical native outputNotes
Runway Gen-4 / Gen-4.524fps1080p native; higher rates are interpolated on export
Sora 224fps base, refined toward 301080p native, upscale options above
Google Veo 3.124fps base (can read 24-30 between shots)1080p native; rate can drift shot to shot
Kling 3.0up to 60fps nativenative 4K / 60fps is the standout (shipped Feb 2026)

Older sources will still say “Sora,” “Gen-3,” or “Kling” without a version; treat those as the previous generation and re-check the current model card before relying on a rate.

How to spot it: Scrub frame-by-frame. If alternating frames look near-identical or you see interpolation halos around moving edges, the file is “30fps” in metadata but only ~15fps of unique frames.

2. Export muxer rounds to the nearest broadcast rate

You asked for 24fps. The muxer rounds to 23.976 (NTSC film) or 25 (PAL). Some platforms force 30 or 60 regardless of input. The metadata reads the rounded value, not your request.

How to spot it: Compare requested FPS to actual file FPS via ffprobe. A 0.024 fps drift (24 → 23.976) is the muxer; a full rate swap (24 → 30) is the platform forcing.

3. Container declares one FPS, stream is actually another (VFR vs CFR)

The file’s container says 30fps but the actual frame timestamps are variable frame rate (VFR). Players honor the container, editors honor the timestamps, and they disagree. Audio-video sync drifts after import.

How to spot it: ffprobe reports two different rates — r_frame_rate (container declared) vs avg_frame_rate (computed from timestamps).

4. You requested high FPS but the model’s max is lower

You asked for 60fps. The model’s supported set is [24, 30]. The platform silently clamps to 30 (or to 24 then interpolates to 60). Your slow-motion plan was based on a rate the model never actually delivers.

How to spot it: Check the model’s documented FPS support set. If 60 isn’t in it, you’re getting interpolation, not real high-FPS capture.

5. Editor’s project rate overrides clip rate on import

Your DaVinci/Premiere project is set to 30fps. You drop a 24fps clip onto the timeline. The editor either drops frames, duplicates frames, or applies time-conformance silently. The “wrong” rate you see is the project, not the clip.

How to spot it: Right-click the clip in the bin (not on the timeline). The bin shows source rate. The timeline shows project rate. Mismatch confirmed.

6. Slow-motion ramp baked into the file at generation time

You prompted “slow motion” or “120fps look.” The model interpolated frames into the clip and exported at 30fps. The “slow-motion” is fake-smooth, but the file FPS is still 30. There is no high-FPS source to ramp from in post.

How to spot it: The clip looks slow but the frame rate is normal. Re-timing it in post produces choppy results because there are no extra frames to draw from.

7. Re-encoding for upload changes the FPS

YouTube/TikTok/X re-encode on upload. They normalize to platform standards (30 or 60). The file you uploaded was 24fps; what plays back to viewers is 30fps with their server-side interpolation.

How to spot it: Download your own video back from the platform. Run ffprobe. Compare to your upload.

Shortest path to fix

Step 1: Identify your model’s native rate

Read the current model card (Runway Gen-4, Pika, Kling 3.0, Sora 2, Veo 3.1) for “native frame rate” or “supported FPS.” If it is not documented, generate a 1-second clip at your highest requested rate, run ffprobe, and count how many frames are actually unique:

ffprobe -v error -count_frames -select_streams v:0 \
  -show_entries stream=r_frame_rate,nb_read_frames \
  -of csv input.mp4

If nb_read_frames divided by the duration matches the declared rate, you have real frames. If it’s half, the model interpolated.

Step 2: Pick a target rate that matches the model’s native rate

Don’t fight the model. If the native rate is 16fps, ask for 24 (close enough that interpolation is light) instead of 60. The output looks much better at a rate the model can honestly produce.

Step 3: Lock the export muxer to the requested rate

When re-encoding from the model output, force a constant frame rate:

ffmpeg -i input.mp4 -fps_mode cfr -r 24 \
  -c:v libx264 -crf 18 -preset slow output.mp4

The -fps_mode cfr flag converts variable frame rate to constant by duplicating or dropping frames as needed; -r 24 sets the exact target. No platform muxer guesswork. Note: the older -vsync 1 does the same thing, but -fps_mode replaced it back in ffmpeg 5.1 (June 2022) and -vsync now prints a deprecation warning, so use -fps_mode in any new script. -fps_mode is also per-stream, so you can set video and audio handling independently. See the ffmpeg main options docs for the full list of modes (cfr, vfr, passthrough, drop).

Step 4: Set the editor’s project rate before import

In DaVinci: Project Settings → Master Settings → Timeline Frame Rate. In Premiere: New Sequence → match the source clip rate. Set this before you import the AI clip. If you have multiple AI clips at different rates, set the project to the most common rate and convert outliers explicitly with optical flow.

Step 5: For true slow-motion, generate high-rate then ramp in post

If you want slow-motion, you need a real high-FPS source. Generate at 48 or 60fps if the model supports it natively (verify per Step 1; as of June 2026, Kling 3.0 is the mainstream model that delivers native 60fps). Then drop the clip on a 24fps timeline and reinterpret. Don’t ask the model for “slow motion” in the prompt, because that produces a fake slowdown baked into a normal-rate file.

Step 6: Verify after every encode stage

Don’t grep fps from the human-readable dump; it can show the container rate while hiding VFR. Pull both rate fields explicitly:

ffprobe -v error -select_streams v:0 \
  -show_entries stream=r_frame_rate,avg_frame_rate \
  -of default=nw=1 your_clip.mp4

Run this after the model export, after your re-encode, and after you download your own upload back from the platform. When r_frame_rate equals avg_frame_rate and both equal your target (for example both 24/1), the file is honest CFR. If they differ, you still have VFR and an editor will fight it.

Step 7: Upload at the platform’s native rate, not “highest possible”

If the platform re-encodes to 30, upload at 30. You skip one round of interpolation. For TikTok and YouTube Shorts, 30 is the safest target. For cinematic uploads to YouTube long-form, 24 is preserved if the file is honest CFR 24.

How to confirm it’s fixed

You are done when all three of these hold:

  1. ffprobe shows r_frame_rate and avg_frame_rate are equal and match your target (for example both 24/1).
  2. The clip drops onto a same-rate timeline with no “conform” or “interpret footage” prompt, and audio stays in sync to the end of the clip.
  3. After upload, the copy you download back from the platform still reports the same rate (or the platform’s standard rate you deliberately chose).

If step 1 passes but step 2 still warns, your editor project rate is the mismatch (Fix Step 4), not the file.

When this is not on you

Many models do not expose true frame rate control. They generate at their internal rate, and the “FPS” parameter only affects the export step’s interpolation. You can pick the export rate but not the underlying capture rate. That is a model limitation, not a config bug, and the honest fix is to pick a target close to the model’s native rate (Fix Step 2) rather than to demand a rate it fakes.

Easy to misdiagnose as

  • “Stuttering playback.” The file may be the correct frame rate; the issue is the player or display refresh-rate mismatch (for example, a 24fps file on a 60Hz monitor with no 3:2 pulldown). Test on a different player before blaming the file.
  • “Slow-motion looks bad.” If the model returned a 30fps file with baked-in fake slowness, no amount of post-production can recover the missing frames. Regenerate at a higher native rate instead.
  • “Audio drift.” Audio-video drift after import is usually a VFR-vs-CFR issue, not a frame-rate value issue. Re-encode to CFR first, then troubleshoot drift.

Prevention

  • Document each model’s native generation rate; share with your team.
  • Always re-encode model output to CFR before edit; never bring VFR onto a timeline.
  • Set editor project rate to match the dominant source rate before importing clips.
  • Run ffprobe on every model output as a first step before editing.
  • For slow-motion shots, generate at the highest native rate the model supports and ramp in post.
  • Don’t request frame rates the model doesn’t natively support; you only get interpolation.

FAQ

  • Why does the model give me 30fps when I asked for 24? Most models default toward platform-friendly rates. Even when you select 24, the export muxer may round to 23.976 or override to 30. Re-encode locally with ffmpeg -fps_mode cfr -r 24 to lock the exact rate.
  • Is interpolated 60fps the same as real 60fps? No. Interpolated frames are guessed midpoints, not captured motion. They look smooth but reveal artifacts on fast motion (ghosting, soft edges) and do not give you extra frames to draw on for real-time slow-motion playback.
  • -vsync 1 worked yesterday, why the warning now? -vsync has been deprecated since ffmpeg 5.1 (June 2022) and the current 7.x line still prints the warning. It runs for now, but the supported flag is -fps_mode cfr. Swap it in scripts so they do not break when -vsync is finally removed.
  • Which model actually outputs 60fps natively in 2026? As of June 2026, Kling 3.0 is the mainstream model with native up-to-60fps output (it shipped native 4K/60fps in February 2026). Runway Gen-4/4.5 and Sora 2 are 24fps native (Sora 2 refines toward 30), and Veo 3.1 is 24fps base and can read 24-30 between shots. Anything above a model’s native rate is interpolated, so confirm on the current model card before you plan a slow-motion shot.
  • ffprobe shows 24/1 and 2997/125 for one file. Which is real? That is the VFR tell: r_frame_rate (24/1) is the container’s declared base, avg_frame_rate (2997/125, about 23.976) is computed from timestamps. Re-encode to CFR so both agree, then both your player and editor read the same rate.
  • Will re-encoding to CFR hurt quality? A single re-encode at -crf 18 is visually near-lossless for delivery work. The frame duplication or dropping that CFR conversion performs changes timing, not per-frame detail, so the trade is worth it to stop editors and players from disagreeing.

Tags: #ai-video #Troubleshooting #Video generation #frame-rate #fps #export