omermazig's picture
Tolerate fps difference of 5 for usage of original fps. This is because YouTube videos are commonly with 25 FPS and we're trying to work with 30 FPS
0cd2e7c
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()