import shutil from typing import Optional, Tuple import cv2 def change_video_resolution_and_fps(video_path: str, output_path: str, new_resolution: Optional[Tuple[int, int]] = None, new_fps: Optional[int] = None, acceptable_fps_violation: int = 0) -> bool: cap = cv2.VideoCapture(video_path) try: original_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) original_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) resolution = (original_width, original_height) fps = int(cap.get(cv2.CAP_PROP_FPS)) # Specify the new_resolution and new_fps for the cut video new_resolution = new_resolution if new_resolution else resolution new_fps = fps if ((not new_fps) or (abs(new_fps - fps) <= acceptable_fps_violation)) else new_fps fps_decrease_factor = fps / new_fps if not fps_decrease_factor.is_integer(): raise ValueError(f"New fps ({new_fps}) must be a divisor of the current fps ({fps})") if fps == new_fps and (original_width, original_height) == new_resolution: shutil.copy(video_path, output_path) return True current_frame = 0 # Read first frame ret, frame = cap.read() if not ret: # Video has ended, without us recording anything return False # Initialize the video writer to save the cut video fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter(output_path, fourcc, new_fps, new_resolution, isColor=True) new_video_current_frame = 0 while ret: if current_frame % fps_decrease_factor == 0: if resolution != new_resolution: # Resize the frame to the desired new_resolution before writing it frame = cv2.resize(frame, new_resolution, interpolation=cv2.INTER_AREA) # Write the frame to the cut video out.write(frame) new_video_current_frame += 1 current_frame += 1 # Read next frame ret, frame = cap.read() # We're done recording out.release() return new_video_current_frame > 0 finally: # Release the video capture and close all windows cap.release()