-
-
Save pgtwitter/02c3d7257e12c5ccbede755981f4623f to your computer and use it in GitHub Desktop.
動画中の描画領域を特定して,Cropした動画を作成,その後,そのCropした動画を縦長(1080x1920)サイズ中にセンタリングして配置した動画を作成する.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # %% | |
| 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