Skip to content

Instantly share code, notes, and snippets.

@pgtwitter
Created May 4, 2026 02:14
Show Gist options
  • Select an option

  • Save pgtwitter/02c3d7257e12c5ccbede755981f4623f to your computer and use it in GitHub Desktop.

Select an option

Save pgtwitter/02c3d7257e12c5ccbede755981f4623f to your computer and use it in GitHub Desktop.
動画中の描画領域を特定して,Cropした動画を作成,その後,そのCropした動画を縦長(1080x1920)サイズ中にセンタリングして配置した動画を作成する.
# %%
import cv2
import numpy as np
# ffmpeg -i input.mov -c copy input.mp4
cap = cv2.VideoCapture('input.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_cropped.mp4', fourcc, fps, (0, 0)) # 後でサイズ更新
padding = 10 # 少し余白を持たせる(ピクセル)
min_x, min_y, max_x, max_y = width, height, 0, 0
frames = []
while True:
ret, frame = cap.read()
if not ret:
break
# 白背景以外をマスク(RGBすべて255に近いものを除外)
threshold = 250
mask = cv2.inRange(frame, (0, 0, 0), (threshold, threshold, threshold)) # 白を黒に
# 輪郭検出
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
# すべての輪郭を囲む最小矩形
x, y, w, h = cv2.boundingRect(np.concatenate(contours))
min_x = min(min_x, x)
min_y = min(min_y, y)
max_x = max(max_x, x + w)
max_y = max(max_y, y + h)
frames.append(frame)
cap.release()
# 全体の最小矩形 + padding
crop_x = max(0, min_x - padding)
crop_y = max(0, min_y - padding)
crop_w = min(width - crop_x, max_x - min_x + 2*padding)
crop_h = min(height - crop_y, max_y - min_y + 2*padding)
# 再エンコード
out = cv2.VideoWriter('output_cropped.mp4', fourcc, fps, (crop_w, crop_h))
for frame in frames:
cropped = frame[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w]
out.write(cropped)
out.release()
print(f"Cropped to: {crop_w}x{crop_h} at offset ({crop_x}, {crop_y})")
# %%
# FFmpeg一発版(参考)
# ffmpeg -i output_cropped.mp4 -vf "scale=1080:-1,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=black" -c:v libx264 -crf 18 output_shorts.mp4
# ffmpeg -i output_cropped.mp4 -vf "scale=1080:-1,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=white" -c:v libx264 -crf 18 output_shorts.mp4
# ====================== Shorts用に上下余白追加 ======================
target_width = 1080
target_height = 1920
cap = cv2.VideoCapture('output_cropped.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out_shorts = cv2.VideoWriter('output_shorts_py.mp4', fourcc, fps, (target_width, target_height))
while True:
ret, frame = cap.read()
if not ret:
break
h, w = frame.shape[:2] # 現在のフレームサイズ(1720x1288など)
# 横幅を1080にスケール(アスペクト比を維持)
scale = target_width / w
new_h = int(h * scale)
resized = cv2.resize(frame, (target_width, new_h))
# 黒背景(上下余白)のキャンバス作成
# canvas = np.zeros((target_height, target_width, 3), dtype=np.uint8) # 黒背景
# 白背景にしたい場合は → np.full((target_height, target_width, 3), 255, dtype=np.uint8)
canvas = np.full((target_height, target_width, 3), 255, dtype=np.uint8)
# 中央に配置
y_offset = (target_height - new_h) // 2
canvas[y_offset:y_offset+new_h, 0:target_width] = resized
out_shorts.write(canvas)
cap.release()
out_shorts.release()
print("縦長動画を作成しました: output_shorts_py.mp4")
# %%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment