Search code examples
pythonopencvvideo-processing

How can I extract all the frames from a particular time interval in a video?


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?


Solution

  • 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