AI 视频输出帧率跟你要的对不上

你点了 24fps 电影感,出来 30fps。或者 60fps 慢动作素材在别的地方放就掉帧。AI 视频 FPS 在每个环节都会被重新解释,怎么端到端锁死。

你把模型设成”24fps cinematic”,导出落到时间线上,文件信息一看是 30fps。或者更糟:在模型自带的网页预览里播得好好的,放到别的地方就卡。再或者你点了 60fps 想做慢动作,结果拿到一个流畅但不对的 24fps 片段,模型在时间维度上插值伪装出 60fps 的感觉。AI 视频帧率这个参数看起来很干净,但在三四个环节都会被重新解释:模型的原生生成 rate、时间插值步骤、导出 muxer,最后你打开的剪辑软件或播放器又是一层。

这篇梳理 FPS 在哪几个阶段被改写、怎么定位是哪一步翻了车、以及怎么端到端把帧率锁死,让输出和请求对得上。

Common causes

按出现频率从高到低排。

1. 模型用固定原生 rate 生成,再插值到你要的 rate

当前大多数模型(Sora、Runway Gen-3、Kling、Veo)内部只用一两个原生 rate 生成——通常是 8、12、16 或 24fps——然后在时间维度上插值到你请求的 FPS。这个插值不是免费的:它带来鬼影、双边缘、以及不像该 rate 真实拍摄出来的运动。

怎么判断:逐帧拖。如果相邻帧几乎一模一样,或者运动边缘有插值光晕,这个文件 metadata 是 30fps,但实际唯一帧只有 ~15fps。

2. 导出 muxer 把帧率四舍五入到最接近的广播标准

你要的 24fps。Muxer 取整成 23.976(NTSC film)或 25(PAL)。有些平台不管你输入什么直接强制 30 或 60。Metadata 里写的是取整后的值,不是你请求的值。

怎么判断:用 ffprobe 对比请求 FPS 和实际文件 FPS。漂 0.024fps(24 → 23.976)是 muxer 干的;rate 直接换(24 → 30)是平台强制。

3. Container 写一个 FPS,stream 其实是另一个(VFR vs CFR)

文件 container 写 30fps,但实际帧时间戳是 VFR(可变帧率)。播放器认 container,剪辑软件认时间戳,两边不一致。导入后音画就开始漂。

怎么判断:ffprobe 会报两个不同的 rate——r_frame_rate(container 声明)和 avg_frame_rate(从时间戳算出来)。

4. 你点了高 FPS,但模型最高没那么高

你要 60fps。模型支持集是 [24, 30]。平台静默 clamp 到 30(或者先 24 再插值到 60)。你的慢动作方案建立在一个模型根本不出的 rate 上。

怎么判断:看模型文档支持的 FPS 集。60 不在里头,你拿到的就是插值,不是真高 FPS 采集。

5. 剪辑软件项目 rate 在导入时覆盖了素材 rate

你的 DaVinci/Premiere 项目设的 30fps。你拖一个 24fps 片段上时间线。软件要么丢帧、要么复制帧、要么静默 time-conform。你看到的”错”的 rate 是项目的,不是素材的。

怎么判断:在素材箱里(不是时间线上)右键素材。素材箱显示源 rate,时间线显示项目 rate。对不上就是这个原因。

6. 慢动作 ramp 在生成时就 bake 进文件了

你 prompt 里写了”slow motion”或者”120fps look”。模型在片段里插值塞了帧,然后按 30fps 导出。这个”慢动作”是假流畅,文件 FPS 还是 30。后期没有任何高 FPS 源可以拿来 ramp。

怎么判断:片段看起来是慢的但帧率正常。在后期重新做时间,出来一卡一卡的,因为没有多余的帧可以取。

7. 上传时的重编码改了 FPS

YouTube/TikTok/X 在上传时会重编码。它们归一化到平台标准(30 或 60)。你上传的是 24fps,观众看到的是平台服务器端插值后的 30fps。

怎么判断:把自己的视频从平台下载回来。跑 ffprobe。和你上传的对比。

Shortest path to fix

Step 1: 摸清模型的原生 rate

读 Runway、Pika、Kling、Sora、Veo 的文档,找”native frame rate”或者”supported FPS”。没写的话,在你最高请求 rate 下生成 1 秒片段,跑 ffprobe,数实际有多少唯一帧:

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

nb_read_frames 除以时长等于声明 rate,说明帧是真的。如果只有一半,模型在插值。

Step 2: 选一个匹配模型原生 rate 的目标 rate

别跟模型硬刚。原生 rate 是 16fps,就要 24(差距小,插值轻),别要 60。模型能诚实给出的 rate,出片质量好得多。

Step 3: 把导出 muxer 锁到请求 rate

从模型输出重编码时强制 CFR:

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

-vsync cfr 把 VFR 转成 CFR。-r 24 锁死目标 rate。不让平台 muxer 瞎猜。

Step 4: 导入前先设好剪辑项目 rate

DaVinci:Project Settings → Master Settings → Timeline Frame Rate。Premiere:新建 Sequence → 匹配源片段 rate。在导入 AI 片段之前就设好。如果有多个不同 rate 的 AI 片段,把项目设成最常见的那个 rate,异常 rate 的片段用 optical flow 显式转换。

Step 5: 真要慢动作,先高 rate 生成再后期 ramp

想要慢动作,你需要真的高 FPS 源。如果模型原生支持 48 或 60fps 就用(按 Step 1 验证)。然后把片段拖到 24fps 时间线上重新解释。别 prompt 里直接写”slow motion”——那只会得到一个 bake 进正常 rate 文件里的假慢动作。

Step 6: 每个编码阶段都验一遍

养成习惯:

# 模型导出后
ffprobe model_output.mp4 | grep fps

# 你的重编码之后
ffprobe your_export.mp4 | grep fps

# 上传后下载回来再验
ffprobe downloaded_from_youtube.mp4 | grep fps

哪一步翻了 rate,在交付前能抓到。

Step 7: 按平台原生 rate 上传,别上传”最高”

平台要重编码到 30,你就 30 上传。少一轮插值。TikTok/YouTube Shorts 最稳的是 30。YouTube 长视频走电影感,文件如果是诚实的 CFR 24,24fps 会被保留。

When this is not on you

很多模型根本不暴露真正的帧率控制——它们以内部 rate 生成,“FPS”参数只影响导出步骤的插值。你能选导出 rate,但选不了底层采集 rate。这是模型限制,不是配置 bug。

Easy to misdiagnose as

  • “播放卡顿”。文件 rate 可能是对的;卡是播放器或显示器刷新率不匹配(比如 24fps 文件在 60Hz 屏幕上没做 3:2 pulldown)。先换播放器再 blame 文件。
  • “慢动作看起来不对”。如果模型给的是 30fps 文件里 bake 了假慢,后期怎么修都补不出缺的帧。回去用更高原生 rate 重生成。
  • “音画漂移”。导入后音画漂通常是 VFR vs CFR 的问题,不是帧率值的问题。先重编码到 CFR,再排查漂移。

Prevention

  • 把每个模型的原生生成 rate 记下来,团队共享。
  • 模型输出在剪辑前一定重编码到 CFR;绝不让 VFR 上时间线。
  • 导入前先把剪辑项目 rate 设成主源 rate。
  • 每个模型输出第一步都跑 ffprobe,再开始剪。
  • 慢动作镜头按模型支持的最高原生 rate 生成,后期再 ramp。
  • 别请求模型原生不支持的帧率;那只会拿到插值。

FAQ

  • 为什么我要 24fps 模型给我 30fps? 多数模型默认 clamp 到平台友好的 rate。即使你选了 24,导出 muxer 也可能取整成 23.976 或者覆盖成 30。本地重编码锁死。
  • 插值出来的 60fps 和真 60fps 一样吗? 不一样——插值帧是猜出来的中间帧,不是采到的运动。看起来流畅,但快速运动下会暴露 artifact(鬼影、边缘软),也不能真的拿来做慢动作回放。

标签: #ai-video #排查 #视频生成 #frame-rate #fps #export