如何移除动画内容重复帧以节省超分辨率GPU时间并在编码时恢复帧时序?
我之前也碰到过一模一样的问题——动画里动辄25-50%的重复帧,超分辨率的时候纯纯浪费GPU算力,用mpdecimate去重后又不知道怎么把时序还原回来。后来摸索出一套用FFmpeg配合ChaiNNer的完整流程,既能省GPU时间,又能让最终视频播放效果和原片完全一致,给你一步步拆解:
第一步:生成去重后的无损视频与帧序列
首先我们要用FFmpeg的mpdecimate滤镜去掉重复帧,但不是直接删帧,而是把连续的重复帧合并成单帧,同时保留原视频的总时长和时序(相当于把重复帧的时长都加到保留帧上)。先导出一个无损的去重视频,方便后续提取帧和复用时序:
ffmpeg -i input.mp4 -filter:v "mpdecimate" -c:v libx264 -crf 0 -preset ultrafast lossless_decimated.mp4
然后从这个无损视频里提取帧,这些就是需要超分辨率的“唯一帧”,数量比原视频少一半左右:
ffmpeg -i lossless_decimated.mp4 -vsync 0 decimated_frames/%08d.png
-vsync 0是为了让每个帧保留原始的时间戳信息,后续编码时能准确还原时序。
第二步:用ChaiNNer处理超分辨率
把decimated_frames文件夹里的所有PNG导入ChaiNNer,按照你的常规流程做超分辨率处理就行。注意输出的upscaled帧要保持和原去重帧一样的文件名格式(比如都是8位数字命名:00000001.png、00000002.png...),方便后续FFmpeg识别顺序。
第三步:将Upscaled帧编码为原时序视频
这一步是关键——我们要把处理好的高分辨率帧,按照原视频的时序重新编码,让重复帧的视觉效果还原回来(其实是用upscaled的唯一帧填充重复位置)。直接用之前生成的lossless_decimated.mp4作为音频和时序模板就行:
ffmpeg -i upscaled_frames/%08d.png -i lossless_decimated.mp4 -map 0:v -map 1:a -c:a copy -c:v libx265 -crf 18 -vsync vfr output.mp4
-map 0:v取upscaled的视频帧,-map 1:a直接复用原去重视频的音频(和原片完全一致)-c:a copy避免重新编码音频,节省时间-vsync vfr让FFmpeg保留原始的时间戳信息,这样每个upscaled帧的显示时长会自动对应原视频中重复帧的总时长,最终视频的播放速度、时长和原片完全一样- 你可以把
libx265换成你喜欢的编码器,crf 18是高质量编码参数,可根据需求调整
额外验证小技巧
你可以先播放lossless_decimated.mp4和原视频对比,视觉上完全看不出区别(因为只是合并了重复帧,播放时还是原来的速度),确认没问题再做超分辨率,这样就能保证最终的output.mp4既高清又和原片播放效果一致。
如果遇到文件名顺序问题,确保去重帧和upscaled帧的文件名是连续的数字序列,FFmpeg才能正确按顺序读取。
备注:内容来源于stack exchange,提问作者helplessnoob

