I'm trying to extract all the frames from a particular time frame in Python. For example, I want to take the frames of a video from start_time = 3.25
to end_time = 5.5
. Let's assume the fps of the video is 60. How would I do that?
Very loose code of what I'm thinking of doing:
video = load_video(my_video_path)
fps = 60
start_frame = 3.25 * fps
end_frame = 5.5 * fps
sliced_video = video[start_frame:end_frame]
Not sure what the correct libraries and methodology is to do the following?
You can use PyAV for this. Install with
pip install av
(or pip3, whatever your operating system requires pip to be called)
Then use this code:
import numpy as np
import av
my_video_path = ...
start_time = 3.25
end_time = 5.5
container = av.open(my_video_path)
duration = container.duration * (1 / av.time_base)
print(f"Video duration: {duration:.3f} seconds")
# sanity checks
assert start_time < end_time, "Start time beyond end time"
assert end_time <= duration, "End time beyond file duration"
stream = container.streams.video[0]
# seek
print(f"Seeking to {start_time:.2f} seconds or earlier")
container.seek(
int(start_time / stream.time_base),
stream=stream)
# decode
frames = []
for frame in container.decode(stream):
assert frame.time == float(frame.pts * stream.time_base)
if frame.time > end_time:
print(f"Frame at {frame.time:.2f} seconds -- after end time, stopping")
break
elif frame.time < start_time:
print(f"Frame at {frame.time:.2f} seconds -- before start time, skipping")
continue
else:
print(f"Frame at {frame.time:.3f} seconds")
frame_bgr24 = frame.to_ndarray(format='bgr24')
frames.append(frame_bgr24)
print("Collected", len(frames), "frames")
Video duration: 30.711 seconds
Seeking to 3.250 seconds or earlier
Frame at 3.230 seconds -- before start time, skipping
Frame at 3.246 seconds -- before start time, skipping
Frame at 3.283 seconds
Frame at 3.329 seconds
Frame at 3.347 seconds
...
Frame at 5.349 seconds
Frame at 5.412 seconds
Frame at 5.451 seconds
Frame at 5.512 seconds -- after end time, stopping
Collected 65 frames