使用FFProbe获取视频帧率

31

我是ffprobe的新手,我的目标是获取视频的帧速率并将其存储到Java程序中。我的代码可以存储XML文件,但我想直接存储像int fps = 30;这样的数据。

ffprobe -v quiet -print_format xml -show_format -show_streams "/video/small/small.avi" > "/video/small/test.xml"

这是我的代码。

5个回答

57

这将打印视频的帧率:

ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate file.mp4

8
是的,它会打印FPS,但只作为精确的分数。幸运的是,你可以将这个分数输入计算器得到一个小数值。例如,如果这个命令的答案是 30000/1001,你可以将它输入计算器,得出29.97002997,四舍五入到大约30 FPS。 - GDP2
3
您可以将“-show_entries stream=r_frame_rate”替换为“-show_entries stream”,以获取所有可用值的列表,并使用“-of json/flat/…”以更易于解析的格式获取数据(如果需要)。 - Dragorn421
2
我注意到 r_frame_rate 可能会返回误导性的数字!avg_frame_rate 更加准确。 - FloPinguin
要获取文件夹中所有视频的FPS统计信息,请使用ls *.mp4 | xargs -n 1 -- ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate | sort | uniq -c - Jan Pokorný

5
你也可以直接运行这个命令,在Linux机器上获取视频的FPS。
ffprobe -v quiet -show_streams -select_streams v:0 INPUT |grep "r_frame_rate"

不需要使用 grep。只需像接受的答案中所示,单独使用 ffprobe 即可。 - llogan

4

被接受的回答建议使用stream=r_frame_rate。如果您只需要略微四舍五入的结果,那么这样做是可以的。(30/1而不是约29.7)

要获得精确且未四舍五入的FPS,请将总帧数除以持续时间:

ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -print_format csv="p=0" input.mp4 | read frames && 
ffprobe -i input.mp4 -show_entries format=duration -v quiet -of csv="p=0" | read duration && 
echo $(($frames/$duration))
    >> 29.970094916135743

文件时长:

ffprobe -i input.mp4 -show_entries format=duration -v quiet -of csv="p=0"
    >> 15.367000

文件的总帧数:

ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -print_format csv input.mp4
    >> 461

不错,但计算帧速率相当缓慢且昂贵。而且持续时间返回的是“流,<帧数>”,因此我们需要提取“第二列”。 - Tomasz Gandor
这给了我一个不准确的答案。 - danday74
@danday74 怎么了?这将总帧数除以总秒数,得出一个精确的、未舍入的答案。你的输入和输出是什么? - fullysprinkled

1
获取视频的FPS并将其打印到标准输出: 看到@geo-freak的答案并添加了只获取帧速率的代码(删除了额外的文本)。
ffprobe -v quiet -show_streams -select_streams v:0 input.mp4 |grep "r_frame_rate" | sed -e 's/r_frame_rate=//'

@o_ren的回答似乎更合理。

Python函数来执行相同操作:

def get_video_frame_rate(filename):
result = subprocess.run(
    [
        "ffprobe",
        "-v",
        "error",
        "-select_streams",
        "v",
        "-of",
        "default=noprint_wrappers=1:nokey=1",
        "-show_entries",
        "stream=r_frame_rate",
        filename,
    ],
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
)
result_string = result.stdout.decode('utf-8').split()[0].split('/')
fps = float(result_string[0])/float(result_string[1])
return fps

0

我发现另一种计算fps的方法是...

String query = "ffmpeg -i foo.avi 2>&1 | sed -n 's/.*, \\(.*\\) fp.*/\\1/p' > fps.txt";
    String[] command = {"gnome-terminal", "-x", "/bin/sh", "-c", query};
    Process process = Runtime.getRuntime().exec(command);
    process.waitFor();
    Thread.sleep(2000);
    try {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("fps.txt")));
        output = br.readLine();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }

无论如何,感谢朋友们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接