Skip to content

Instantly share code, notes, and snippets.

@dgwyer
Created June 26, 2025 08:35
Show Gist options
  • Save dgwyer/bfdcb8e7a2fd00e8d9edd08855419d60 to your computer and use it in GitHub Desktop.
Save dgwyer/bfdcb8e7a2fd00e8d9edd08855419d60 to your computer and use it in GitHub Desktop.
Extract the first frame of a 1280x720 video, convert it to an image, then crop and resize both the image and original video to 480x3680
import cv2
import os
from fractions import Fraction
import subprocess
# === Settings ===
video_file = 'videos/video.mp4'
output_image_file = 'first_frame_clipped.jpg'
output_image_resized_file = 'first_frame_resized.jpg'
output_video_file = 'clipped_video.mp4'
target_aspect = Fraction(4, 3)
# === Setup Paths ===
video_path = os.path.join(os.getcwd(), video_file)
print("Checking video path:", video_file)
print("Video file exists:", os.path.exists(video_path))
# === Load Video ===
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print("โŒ Failed to open video file.")
else:
success, frame = cap.read()
if success:
print("โœ… First frame captured successfully.")
height, width = frame.shape[:2]
aspect_fraction = Fraction(width, height).limit_denominator()
print(f"๐Ÿ“ Original Dimensions: {width} x {height}")
print(f"๐Ÿงฎ Original Aspect Ratio: {aspect_fraction.numerator}:{aspect_fraction.denominator}")
# === Calculate crop for 4:3 ===
target_width = (height * target_aspect.numerator) // target_aspect.denominator
print(f"โœ‚๏ธ Cropping to 4:3 โ†’ New width: {target_width}")
x_start = (width - target_width) // 2
x_end = x_start + target_width
cropped_frame = frame[:, x_start:x_end]
print(f"๐Ÿ“ธ Saved cropped frame as '{output_image_file}'")
cv2.imwrite(output_image_file, cropped_frame)
# === Resize image to half dimensions ===
resized_frame = cv2.resize(cropped_frame, (target_width // 2, height // 2), interpolation=cv2.INTER_AREA)
cv2.imwrite(output_image_resized_file, resized_frame)
print(f"๐Ÿ–ผ๏ธ Saved resized image as '{output_image_resized_file}' ({target_width // 2} x {height // 2})")
# === Crop and scale video using ffmpeg ===
ffmpeg_cmd = [
'ffmpeg',
'-y', # auto overwrite
'-i', video_path,
'-filter:v', f'crop={target_width}:{height},scale={target_width // 2}:{height // 2}',
'-c:a', 'copy',
output_video_file
]
print(f"๐ŸŽž๏ธ Cropping and downscaling video to {target_width // 2} x {height // 2}...")
result = subprocess.run(ffmpeg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode == 0:
print(f"โœ… Cropped and scaled video saved as '{output_video_file}'")
else:
print("โŒ ffmpeg error:")
print(result.stderr)
# === Show final sizes and aspect ratios ===
clipped_height, clipped_width = resized_frame.shape[:2]
clipped_aspect = Fraction(clipped_width, clipped_height).limit_denominator()
print(f"๐Ÿ–ผ๏ธ Final Image Size: {clipped_width} x {clipped_height}")
print(f"๐Ÿ”ฒ Final Image Aspect Ratio: {clipped_aspect.numerator}:{clipped_aspect.denominator}")
# === Confirm video size using ffprobe ===
ffprobe_cmd = [
'ffprobe', '-v', 'error',
'-select_streams', 'v:0',
'-show_entries', 'stream=width,height',
'-of', 'csv=p=0:s=x',
output_video_file
]
probe = subprocess.run(ffprobe_cmd, stdout=subprocess.PIPE, text=True)
if probe.returncode == 0:
vid_width, vid_height = map(int, probe.stdout.strip().split('x'))
vid_aspect = Fraction(vid_width, vid_height).limit_denominator()
print(f"๐ŸŽฌ Final Video Size: {vid_width} x {vid_height}")
print(f"๐ŸŽž๏ธ Final Video Aspect Ratio: {vid_aspect.numerator}:{vid_aspect.denominator}")
else:
print("โš ๏ธ Failed to get final video dimensions using ffprobe.")
else:
print("โŒ Failed to read the first frame.")
cap.release()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment