我有一个来自GoPro的240FPS视频,我想将其线性降低到30FPS。为此,我正在使用:
ffmpeg -i raw.mp4 -filter_complex "[v:0]setpts='lerp(2,8,T/5)*PTS" -r 30 output.mp4
* 5是视频时长,以秒为单位
问题在于所产生的视频严重卡顿。但是,如果我使用固定的setpts
,例如setpts=8*PTS
,那么一切都很好。
如何通过FFMPEG进行平滑的FPS转换?
答案 0 :(得分:1)
对于视频,
ffmpeg -i raw.mp4 -filter:v "setpts='if(between(T,0,1),PTS,(((T-1)*(1+7*T/4+1-7/4)/2+1)/T)*PTS)'" -an output.mp4
应该这样做,除了第一秒是正常帧速率。
从概念上讲,我发现以图形方式执行此操作最简单。请查看图像,其中x轴是时间,y轴是PTS。
我正在使用setpts过滤器。
PTS(表示时间戳记)指示何时显示帧,因此PTS * 1表示在输出中与输入同时显示它,其中PTS * 0.5指示在输入时间的50%处显示它。等
所以
setpts='if(between(T,0,1),PTS
表示在第一秒内保持帧速率不变(这主要是因为一个人不能除以零)。之后,面积 A1为1 * 1 = 1。
在t1 = 1s时,我们通过告诉每个帧比输入晚一些的时间开始降低帧速率。面积A2是梯形,其中面积是通过边的平均值乘以基数来计算的。底数为T-1,边的平均值为(1 +(7 * T / 4 + 1-7/4))/ 2(通过为直线创建函数)。要获得1到5秒之间任何给定帧的PTS,我们必须将所有先前区域(在这种情况下为一个)的面积相加,然后除以PTS * 1的面积,等于T。
因此从1s到5s,PTS的计算方式为
((T-1)*(1+7*T/4+1-7/4)/2+1)/T)*PTS
不幸的是,在ffmpeg中对音频使用相同的方法会丢弃大量数据,并导致严重破坏声音(至少是为了加速)。由于我可以准确地计算出视频的时长(与A1 + A2区域相同),因此我最终使用了audacity尝试手动调整每个可变费率部分。