1

I wanna grab 5 frames of a video distributed evenly including first and last frame. The answer to this helped me to loop over the video and get frames. However I didn't find out how to know when it's gonna be the last frame. Also looping over the whole video seems a bit expensive.

Python - Extracting and Saving Video Frames

Is there a better way of getting 5 specific frames (e.g. every 20% of the video) or at least and easy way of getting the total frame number? I already tried multiplying duration and fps from the metadata, but those numbers seem to be rounded and give a wrong number.

Thank you for your help.

JasonTS
  • 2,479
  • 4
  • 32
  • 48

1 Answers1

0

Whether or not this is possible depends on your container and codec being used. Assuming the codec allows retrieving the total number of frames, you can do something like this:

import imageio.v3 as iio
import numpy as np

my_video = "imageio:cockatoo.mp4"
props = iio.improps(my_video, plugin="pyav")

# Make sure the codec knows the number of frames
assert props.shape[0] != -1

for idx in np.linspace(0, props.shape[0]-1, 5, dtype=int):
    # imageIO < 2.21.0
    image = iio.imread(my_video, index=idx)
    # imageIO > 2.21.0
    # image = iio.imread(my_video, index=idx, plugin="pyav")
    iio.imwrite(f"delete_me/frame_{idx:03d}.png", image)

A few notes:

  • you want to use pyav for the call to iio.improps, because it doesn't decode frames, so it is fast.
  • some codecs or containers (especially when streaming video) either don't report or can't report the number of frames stored within. In this case props.shape[0] will be -1 and we can't use this method.
  • normally I'd recommend using pyav for the imread call as well, but there is a bug in the plugin that causes an EoF exception when trying to index= to the last frame. This will be fixed by #855, though I can't say if it will make it into this weekly release or the next.
  • if the codec used doesn't guarantee constant framerate, you won't get any speed advantages over iio.imiter because we can't safely predict how far into the video to seek. If you know that your video has a constant framerate, however, you can use the constant_framerate kwarg of the pyav plugin to speed things up. (IMPORTANT: if the video has variable framerate and you set this anyway the seek will not be accurate.)
  • As usual, you can use iio.imopen if you want to do all of these operations without reopening the video each time.
FirefoxMetzger
  • 2,880
  • 1
  • 18
  • 32