Last active
April 2, 2022 13:12
-
-
Save oshinko/7d7d9b508f5d6137d112e34fe62f2d99 to your computer and use it in GitHub Desktop.
Convert images to mp4
This file contains 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 pathlib | |
import subprocess | |
try: | |
import cv2 | |
except ModuleNotFoundError: | |
import sys | |
subprocess.run(f'{sys.executable} -m pip install opencv-python', | |
shell=True) | |
import cv2 | |
finally: | |
import numpy as np | |
# とりあえず固定 | |
VIDEO_FILE = 'video.mp4' | |
VIDEO_WIDTH = 1280 | |
VIDEO_HEIGHT = 720 | |
VIDEO_DURATION = 20 | |
VIDEO_FPS = 20 | |
def iterimgs(): | |
path = pathlib.Path.cwd() # 引数で渡しても良いかも | |
for x in sorted(path.iterdir()): | |
if x.suffix in ['.jpg', '.png']: | |
if x.is_absolute(): | |
# 日本語が含まれるパスだと cv2.imread に失敗するので、 | |
# なるべく回避できるように相対パスに変換している。 | |
x = x.relative_to(pathlib.Path.cwd()) | |
yield cv2.imread(str(x)) | |
vf = pathlib.Path(VIDEO_FILE) # 引数で渡しても良いかも | |
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') | |
n_imgs = len(list(iterimgs())) | |
n_dups = int(VIDEO_DURATION * VIDEO_FPS / n_imgs) | |
def iterfrms(): | |
for img in iterimgs(): | |
for _ in range(n_dups): | |
yield img | |
# iterimgs で全画像の大きさを取ってから設定しても良いかも | |
vw, vh = VIDEO_WIDTH, VIDEO_HEIGHT | |
video = cv2.VideoWriter(str(vf), fourcc, VIDEO_FPS, (vw, vh)) | |
if not video.isOpened(): | |
print(f"can't open {vf}") | |
exit() | |
for img in iterfrms(): | |
# 動画サイズに合わせて画像をリサイズ | |
h, w = img.shape[:2] | |
scale = min(vw / w, vh / h) | |
img = cv2.resize(img, (int(w * scale), int(h * scale))) | |
h, w = img.shape[:2] | |
# キャンバス (最終的にフレームとなる) | |
cvs = cv2.resize(np.zeros((1, 1, 3), np.uint8), (vw, vh)) | |
# 貼り付け | |
wpad = int((vw - w) / 2) | |
wpad_lmt = w + wpad | |
hpad = int((vh - h) / 2) | |
hpad_lmt = h + hpad | |
cvs[hpad:hpad_lmt, wpad:wpad_lmt] = img | |
# 書き込み | |
video.write(cvs) | |
video.release() | |
# ffmpeg があれば H.264 に変換 | |
try: | |
tmp = pathlib.Path('tmp').with_suffix(vf.suffix) | |
subprocess.run(f'ffmpeg -i {vf} -vcodec libx264 {tmp}', shell=True) | |
except FileNotFoundError: | |
pass | |
else: | |
print('converted to H.264 using ffmpeg') | |
vf.write_bytes(tmp.read_bytes()) | |
tmp.unlink() | |
print('written') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment