Pragthedon's picture
Initial backend API deployment
4f48a4e
import cv2
import numpy as np
from PIL import Image
from typing import List
import os
def extract_frames(video_path: str, num_frames: int = 10) -> List[Image.Image]:
"""
Extracts a fixed number of evenly spaced frames from a video file.
Args:
video_path: Path to the video file
num_frames: Number of frames to extract
Returns:
List of PIL Images extracted from the video
Raises:
ValueError: If video cannot be opened or is invalid
"""
if not os.path.exists(video_path):
raise FileNotFoundError(f"Video file not found: {video_path}")
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise ValueError(f"Could not open video file: {video_path}")
try:
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
if total_frames <= 0:
raise ValueError("Video contains no frames or duration cannot be determined")
# If video has fewer frames than requested, take all available frames
actual_num_frames = min(num_frames, total_frames)
# Calculate frame indices to extract (evenly spaced)
indices = np.linspace(0, total_frames - 1, actual_num_frames, dtype=int)
frames = []
for idx in indices:
# Set the frame position
cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
ret, frame = cap.read()
if ret:
# OpenCV returns BGR, convert to RGB for PIL
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(frame_rgb)
frames.append(pil_image)
else:
print(f"[Warning] Failed to read frame {idx} from {video_path}")
if not frames:
raise ValueError("Failed to extract any valid frames from the video")
return frames
finally:
cap.release()