OpenCV's VideoCapture is broken and hasn't been fixed for the last 5 years: opencv/opencv#9053
This is a PyAV based replacement. Unlike other implementations it can seek at any time.
How to use:
reader = VideoReader('video.mp4')
reader.seek(reader.total_frames - 100) # frame number
while True:
frame = reader.read()
if not frame:
break
# frame is an ndarray - do something with it
print(f'frame {reader.position}: {frame}')
reader.close()
Thanks for this @Eugeny and also @whizmo for your modifications. I've used this to make a version that just allows you to request frames directly without thinking about the current state of the reader. E.g.
It should be fast when frames are requested in sequence, or when the requested frame was requested recently
Gist: https://gist.github.com/petered/db8e334c7aefdf367af1b11e6eefe733