Skip to content
  • (+91) 9409548155
  • support@appdividend.com
  • Home
  • Pricing
  • Instructor
  • Tutorials
    • Laravel
    • Python
    • React
    • Javascript
    • Angular
  • Become A Tutor
  • About Us
  • Contact Us
Menu
  • Home
  • Pricing
  • Instructor
  • Tutorials
    • Laravel
    • Python
    • React
    • Javascript
    • Angular
  • Become A Tutor
  • About Us
  • Contact Us
  • Home
  • Pricing
  • Instructor
  • Tutorials
    • Laravel
    • Python
    • React
    • Javascript
    • Angular
  • Become A Tutor
  • About Us
  • Contact Us
Python

Finding Total Number of Frames in a Video File with Python

  • 08 Oct, 2024
  • Com 0
Finding Total Number of Frames in a Video File in Python

If you are creating a facial recognition, motion detection, or object tracking app, you often need to process videos frame by frame. By knowing the total number of frames in a video file, you can get the duration of the video.

Here is the formula:

duration (seconds) = total_frames / FPS (Frames per second)

Python offers several ways to calculate the count of frames in a video.

Here are five ways:

  1. Using OpenCV’s CAP_PROP_FRAME_COUNT Property
  2. Using Manual Frame Counting with OpenCV
  3. Using ffprobe from FFmpeg via Subprocess
  4. Using PyAV Library
  5. Using MoviePy Library

Here is the “sample.mp4” video we will be using for this practical:

https://appdividend.com/wp-content/uploads/2024/10/sample.mp4

Method 1: Using OpenCV’s CAP_PROP_FRAME_COUNT Property

Capture the input video using cv2.VideoCapture property and then use the cv2.CAP_PROP_FRAME_COUNT property wrapped up by int() function to get the total number of frames.

You need to install the opencv-python library in order to use the cv2.VideoCapture property.

pip install opencv-python

Decision tree diagram

Decision Tree diagram of using OpenCV's CAP_PROP_FRAME_COUNT

Here is the complete Python code:

import cv2


# Custom function that returns total number of frames
def count_frames_opencv(video_path):
    # Capturing the input video
    video = cv2.VideoCapture(video_path)

    # Accessing the CAP_PROP_FRAME_COUNT property
    # To get the total frames
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    video.release()
    return total_frames

# Example usage


# Input video
video_path = 'sample.mp4'

# Calling the custom function
frame_count = count_frames_opencv(video_path)
print(f"Total frames: {frame_count}")

Output

Total frames: 230

And we get the total frames in the output which is 230. The CAP_PROP_FRAME_COUNT approach is blazing fast and avoids reading each frame saving time. The best usecase is to get quick estimates with standard video formats where accuracy does not play a vital role.

However, it might return 0 or -1 for certain codecs or corrupted files. It also heavily relied on the metadata of the video which means if the metadata is incorrect, the final output will be incorrect so it provides moderate accuracy which may not be suitable for highly secure applications.

The time complexity is O(1) and the space complexity is also O(1) because it does not have to iterate each frame for counting and requires less memory usage.

Method 2: Manual Frame Counting with OpenCV

If you do not want to rely on metadata and maintain the high accuracy of several frames, you need to count manually with the help of OpenCV using a while statement.

import cv2

# Custom function to manually count
# total number of frames
def count_frames_manual(video_path):
    # Capturing a video
    video = cv2.VideoCapture(video_path)

    # total frames set to 0
    total_frames = 0

    # Using while statement
    while True:
        # Counting frames using loop
        ret, frame = video.read()
        if not ret:
            break
        total_frames += 1
    video.release()
    return total_frames


# Sample input video
video_path = 'sample.mp4'
frame_count = count_frames_manual(video_path)

print(f"Total frames: {frame_count}")

Output

Total frames: 230

It counts each frame to ensure the accurate total and does not rely on metadata. However, this is the most time-consuming approach because it reads every frame in memory causing high CPU usage. It is not suitable for processing multiple large videos.

If you need accuracy and do not care about time efficiency then I would recommend using this approach otherwise go with the OpenCV’s CAP_PROP_FRAME_COUNT property.

The time complexity is O(n) where “n” is proportional to the number of frames it needs to go through.

The space complexity is O(1) because it reads one frame in memory at a time.

If you want to optimize this approach then consider processing keyframes or sampling.

Method 3: Using ffprobe from FFmpeg via Subprocess

Use the ffprobe tool from the FFmpeg library to extract metadata directly from the video via a subprocess call. The ffprobe approach requires an external dependency FFmpeg/ffprobe which you must install separately.

brew install ffmpeg

If you are using a Windows machine then ensure FFmpeg is installed and added to the system PATH.

import subprocess
import json


# Custom function that accepts video
# and return the count of total frames
def count_frames_ffprobe(video_path):
    # command for subprocess call
    cmd = [
        'ffprobe',
        '-v', 'error',
        '-select_streams', 'v:0',
        '-count_frames',
        '-show_entries', 'stream=nb_read_frames',
        '-print_format', 'json',
        video_path
    ]
    # Running the subprocess
    result = subprocess.run(cmd, stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE, text=True)
    # Converting json result into dictionary object
    output = json.loads(result.stdout)
    
    # Counting frames
    frame_count = int(output['streams'][0]['nb_read_frames'])
    return frame_count


# Example usage
video_path = 'sample.mp4'
frame_count = count_frames_ffprobe(video_path)
print(f"Total frames: {frame_count}")

Output

Total frames: 230

This is a highly accurate approach that handles a wide array of video formats and codecs. However, it does require third-party software installed on your machine and hence takes more time to process and faces compatibility issues on different operating systems. Since we are using a subprocess module, it involves spawning a new process.

Time complexity is O(n) where n is the FFmpeg software which takes some time to load. It reads frame count from metadata directly rather than reading each frame.

Space complexity is O(1) because it requires minimal usage.

Method 4: Using PyAV Library

The PyAV library allows us to iterate each frame of the video and count it. You can install PyAV using the command below:

pip install av

Now, create a custom function that accepts a video as an input file, opens it, decodes each frame using the .decode() function, and counts the total number of frames.

import av

# Custom function that uses .decode() function
# to decode each frame
def count_frames_pyav(video_path):
    container = av.open(video_path)
    total_frames = 0
    for frame in container.decode(video=0):
        total_frames += 1
    container.close()
    return total_frames


# Input video
video_path = 'sample.mp4'

# Calling the custom function
frame_count = count_frames_pyav(video_path)

# Printing the number of frames
print(f"Total frames: {frame_count}")

Output

Total frames: 230

The PyAV approach is accurate and supports various formats and codecs. However, it requires iterating over frames, which can be time-consuming. It also requires PyAV installation, which can be challenging due to dependencies on various operating systems.

It has a time complexity of O(n) where n is a frame through which it will iterate.

The space complexity is O(1).

Method 5: Using MoviePy Library

The moviepy is a specialized video editing library in Python that can load the video file and calculate the frame count by multiplying the video’s frames per second (FPS) by its duration.

Install the moviepy library using the command below:

pip install moviepy

If you are facing any error, install the FFmpeg in your system.

Here is the complete code:

from moviepy.editor import VideoFileClip

# Custom function that accepts video
# And returns frame count
def count_frames_moviepy(video_path):
    
    # Calculating FPS and duration
    clip = VideoFileClip(video_path)
    fps = clip.fps
    duration = clip.duration
    
    # Counting frames based on fps and duration
    frame_count = int(fps * duration)
    clip.reader.close()
    clip.audio.reader.close_proc()
    return frame_count


# Input video
video_path = 'sample.mp4'

# Calling the custom function
frame_count = count_frames_moviepy(video_path)

# Printing the frame count
print(f"Total frames: {frame_count}")

Output

Total frames: 230

If you are using a video that has a variable frame rate then this approach might not be working as expected. It also depends on MoviePy and FFmpeg being installed on your machine. So, if you are facing an error in dependencies, you won’t be able to run this program.

Since this is a video editing library, it can handle many video formats and codecs. It provides a high-level easy functions to integrate into your project.

The time complexity is O(1) because it calculates based on fps and duration.

The space complexity is O(1) because of constant space usage.

Measuring execution time for each approach

I want to measure the time execution for each method to get an idea of which method is the fastest to return the output. This is my personal findings to find out which is the fastest method. 

To measure the time for each method, we can use the “time” module and then plot the bar chart using the “matplotlib” library.

Here is the complete code:

import cv2
import subprocess
import json
import av
from moviepy.editor import VideoFileClip
import time
import matplotlib.pyplot as plt

# Custom function that returns total number of frames using OpenCV
def count_frames_opencv(video_path):
    video = cv2.VideoCapture(video_path)
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    video.release()
    return total_frames

# Custom function to manually count total number of frames using OpenCV


def count_frames_manual(video_path):
    video = cv2.VideoCapture(video_path)
    total_frames = 0
    while True:
        ret, frame = video.read()
        if not ret:
            break
        total_frames += 1
    video.release()
    return total_frames

# Custom function that accepts video and returns the count of total frames using ffprobe


def count_frames_ffprobe(video_path):
    cmd = [
        'ffprobe',
        '-v', 'error',
        '-select_streams', 'v:0',
        '-count_frames',
        '-show_entries', 'stream=nb_read_frames',
        '-print_format', 'json',
        video_path
    ]
    result = subprocess.run(cmd, stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE, text=True)
    output = json.loads(result.stdout)
    frame_count = int(output['streams'][0]['nb_read_frames'])
    return frame_count

# Custom function that returns total frames using PyAV


def count_frames_pyav(video_path):
    container = av.open(video_path)
    total_frames = 0
    for frame in container.decode(video=0):
        total_frames += 1
    container.close()
    return total_frames

# Custom function that returns total frames using MoviePy


def count_frames_moviepy(video_path):
    clip = VideoFileClip(video_path)
    fps = clip.fps
    duration = clip.duration
    frame_count = int(fps * duration)
    clip.reader.close()
    clip.audio.reader.close_proc()
    return frame_count


# Measure time taken by each method and store the results
video_path = 'sample.mp4'
methods = {
    'OpenCV CAP_PROP_FRAME_COUNT': count_frames_opencv,
    'OpenCV Manual Count': count_frames_manual,
    'ffprobe': count_frames_ffprobe,
    'PyAV': count_frames_pyav,
    'MoviePy': count_frames_moviepy
}

times = {}

for method_name, method_function in methods.items():
    start_time = time.time()
    frame_count = method_function(video_path)
    end_time = time.time()
    times[method_name] = end_time - start_time
    print(
        f"{method_name}: Total frames = {frame_count}, Time taken = {times[method_name]:.2f} seconds")

# Plot the results
plt.figure(figsize=(10, 6))
bars = plt.bar(times.keys(), times.values(), color='skyblue')
plt.xlabel('Method')
plt.ylabel('Time (seconds)')
plt.title('Time Taken by Each Method to Count Frames')
plt.xticks(rotation=45, ha='right')

# Add time on each bar
for bar in bars:
    plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() +
             0.05, f'{bar.get_height():.2f}s', ha='center', va='bottom')

plt.tight_layout()
plt.show()

Output

Measuring execution time for each method

Here is the bar chart representing execution time:

Bar chart representing execution time for each method

The above chart is based on my analysis and the code run on my machine. Your result may vary depending on the size of the video and your current working system and its configuration.

As illustrated in the above bar chart, you can see that the fastest method is to use OpenCV’s CAP_PROP_FRAME_COUNT Property. The second fast is using the moviepy approach. If you are looking for accuracy then go for manual counting and if you are already editing videos, use the moviepy library.

Post Views: 88
Share on:
Krunal Lathiya

With a career spanning over eight years in the field of Computer Science, Krunal’s expertise is rooted in a solid foundation of hands-on experience, complemented by a continuous pursuit of knowledge.

How to Get the Duration of a Video in Python
Extracting an Audio from Video using Python

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Address: TwinStar, South Block – 1202, 150 Ft Ring Road, Nr. Nana Mauva Circle, Rajkot(360005), Gujarat, India

Call: (+91) 9409548155

Email: support@appdividend.com

Online Platform

  • Pricing
  • Instructors
  • FAQ
  • Refund Policy
  • Support

Links

  • About Us
  • Contact Us
  • Privacy Policy
  • Terms of services

Tutorials

  • Angular
  • React
  • Python
  • Laravel
  • Javascript
Copyright @2024 AppDividend. All Rights Reserved
Appdividend