跳转到内容

插帧与时序稳定

将动漫超分后的 RIFE 插帧、运动补偿时域降噪和光流修补整理成可执行流水线。

超分后如果出现抖动、跳帧、口型漂移、边缘闪烁或时间不连贯,默认流水线应该是:

超分
-> 插帧
-> 运动补偿时域降噪
-> 局部光流修补
-> 全片调色
-> 压制
-> A/B 回归

关键原则是:尽量让光流和运动向量在“还没有被重度降噪、锐化、调色破坏”的画面上工作;调色和最终压制放到时序稳定之后做。这样能降低插帧错配、边缘闪烁和局部拖影的概率。

交互式流程图入口:插帧稳定交互图

来源是一段关于“插帧与时序稳定”的 ChatGPT 分享内容。原内容给出了 RIFE、rife-ncnn-vulkan、VapourSynth + MVTools、低显存分块、光流修补和回归评测的命令清单。这里将它改写成长期可复用的视频后期流水线。

这条流水线适合接在动漫超分之后,目标不是单纯把帧率拉高,而是在提升流畅度的同时控制副作用:

  • 快速运动里的错配。
  • 嘴部、字幕和线条边缘的闪烁。
  • 插帧后出现的微抖、蚊噪和鬼影。
  • 音画不同步。
  • 低显存设备上的 OOM。

推荐顺序是:

  1. 先超分,让光流在高分辨率画面上估计,减少锯齿和边缘误判。
  2. 再插帧,把帧率提升到目标值。
  3. 再做运动补偿时域降噪,处理插帧后的小抖动和闪烁。
  4. 对破碎场景做局部光流修补。
  5. 最后做全片调色和压制。

如果素材已经有强烈 LUT、锐化或降噪,建议先拿 10-30 秒小样做对照。只要这些处理让运动边界更难估计,就应该把它们移到插帧之后。

官方 Python 版适合有 CUDA 或 PyTorch 环境的机器。它的优势是模型更新和参数空间更完整;代价是环境准备更重。

Terminal window
# 1) 抽出原音轨,后面无损合并
ffmpeg -i input.mp4 -vn -acodec copy audio.m4a
# 2) 拆成帧序列。PNG 更稳,JPG 更省空间
mkdir -p frames interpolated-frames
ffmpeg -i input.mp4 frames/frame_%06d.png
# 3) 运行 RIFE。--exp=1 表示 2x 插帧
python3 inference_video.py \
--exp=1 \
--img=frames/ \
--output=interpolated-frames/
# 4) 按目标帧率封装,并合并原音轨
ffmpeg -framerate 48 -i interpolated-frames/%06d.png -i audio.m4a \
-c:v libx264 -crf 18 -pix_fmt yuv420p \
-c:a copy out-rife.mp4

这里要避免一个常见错误:不要用原始帧率封装插帧后的帧序列。目标是 48fps、60fps 还是其他帧率,必须在重封装时显式写入。

rife-ncnn-vulkan 更适合低显存、无 PyTorch、macOS、核显或需要快速部署的场景。它的依赖更轻,适合先跑可用版本。

Terminal window
ffmpeg -i input.mp4 -vn -acodec copy audio.m4a
mkdir -p frames out-frames
ffmpeg -i input.mp4 frames/frame_%06d.png
./rife-ncnn-vulkan \
-i frames/ \
-o out-frames/
ffmpeg -framerate 48 -i out-frames/%06d.png -i audio.m4a \
-c:v libx264 -crf 18 -pix_fmt yuv420p \
-c:a copy out-rife-ncnn.mp4

如果 Windows 使用 .exe,只需要替换可执行文件路径。其余流程仍然是“抽音轨 -> 拆帧 -> 插帧 -> 按新 fps 合并音频”。

插帧后的小抖动和细碎噪点,优先用 VapourSynth + MVTools 处理。它不是普通空间降噪,而是基于前后帧运动向量做时域融合,更适合保留运动细节。

denoise.vpy
import vapoursynth as vs
core = vs.core
src = core.ffms2.Source("out-rife-ncnn.mp4")
super_clip = core.mv.Super(src, pel=2, sharp=1)
backward = core.mv.Analyse(super_clip, isb=True, delta=1)
forward = core.mv.Analyse(super_clip, isb=False, delta=1)
denoised = core.mv.Degrain1(
src,
super_clip,
backward,
forward,
thSAD=200,
)
denoised.set_output()
Terminal window
vspipe --y4m denoise.vpy - | \
ffmpeg -i - -c:v libx264 -crf 18 denoised.mp4

thSAD 是最先调的参数。经验范围可以从 150-300 开始:数值越高,时域融合越强;如果出现拖影,就降低它,或者改用 Degrain2/3 并重新调 delta

低显存设备可以把画面切成竖条分别插帧,再拼回去。这能规避 OOM,但要注意块边界。

Terminal window
mkdir -p tiles tiles-out
for i in 0 1 2; do
mkdir -p "tiles/$i" "tiles-out/$i"
ffmpeg -i frames/frame_%06d.png \
-vf "crop=iw/3:ih:iw/3*${i}:0" \
"tiles/$i/frame_%06d.png"
./rife-ncnn-vulkan \
-i "tiles/$i" \
-o "tiles-out/$i"
done
ffmpeg -framerate 48 \
-i tiles-out/0/%06d.png \
-i tiles-out/1/%06d.png \
-i tiles-out/2/%06d.png \
-filter_complex "[0][1][2]xstack=inputs=3:layout=0_0|w0_0|w0+w1_0[out]" \
-map "[out]" \
-c:v libx264 stitched.mp4

分块前要先确认宽高为偶数。边界抖动明显时,每块加 2-4px 重叠,再在拼接前裁回目标区域。

有些镜头不适合全片强行自动处理,例如:

  • 快速运动。
  • 大幅形变。
  • 淡入淡出。
  • 字幕边缘。
  • 嘴部和角色轮廓。

这类位置可以做局部光流引导修补:基于前后帧光流,对破碎或缺块区域做 inpainting 或导向型融合。它不应该作为默认全片步骤,而是用于少数问题镜头的局部打磨。

如果目标是时序稳定,调色通常放在插帧和运动补偿降噪之后。原因是强 LUT、局部对比、锐化和降噪都可能改变光流估计所依赖的边缘和亮度关系。

LUT 调色流水线 拼接时,可以这样理解:

  • 小样阶段:可以先套轻量 LUT 预览整体风格,但不要用它作为插帧输入的唯一版本。
  • 正片阶段:优先 超分 -> 插帧 -> 时域降噪 -> 调色 -> 压制
  • 特殊情况:如果插帧工具输出会明显改变颜色,再把 LUT 固定放到插帧后。

不要只看平均指标。动漫插帧更需要主观回归集。

建议保留一组固定小样:

  • 人物嘴部。
  • 快速镜头。
  • 淡入淡出。
  • 字幕边缘。
  • 高饱和线条。
  • 暗部运动。

每次参数变化都至少比较:

  1. 仅超分版本。
  2. 超分 + 插帧版本。
  3. 超分 + 插帧 + 时域降噪版本。
  4. 最终调色压制版本。

客观指标可以看 PSNR/SSIM,但最终判断仍然要回到口型、边缘、拖影、闪烁和音画同步。

  • 口型漂、边缘闪:插帧后做 MVTools 时域降噪;必要时对嘴部或字幕局部减弱强度。
  • 鬼影、拖影:降低 thSAD,减少 Degrain 强度,极端镜头改局部光流修补。
  • 色带、块状:提高码率,或改用 10-bit 编码,例如 -pix_fmt yuv420p10le 加 x265。
  • 性能不足:无 CUDA 用 rife-ncnn-vulkan;有高性能 NVIDIA 显卡再优先官方 RIFE Python 版。
  • 音画不同步:始终按插帧后的真实 fps 重封装,并用原音轨 -c:a copy
  • 分块接缝:保证偶数分辨率,使用重叠裁剪,避免块边界刚好落在高运动主体上。
  • 做一键脚本:拆帧、抽音轨、RIFE/ncnn 分支、重封装、回归样片导出。
  • 为 Mac mini、4070 Ti Super 等不同机器整理并行数和显存参数。
  • 把固定回归样片结构沉淀成目录模板。