30

I am new in ffprobe my aim is get video fps and store into java program. my code store xml files but i want store directly like int fps=30;

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

this is my code.

RDY
  • 613
  • 1
  • 9
  • 25

5 Answers5

56

This will print the video FPS:

ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate file.mp4
o_ren
  • 772
  • 1
  • 7
  • 14
  • 7
    Yes, it prints the FPS, but only as a precise fraction. Fortunately, you can take this fraction and put it into a calculator to get a decimal value. For example, if the answer from this command is `30000/1001`, you can put that into a calculator which yields `29.97002997`, rounding up to approximately 30 FPS. – GDP2 Apr 20 '19 at 22:01
  • 3
    You can replace "-show_entries stream=r_frame_rate" with "-show_entries stream" to get a list of all available values, and use "-of json/flat/..." to get the data in a more parseable format if needed – Dragorn421 May 15 '20 at 09:23
  • 2
    I noticed that r_frame_rate can return misleading numbers! avg_frame_rate was much more correct. – FloPinguin Oct 27 '20 at 15:06
  • To get the FPS statistics for all the videos in a folder, use `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ý May 12 '21 at 05:57
4

You can simply run this also, to get the video FPS, this will work on linux machines.

ffprobe -v quiet -show_streams -select_streams v:0 INPUT |grep "r_frame_rate"
geo-freak
  • 327
  • 3
  • 20
4

The accepted answer suggests using stream=r_frame_rate. This is okay if you only need a slightly rounded result. (30/1 instead of ~29.7)

For a Precise & Unrounded FPS, Divide Total Frames by Duration:

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

Duration of file:

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

Total frame count of file:

ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -print_format csv input.mp4
    >> 461
Tomasz Gandor
  • 8,235
  • 2
  • 60
  • 55
1

Get the video FPS and print it to stdout: Saw the answer by @geo-freak and added it to get only the frame rate (remove the extra text).

ffprobe -v quiet -show_streams -select_streams v:0 input.mp4 |grep "r_frame_rate" | sed -e 's/r_frame_rate=//'

The answer by @o_ren seems more reasonable.

Python Function to do the same:

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
Ankur Bhatia
  • 527
  • 3
  • 5
0

I found calculate fps in another method that is..

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();
    }

Anyway thanks friends.

RDY
  • 613
  • 1
  • 9
  • 25