如何找到任何视频文件的每秒帧数?

有没有找到 Ubuntu 上视频的帧率的简单方法?在 Windows 上,我使用 Gspot 来查找有关视频文件的所有信息。但是在 Ubuntu 上,我发现很难找到这些基本信息。任何帮助都将不胜感激。

这是不可能的,因为并非所有视频文件都有“fps”(因为存在可变帧率编码)。 - fkraiem
1VFR视频仍然具有平均帧率 - 其实用性取决于具体应用。 - thomasrutter
15个回答

这将告诉你帧率,如果它不是可变帧率的话:
ffmpeg -i 文件名
文件名被隐藏后的示例输出:
输入 #0, matroska,webm, 来自 'somerandom.mkv':
  时长: 01:16:10.90, 开始: 0.000000, 比特率: N/A
    流 #0.0: 视频: h264 (High), yuv420p, 720x344 [PAR 1:1 DAR 90:43], 25 fps, 25 tbr, 1k tbn, 50 tbc (默认)
    流 #0.1: 音频: aac, 48000 Hz, 立体声, s16 (默认)
ffmpeg -i 文件名 2>&1 | sed -n "s/.*, \(.*\) fp.*/\1/p"
有人编辑了一个并不完全符合我的要求。在这里引用here
额外的编辑...如果你想要tbr值,这个sed命令可以使用:
sed -n "s/.*, \(.*\) tbr.*/\1/p"

我需要在这个一行代码中使用tb而不是fp。似乎并非所有的视频文件都报告帧率,但它们都会输出类似于tbr tbc的数值,其数值相同。 - sup
有效,但是编辑输出的一行代码将tbc值而不是tbr值输出在这个特定的输出集中。这是我更改它的原因之一...我宁愿它以一种非常明显的方式失败,而不是一种完全不被注意到的方式。 - RobotHumans
我觉得 sed -n "s/.*, \(.*\) tbr.*/\1/p 最后缺少了 ",对吗? - sup
9FFmpeg并没有被弃用,avconv是从FFmpeg的一个分支中衍生出来的。为了避免那些使用FFmpeg替代方案的用户混淆,虚假的分支被标记为已弃用,以让这些用户知道他们正在使用的版本正在发生变化。你的评论是误导性的,可能会导致用户浪费时间研究这个问题。 - Chris
1如果是可变帧率呢? - 0xcaff
它在输出中指定了可变比特率(VBR)。 - RobotHumans
无论是恒定比特率还是可变比特率,都可以参考我的解决方案。 - Alberto Salvia Novella
ffmpeg的输出不适合机器解析。请改用专门用于此类用途的ffprobe,您将不再需要使用sed命令。请参考一些问题的答案或者访问FFmpeg Wiki: FFprobe获取更多信息。 - llogan

ffprobe -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate infile

结果:

2997/100

4这可能是最好的答案,因为它给出了准确的帧率(例如24000/1001 = 23.976023976)。 - ntg
1有时候,根据格式的不同,我会得到0/0 - Daniel_L
3根据你的需求,这要看情况。它会报告编码的帧率,但不会显示视频的实际帧率。例如,将一个30帧每秒的视频编码为60帧每秒,会显示60帧每秒,但实际输出仍然是30帧每秒。 - Harvey
11如果视频流不是第一个流,这种方法就不起作用;而且,如果它查找的是音频流,你将会得到0/0的结果。我会修改代码,加上"-select_streams V:0",这样就可以选择第一个运动的视频流了。 - Sam Watkins
2@SamWatkins的补集很重要。没有它,给定命令的输出将为0/0 - jdhao
不确定Linux,但Windows在infile参数之前需要-i。命令应为ffprobe ..... -i infile - Chef Pharaoh
错误!这是编码器的帧率,而不是视频的帧率。它们可以相匹配,但不一定!请查看我的解决方案以获得正确答案。 - Alberto Salvia Novella
我注意到r_frame_rate可能返回误导性的数字!avg_frame_rate更准确一些。 - FloPinguin
从视频/编解码器的角度来看,这两个数字是如何确定的?为什么是2997乘以100而不是299.7除以10等等。 - Raleigh L.
这个解决方案在存在两个(?)视频流的情况下也不适用。对于某些视频,我得到了以下结果:30/1 30/1 - Raleigh L.

这是一个基于Steven Penny答案的Python函数,使用ffprobe来获取精确的帧率。
ffprobe 'Upstream Color 2013 1080p x264.mkv' -v 0 -select_streams v -print_format flat -show_entries stream=r_frame_rate

import sys
import os
import subprocess
def get_frame_rate(filename):
    if not os.path.exists(filename):
        sys.stderr.write("ERROR: filename %r was not found!" % (filename,))
        return -1         
    out = subprocess.check_output(["ffprobe",filename,"-v","0","-select_streams","v","-print_format","flat","-show_entries","stream=r_frame_rate"])
    rate = out.split('=')[1].strip()[1:-1].split('/')
    if len(rate)==1:
        return float(rate[0])
    if len(rate)==2:
        return float(rate[0])/float(rate[1])
    return -1

rate = out.decode("utf-8").split('"')[1].split('/')会更好:它处理了多个视频流的情况。另外,我需要将子进程的输出转换为字符串,使用decode方法。 - FloPinguin
我注意到r_frame_rate可能返回误导性的数字!avg_frame_rate更准确一些。 - FloPinguin

获取给定的平均帧率,以分数表示:

fraction=$(ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=nw=1:nk=1 "${input}")

然后将其四舍五入到最近的整数

python -c "print (round(${fraction}))"


在Nautilus(图形文件管理器)中,与命令行相对应的选择是通过上下文菜单查看文件属性。对于音频/视频文件,您可以在那里获得一个额外的选项卡,其中包含附加信息。

这是一个使用mplayer的Python脚本来做这个的,如果有人感兴趣的话。它的用法是`path/to/script path/to/movie_name1 path/to/movie/name2`等等。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import subprocess
import re
import sys

pattern = re.compile(r'(\d{2}.\d{3}) fps')
for moviePath in sys.argv[1:]:
    mplayerOutput = subprocess.Popen(("mplayer", "-identify", "-frames", "0", "o-ao", "null", moviePath), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
    fps = pattern.search(mplayerOutput).groups()[0]
    print fps

这并不是非常详尽的。例如,你的正则表达式无法匹配 120 fps 的视频,而且它也无法处理 25 fps。此外,你需要转义 .。所以,请使用:(\d+(\.\d+)?) fps - slhck
嗯,这已经非常过时了。现在只需要在MPV上播放并按下i键就可以了。 - sup

我通常使用exiftool来获取任何文件类型的信息... 例如,使用命令exiftool file.swf,我可以了解任何swf文件的帧速率,这是我无法通过ffmpeg实现的。

使用默认与MPV捆绑的脚本来获取统计数据。只需使用MPV播放文件并按下i键,将显示一系列统计信息,包括帧率。

还适用于VLC:工具 > 编解码器信息。 - qwr

ffprobe <media> 2>&1| grep ",* fps" | cut -d "," -f 5 | cut -d " " -f 2

2讲英语翻译成中文。只返回翻译文本:解释它会做什么? - Raja G

如果有人偶然看到这个...你当然可以使用输入参数作为路径 ;)
import numpy as np
import os
import subprocess

def getFramerate():
    con = "ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 D:\\Uni\\Seminar\\leecher\\Ninja\\stream1.mp4"

    proc = subprocess.Popen(con, stdout=subprocess.PIPE, shell=True)
    framerateString = str(proc.stdout.read())[2:-5]
    a = int(framerateString.split('/')[0])
    b = int(framerateString.split('/')[1])
    return int(np.round(np.divide(a,b)))