ffmpeg:如果超过阈值则降低 fps,但如果低于阈值则不增加 [英] ffmpeg: reduce fps if over threshold but do not increase if under threshold

查看:38
本文介绍了ffmpeg:如果超过阈值则降低 fps,但如果低于阈值则不增加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ffmpeg CLI 允许您指定 -r -vf fps= 为您的输出设置固定的 FPS.>

我想得到的行为是:

  • 输入可以有任意 FPS(可能是 20-120).
  • 如果输入 FPS 大于 30,则将其降低到 30 FPS.
  • 如果输入 FPS <=30,请勿修改 FPS.

更多背景:

上述选项非常适合将视频标准化为固定 FPS,但不太好确保视频不会有效地超过某个 FPS 阈值.确实,如果我设置 -r 30 并且视频是 29 fps,那么 ffmpeg 会在不需要时为我们提供大量 CPU 以将其提升到 30我的用例.

解决方案

这可以在恒定帧率视频上完成 - 我下面的方法可能适用于 VFR 视频,但我没有合适的视频来测试.

基本命令:

ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0 out.mp4

在 120 fps 流中,

视频:h264(高)... 120 fps、120 tbr、15360 tbn、240 tbc

这会产生

视频:h264(高)... 30.08 fps,30 tbr,15360 tbn,240 tbc

选择过滤器的作用是,在选择第一帧后,仅选择与先前选择的帧的间隔为 1/30 秒或更多的其他帧.实际上,这会将视频压缩到 30 fps 以下.

注意两点:

1)最后一帧的时长被截断,所以fps值会略大于目标值.但所有其他帧都以 30 fps 的速度循环.

2) 输出帧率是源帧率除以一个整数所得的最高数值.所以,如果在命令中将30.01替换为26,结果将是24 tbr,因为除法不能得到25和26120 为整数.这有利于避免输出中的运动卡顿.命令中的除数应略大于上限,即 30.01 而不是 30.否则,结果是不稳定的.

如果输入为 30 fps 或更低,则选择所有帧.

<小时>

附录:

如果上述命令的输出通过管道传输到另一个 ffmpeg 实例,则输出 fps 是准确的,并且编解码器速率 tbc 也被重置.

ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0-c:v rawvideo -c:a pcm_s16le -f 坚果 - |ffmpeg -f 螺母 -i - out.mp4

The ffmpeg CLI allows your to specify -r <fps> or -vf fps=<fps> to set a fixed FPS for your output.

The behavior I would like to get is:

  • Input can have arbitrary FPS (likely 20-120).
  • If input FPS is >30, reduce it to 30 FPS.
  • If input FPS is <=30, do not modify FPS.

More context:

Aforementioned options are great to normalize videos to a fixed FPS but not so good to make sure videos do not get over a certain FPS threshold efficiently. Indeed, if I set -r 30 and the video is 29 fps, ffmpeg is going to us a lot of CPU to raise it to 30 when it wasn't needed for my use-case.

解决方案

This can be done on constant frame rate video - my method below may work on VFR video, but I don't have a suitable video to test.

Basic command:

ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0 out.mp4

On a 120 fps stream,

Video: h264 (High) ... 120 fps, 120 tbr, 15360 tbn, 240 tbc

this produces

Video: h264 (High) ... 30.08 fps, 30 tbr, 15360 tbn, 240 tbc

What the select filter does, after selecting the first frame, is only select further frames if their interval from the previously selected frame is 1/30th of a second or more. In practice, this decimates videos to below 30 fps.

Two things to note:

1) the duration of the last frame is truncated, so the fps value will be slightly greater than the target. But all other frames cycle at 30 fps.

2) The output framerate is the highest number obtained by dividing the source rate by an integer. So, if in the command, 30.01 is replaced by 26, the result will be 24 tbr since neither 25 nor 26 can be obtained by dividing 120 by an integer. This has the benefit of avoiding motion stutter in the output. The divisor in the command should be slightly greater than the ceiling i.e. 30.01 instead of 30. Else, the results are wobbly.

If the input is 30 fps or less, then all frames are selected.


Addendum:

If the output of the above command is piped to another ffmpeg instance, the output fps is exact and the codec rate tbc is reset as well.

ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0
        -c:v rawvideo -c:a pcm_s16le -f nut - | ffmpeg -f nut -i - out.mp4

这篇关于ffmpeg:如果超过阈值则降低 fps,但如果低于阈值则不增加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆