Source code for HMB.VideosHelper

import cv2
import numpy as np


[docs] class VideosHelper(object): r''' VideosHelper: Helpers for common video operations using OpenCV. Methods provided: - ReadVideo(videoPath) - WriteVideo(videoPath, frames, fps, frameSize, fourccType="mp4v") - ShowVideo(video, frameIndex) - ShowVideoFrames(video, frameIndexRange) - GetVideoFrames(video) - GetVideoFramesCount(video) - GetVideoFPS(video) - GetVideoFrameSize(video) - GetVideoFrameSizeString(video) - GetVideoDuration(video) - GetVideoFrame(video, frameIndex) - GetVideoFrameTime(video, frameIndex) - GetVideoFrameIndex(video, frameTime) - GetVideoFrameIndexRange(video, frameTimeRange) - GetVideoFrameTimeRange(video, frameIndexRange) - GetVideoFrameRange(video, frameIndexRange) '''
[docs] def ReadVideo(self, videoPath): r''' Open a video file and return a cv2.VideoCapture object. Parameters: videoPath (str): Path to the video file. Returns: cv2.VideoCapture: Opened video capture object. ''' video = cv2.VideoCapture(videoPath) return video
[docs] def WriteVideo(self, videoPath, frames, fps, frameSize, fourccType="mp4v"): r''' Write a sequence of frames to a video file. Parameters: videoPath (str): Output path for the video file. frames (Iterable): Sequence of frames (NumPy arrays) to write. fps (float): Frames per second. frameSize (tuple): (width, height) of the frames. fourccType (str): FourCC codec string (default "mp4v"). ''' # fourccType can be: DIVX, XVID, MJPG, X264, WMV1, WMV2, I420. fourcc = cv2.VideoWriter_fourcc(*fourccType) video = cv2.VideoWriter(videoPath, fourcc, fps, frameSize) for frame in frames: video.write(frame) video.release()
[docs] def ShowVideo(self, video, frameIndex): r''' Display a single frame from a video using OpenCV GUI (blocking until a key press). Parameters: video (cv2.VideoCapture): Video capture object. frameIndex (int): Index of the frame to display. ''' frame = self.GetVideoFrame(video, frameIndex) cv2.imshow("Frame", frame) cv2.waitKey(0) cv2.destroyAllWindows()
[docs] def ShowVideoFrames(self, video, frameIndexRange): r''' Display multiple frames by index range. Parameters: video (cv2.VideoCapture): Video capture object. frameIndexRange (Iterable): Iterable of frame indices to display. ''' for frameIndex in frameIndexRange: self.ShowVideo(video, frameIndex)
[docs] def GetVideoFrames(self, video): r''' Read all frames from an opened `cv2.VideoCapture` into a list. Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: list: List of frames as NumPy arrays. ''' frames = [] while (True): success, frame = video.read() if (not success): break frames.append(frame) return frames
[docs] def GetVideoFramesCount(self, video): r''' Get the total frame count of a video. Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: int: Total number of frames (may be 0 for some live streams). ''' framesCount = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) return framesCount
[docs] def GetVideoFPS(self, video): r''' Return the frames-per-second (FPS) rate for the video. Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: float: FPS value. ''' fps = video.get(cv2.CAP_PROP_FPS) return fps
[docs] def GetVideoFrameSize(self, video): r''' Get the video frame size as (width, height). Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: tuple: (width, height) in pixels. ''' width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) return (width, height)
[docs] def GetVideoFrameSizeString(self, video): r''' Return a human-readable frame size string like "640x480". Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: str: Frame size string. ''' (width, height) = self.GetVideoFrameSize(video) frameSizeString = str(width) + "x" + str(height) return frameSizeString
[docs] def GetVideoDuration(self, video): r''' Estimate video duration in seconds using frame count and fps. Parameters: video (cv2.VideoCapture): Opened video capture object. Returns: float: Duration in seconds. ''' framesCount = self.GetVideoFramesCount(video) fps = self.GetVideoFPS(video) duration = framesCount / fps return duration
[docs] def GetVideoFrame(self, video, frameIndex): r''' Retrieve a specific frame by index from an opened video. Parameters: video (cv2.VideoCapture): Opened video capture object. frameIndex (int): Frame index. Returns: numpy.ndarray: Frame image array (BGR color by OpenCV convention). ''' video.set(cv2.CAP_PROP_POS_FRAMES, frameIndex) success, frame = video.read() return frame
[docs] def GetVideoFrameTime(self, video, frameIndex): r''' Convert a frame index to its timestamp (in seconds) using FPS. Parameters: video (cv2.VideoCapture): Opened video capture object. frameIndex (int): Frame index. Returns: float: Timestamp in seconds. ''' fps = self.GetVideoFPS(video) frameTime = frameIndex / fps return frameTime
[docs] def GetVideoFrameIndex(self, video, frameTime): r''' Convert a timestamp (seconds) to a fractional frame index. Parameters: video (cv2.VideoCapture): Opened video capture object. frameTime (float): Timestamp in seconds. Returns: float: Frame index (may be fractional). ''' fps = self.GetVideoFPS(video) frameIndex = frameTime * fps return frameIndex
[docs] def GetVideoFrameIndexRange(self, video, frameTimeRange): r''' Convert a list/iterable of timestamps to frame indices. Parameters: video (cv2.VideoCapture): Opened video capture object. frameTimeRange (Iterable): Iterable of timestamps in seconds. Returns: list: List of frame indices (may be fractional). ''' fps = self.GetVideoFPS(video) frameIndexRange = [frameTime * fps for frameTime in frameTimeRange] return frameIndexRange
[docs] def GetVideoFrameTimeRange(self, video, frameIndexRange): r''' Convert a list/iterable of frame indices to timestamps. Parameters: video (cv2.VideoCapture): Opened video capture object. frameIndexRange (Iterable): Iterable of frame indices. Returns: list: List of timestamps in seconds. ''' fps = self.GetVideoFPS(video) frameTimeRange = [frameIndex / fps for frameIndex in frameIndexRange] return frameTimeRange
[docs] def GetVideoFrameRange(self, video, frameIndexRange): r''' Retrieve multiple frames by their indices and return them as a list. Parameters: video (cv2.VideoCapture): Opened video capture object. frameIndexRange (Iterable): Iterable of frame indices. Returns: list: List of frames as NumPy arrays. ''' frames = [] for frameIndex in frameIndexRange: frame = self.GetVideoFrame(video, frameIndex) frames.append(frame) return frames
if __name__ == "__main__": # SafeCall helper used to call methods and gracefully report failures. def SafeCall(name, fn, *args, **kwargs): try: res = fn(*args, **kwargs) print(f"{name} ->", res) print("-" * 40) return res except Exception as e: print(f"{name} raised {type(e).__name__}:", e) print("-" * 40) return None # Lightweight MockVideo to avoid depending on actual cv2.VideoCapture for demos. class MockVideo: def __init__(self, frames, fps=30.0): self._frames = list(frames) self._fps = float(fps) self._pos = 0 def read(self): if self._pos < len(self._frames): f = self._frames[self._pos] self._pos += 1 return True, f return False, None def set(self, prop, value): # Only support setting frame position if prop == 1 or getattr(prop, "name", None) == "CAP_PROP_POS_FRAMES": try: self._pos = int(value) except Exception: self._pos = 0 def get(self, prop): # Map common CAP_PROP_* codes that OpenCV uses; use numeric constants if available. # We will accept integer codes for CAP_PROP_FRAME_COUNT=7, CAP_PROP_FPS=5, CAP_PROP_FRAME_WIDTH=3, CAP_PROP_FRAME_HEIGHT=4 try: code = int(prop) except Exception: code = None # Common OpenCV property codes if (code == 7): # CAP_PROP_FRAME_COUNT return len(self._frames) if (code == 5): # CAP_PROP_FPS return self._fps if (code == 3): # CAP_PROP_FRAME_WIDTH # Assume frames are numpy arrays HxWxC. if (len(self._frames) > 0): return self._frames[0].shape[1] return 0 if (code == 4): # CAP_PROP_FRAME_HEIGHT if (len(self._frames) > 0): return self._frames[0].shape[0] return 0 # Fallback. return 0 vh = VideosHelper() # Create a few dummy frames (small RGB images) frames = [np.zeros((10, 16, 3), dtype=np.uint8) + i for i in range(3)] mock = MockVideo(frames, fps=10.0) SafeCall("GetVideoFramesCount", vh.GetVideoFramesCount, mock) SafeCall("GetVideoFPS", vh.GetVideoFPS, mock) SafeCall("GetVideoFrameSize", vh.GetVideoFrameSize, mock) SafeCall("GetVideoFrameSizeString", vh.GetVideoFrameSizeString, mock) SafeCall("GetVideoDuration", vh.GetVideoDuration, mock) SafeCall("GetVideoFrame", vh.GetVideoFrame, mock, 1) SafeCall("GetVideoFrameTime", vh.GetVideoFrameTime, mock, 2) SafeCall("GetVideoFrameIndex", vh.GetVideoFrameIndex, mock, 0.5) SafeCall("GetVideoFrameIndexRange", vh.GetVideoFrameIndexRange, mock, [0.0, 0.5, 1.0]) SafeCall("GetVideoFrameTimeRange", vh.GetVideoFrameTimeRange, mock, [0, 1, 2]) SafeCall("GetVideoFrameRange", vh.GetVideoFrameRange, mock, [0, 1]) # GetVideoFrames: will exhaust the mock read cursor; create a fresh mock to test. mock2 = MockVideo(frames, fps=10.0) SafeCall("GetVideoFrames", vh.GetVideoFrames, mock2) # Attempt to call WriteVideo (may require cv2.VideoWriter and filesystem access) - guarded. try: SafeCall("WriteVideo (to /tmp/test.mp4)", vh.WriteVideo, "hmb_test_video.mp4", frames, 10.0, (16, 10), "mp4v") except Exception as e: print("WriteVideo skipped:", type(e).__name__, e) print("VideosHelper demo completed.")