4

I need a fast and reliable way to get the total frame count of a video.

Here are the following methods that I have tried and their flaws:

  1. ffprobe (fast way)

    ffprobe -select_streams v:0 -show_entries stream=nb_frames -of default=noprint_wrappers=1 input.mp4

Problem: Often returns N/A, not reliable.

  1. ffprobe (slow way)

    ffprobe -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mp4

Problem: Pretty slow, can take a minute for longer videos.

  1. ffmpeg (fast way)

    ffmpeg -i input.mp4 -map 0:v:0 -c copy -f null -

Problem: Needs to fully decode video once, which is rather slow

I know that what I'm looking for is possible because certain software (like Topaz Video Enhance) can do it. But I don't know how I can achieve this in my C# project or ffmpeg.

nmkd
  • 306
  • 3
  • 9
  • 2
    *Needs to fully decode video once, which is rather slow* --> with -c copy, it doesn't decode. – Gyan Feb 08 '21 at 08:52
  • Right, I guess then the bottleneck here is I/O. Running this on a 50 GB BD Rip on an HDD would take quite a while. – nmkd Feb 08 '21 at 13:16

2 Answers2

4

The command

ffmpeg -i input.mp4 -map 0:v:0 -c copy -f null -

does not decode frames and so is the fastest universal way.

For MP4/MOV family of files, there is another way which may be faster.

ffmpeg -i in.mp4 -v trace 2>&1 -hide_banner | grep -A 10 codec_type=0 | grep -oP "(?<=sample_count=)\d+"

FFmpeg parses the metadata when fed an input. The demuxers usually post some messages to the log with some of the key parameters read from the header. The MOV/MP4 demuxer does this at trace loglevel and it includes the 'sample count' for all tracks. The above command extracts it for the video track.

Gyan
  • 85,394
  • 9
  • 169
  • 201
0

Mediainfo seems to be pretty fast.

This command will return the frame count:

mediainfo --Output="Video;%FrameCount%" input.mp4

From what I tested, mediainfo returns frame count faster than ffmpeg or ffprobe.

These related question may also help:
Fetch frame count with ffmpeg - stackoverflow
How do I get the number of frames in a video on the linux command line? - superuser

Here is a C# method that returns the video frame count of a video file using mediainfo:

private static int GetVideoFrameCount(string videoFileName)
{
    Process proc = new Process();
    proc.StartInfo.FileName = "mediainfo";
    proc.StartInfo.Arguments = $"--Output=\"Video;%FrameCount%\" \"{videoFileName}\"";
    proc.StartInfo.CreateNoWindow = true;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;

    proc.Start();
    proc.WaitForExit();

    string output = proc.StandardOutput.ReadLine();
    return int.TryParse(output, out int frameCount) ? frameCount : -1;
}
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37