ffmpeg is an excellent tool for video processing. However, using ffmpeg directly inside Python is not convenient enough. Previously, I have been using ffmpeg-python, which is a thin wrapper around the ffmpeg command line executable.

The main issue with ffmpeg-python is its slow speed in performance-critical applications, due to its nature as a simple wrapper package.

The PyAV is a more performant package providing ffmpeg library bindings1.

To install PyAV, run the following command:

pip install av

Simple use case: extract frame every one second

Here is a code snippet for how to extract video frames every one second:

import os

import av

out_dir = "demo"
if not os.path.exist(out_dir):

fpath = "test.mp4"
container = av.open(fpath)

# take first video stream
stream = container.streams.video[0]

# get video fps
average_fps = int(stream.average_rate)

for idx, frame in enumerate(container.decode(stream)):
    if idx % average_fps != 0:


In the code snippet, we create a container, which contains all video and audio streams in the video.

We then use container.streams.video[0] to get the video stream. container.decode() is used to decode the stream into frames.

Since videos may have variable fps, there are actually several frame rates. stream.average_rate is the average fps for video, and it works fine in our case. However, it is not a native type, we need to convert it to float or int before usage.

Some of the other important information of a stream:

  • video duration in seconds: float(stream.duration * stream.time_base)
  • video frame number: stream.frames
  • frame width and height: frame.width, frame.height


  1. It works by invoking the ffmpeg libraries directly, instead of using ffmpeg executable. ↩︎