How to Create a Reusable Independent Video Reader Class
Description: Learn how to create a reusable VideoReader service in Python using OpenCV to read video files frame-by-frame and access FPS, frame count, width, and height.
In the previous part, we looked at how to get basic video file metadata using OpenCV.
As video-processing applications become more complex, directly using cv2.VideoCapture throughout your application can make the code harder to maintain and reuse.
A better approach is to create a small, reusable service class that handles video reading in one place.
In this part, we will create a VideoReader class that can:
- Open and validate a video file
- Read video frames one by one
- Get the video FPS
- Get the total frame count
- Get the video width and height
- Release the video resource properly
Create a Reusable VideoReader
We can create a simple VideoReader service using OpenCV, pathlib, Python type hints, and NumPy.
"""
Helper video reader functions
Service layer for reading video files frame-by-frame using OpenCV.
"""
from pathlib import Path
from urllib.parse import urlparse
from typing import Generator
import cv2
import numpy as np
class VideoReader:
def __init__(self, video_path: str):
"""
compatible with local files and URLs
"""
self.video_path = video_path
parsed = urlparse(video_path)
is_url = parsed.scheme in ("http", "https")
if not is_url:
path = Path(video_path)
if not path.exists():
raise FileNotFoundError(video_path)
self.cap = cv2.VideoCapture(video_path)
if not self.cap.isOpened():
raise RuntimeError(f"Unable to open video: {video_path}")
@property
def fps(self) -> float:
return self.cap.get(cv2.CAP_PROP_FPS)
@property
def frame_count(self) -> int:
return int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
@property
def width(self) -> int:
return int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
@property
def height(self) -> int:
return int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
def frames(self) -> Generator[tuple[int, np.ndarray], None, None]:
"""
Yield:
frame_index,
frame (numpy array)
"""
frame_index = 0
while True:
success, frame = self.cap.read()
if not success:
break
yield frame_index, frame
frame_index += 1
def release(self):
self.cap.release()
here we first check it is url or not, then checking whether the file exists or not, if not then prevents the application from trying to open a file that does not exist. after that we verify that OpenCV successfully opened the video. This is important because a file can exist but still be unsupported, corrupted, or inaccessible.
let’s wait for next part.
