Skip to content

Video

VideoInfo

A class to store video information, including width, height, fps and total number of frames.

Attributes:

Name Type Description
width int

width of the video in pixels

height int

height of the video in pixels

fps int

frames per second of the video

total_frames int

total number of frames in the video, default is None

Examples:

>>> import supervision as sv

>>> video_info = sv.VideoInfo.from_video_path(video_path='video.mp4')

>>> video_info
VideoInfo(width=3840, height=2160, fps=25, total_frames=538)

>>> video_info.resolution_wh
(3840, 2160)
Source code in supervision/utils/video.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@dataclass
class VideoInfo:
    """
    A class to store video information, including width, height, fps and total number of frames.

    Attributes:
        width (int): width of the video in pixels
        height (int): height of the video in pixels
        fps (int): frames per second of the video
        total_frames (int, optional): total number of frames in the video, default is None

    Examples:
        ```python
        >>> import supervision as sv

        >>> video_info = sv.VideoInfo.from_video_path(video_path='video.mp4')

        >>> video_info
        VideoInfo(width=3840, height=2160, fps=25, total_frames=538)

        >>> video_info.resolution_wh
        (3840, 2160)
        ```
    """

    width: int
    height: int
    fps: int
    total_frames: Optional[int] = None

    @classmethod
    def from_video_path(cls, video_path: str) -> VideoInfo:
        video = cv2.VideoCapture(video_path)
        if not video.isOpened():
            raise Exception(f"Could not open video at {video_path}")

        width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fps = int(video.get(cv2.CAP_PROP_FPS))
        total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
        video.release()
        return VideoInfo(width, height, fps, total_frames)

    @property
    def resolution_wh(self) -> Tuple[int, int]:
        return self.width, self.height

VideoSink

Context manager that saves video frames to a file using OpenCV.

Attributes:

Name Type Description
target_path str

The path to the output file where the video will be saved.

video_info VideoInfo

Information about the video resolution, fps, and total frame count.

Example
>>> import supervision as sv

>>> video_info = sv.VideoInfo.from_video_path(video_path='source_video.mp4')

>>> with sv.VideoSink(target_path='target_video.mp4', video_info=video_info) as sink:
...     for frame in get_video_frames_generator(source_path='source_video.mp4', stride=2):
...         sink.write_frame(frame=frame)
Source code in supervision/utils/video.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class VideoSink:
    """
    Context manager that saves video frames to a file using OpenCV.

    Attributes:
        target_path (str): The path to the output file where the video will be saved.
        video_info (VideoInfo): Information about the video resolution, fps, and total frame count.

    Example:
        ```python
        >>> import supervision as sv

        >>> video_info = sv.VideoInfo.from_video_path(video_path='source_video.mp4')

        >>> with sv.VideoSink(target_path='target_video.mp4', video_info=video_info) as sink:
        ...     for frame in get_video_frames_generator(source_path='source_video.mp4', stride=2):
        ...         sink.write_frame(frame=frame)
        ```
    """

    def __init__(self, target_path: str, video_info: VideoInfo):
        self.target_path = target_path
        self.video_info = video_info
        self.__fourcc = cv2.VideoWriter_fourcc(*"mp4v")
        self.__writer = None

    def __enter__(self):
        self.__writer = cv2.VideoWriter(
            self.target_path,
            self.__fourcc,
            self.video_info.fps,
            self.video_info.resolution_wh,
        )
        return self

    def write_frame(self, frame: np.ndarray):
        self.__writer.write(frame)

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.__writer.release()

get_video_frames_generator

Get a generator that yields the frames of the video.

Parameters:

Name Type Description Default
source_path str

The path of the video file.

required
stride int

Indicates the interval at which frames are returned, skipping stride - 1 frames between each.

1

Returns:

Type Description
Generator[ndarray, None, None]

A generator that yields the frames of the video.

Examples:

>>> import supervision as sv

>>> for frame in sv.get_video_frames_generator(source_path='source_video.mp4', stride=2):
...     ...
Source code in supervision/utils/video.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def get_video_frames_generator(
    source_path: str, stride: int = 1
) -> Generator[np.ndarray, None, None]:
    """
    Get a generator that yields the frames of the video.

    Args:
        source_path (str): The path of the video file.
        stride (int): Indicates the interval at which frames are returned, skipping stride - 1 frames between each.

    Returns:
        (Generator[np.ndarray, None, None]): A generator that yields the frames of the video.

    Examples:
        ```python
        >>> import supervision as sv

        >>> for frame in sv.get_video_frames_generator(source_path='source_video.mp4', stride=2):
        ...     ...
        ```
    """
    video = cv2.VideoCapture(source_path)
    if not video.isOpened():
        raise Exception(f"Could not open video at {source_path}")

    frame_count = 0
    success, frame = video.read()
    while success:
        if frame_count % stride == 0:
            yield frame
        success, frame = video.read()
        frame_count += 1

    video.release()

process_video

Process a video file by applying a callback function on each frame and saving the result to a target video file.

Parameters:

Name Type Description Default
source_path str

The path to the source video file.

required
target_path str

The path to the target video file.

required
callback Callable[[ndarray, int], ndarray]

A function that takes in a numpy ndarray representation of a video frame and an int index of the frame and returns a processed numpy ndarray representation of the frame.

required

Examples:

>>> from supervision import process_video

>>> def process_frame(scene: np.ndarray) -> np.ndarray:
...     ...

>>> process_video(
...     source_path='source_video.mp4',
...     target_path='target_video.mp4',
...     callback=process_frame
... )
Source code in supervision/utils/video.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
def process_video(
    source_path: str,
    target_path: str,
    callback: Callable[[np.ndarray, int], np.ndarray],
) -> None:
    """
    Process a video file by applying a callback function on each frame and saving the result to a target video file.

    Args:
        source_path (str): The path to the source video file.
        target_path (str): The path to the target video file.
        callback (Callable[[np.ndarray, int], np.ndarray]): A function that takes in a numpy ndarray representation of a video frame and an int index of the frame and returns a processed numpy ndarray representation of the frame.

    Examples:
        ```python
        >>> from supervision import process_video

        >>> def process_frame(scene: np.ndarray) -> np.ndarray:
        ...     ...

        >>> process_video(
        ...     source_path='source_video.mp4',
        ...     target_path='target_video.mp4',
        ...     callback=process_frame
        ... )
        ```
    """
    source_video_info = VideoInfo.from_video_path(video_path=source_path)
    with VideoSink(target_path=target_path, video_info=source_video_info) as sink:
        for index, frame in enumerate(
            get_video_frames_generator(source_path=source_path)
        ):
            result_frame = callback(frame, index)
            sink.write_frame(frame=result_frame)