Skip to content

Instantly share code, notes, and snippets.

@ashe23
Created December 3, 2021 13:10
Show Gist options
  • Select an option

  • Save ashe23/c550900b391c2f50addfa480f00905c8 to your computer and use it in GitHub Desktop.

Select an option

Save ashe23/c550900b391c2f50addfa480f00905c8 to your computer and use it in GitHub Desktop.
Create video from images [Updated]
# run methods
# py img_to_video.py --input inputdir --output outputdir --img_format fmt
# default input dir - current dir
# default output dir - current_dir/output
# default img_format - png
import os
import os.path
import glob
import argparse
import re
import subprocess
DEFAULT_INPUT_DIR = os.getcwd()
# DEFAULT_OUTPUT_DIR = DEFAULT_INPUT_DIR + "/output/"
# INPUT_DIR = ""
# OUTPUT_DIR = ""
# IMG_FORMAT = "png"
patterns = []
input_dir = ""
output_dir = ""
img_fmt = "png"
def dir_path(string):
if os.path.isdir(string):
return string
else:
raise NotADirectoryError(string)
def parse_cmd_args():
# todo:ashe23 add flag --clean , removes images after successful render
# todo:ashe23 add flag --video_fmt, video format format
# todo:ashe23 add flag --pattern, image sequence pattern search for and render only it
parser = argparse.ArgumentParser(description='Image sequences to video converter')
parser.add_argument('--in', type=dir_path, help='Input directory where look for images')
parser.add_argument('--out', type=dir_path, help='Output directory where final video will be placed')
parser.add_argument('--img_fmt', default='png', const='png', nargs='?', choices=['png', 'jpg'], help='Input image format(jpg|png)')
args = vars(parser.parse_args())
global input_dir
global output_dir
global img_fmt
if args['in'] == None:
input_dir = DEFAULT_INPUT_DIR
else:
input_dir = args['in']
DEFAULT_OUTPUT_DIR = input_dir + "/output/"
if args['out'] == None:
output_dir = DEFAULT_OUTPUT_DIR
else:
output_dir = args['out']
# creating output dir if not exists
if not os.path.exists(output_dir):
os.mkdir(output_dir)
img_fmt = args['img_fmt']
print("Input: {}".format(input_dir))
print("Output: {}".format(output_dir))
print("ImageFormat: {}".format(img_fmt))
def find_renderable_sequences():
os.chdir(input_dir)
for file in glob.glob("*." + img_fmt):
reg_expr = r'\d+.'+ img_fmt + '$'
pattern = re.sub(reg_expr, '', file)
if pattern not in patterns:
patterns.append(pattern)
def render(sequence_name):
mp4_settings = {
'input': 'ffmpeg -framerate 30 -i ' + sequence_name + '%04d.' + img_fmt,
'codec': '-c:v libx264',
'bitrate': '-b:v 5M -maxrate 5M -bufsize 100M',
'profile': '-profile:v high -level:v 5.2 -refs 4',
'color_range': '-colorspace:v "bt709" -color_primaries:v "bt709" -color_trc:v "bt709" -color_range:v "tv"',
'preset': '-preset fast',
'tune': '-tune animation',
'pixel_fmt': '-pix_fmt yuv420p',
'output': '-brand mp42 ' + sequence_name + '.mp4'
}
# render command
mp4_cmd = ' '.join(list(mp4_settings.values()))
res = subprocess.call(mp4_cmd, shell=True)
if res == False:
# move created .mp4 to its corresponding Point folder
fromPath = input_dir + '/' + sequence_name + '.mp4'
toPath = output_dir + '/' + pattern + '.mp4'
os.replace(fromPath, toPath)
# ===========
# ENTRY POINT
# ===========
parse_cmd_args()
find_renderable_sequences()
print(patterns)
for pattern in patterns:
render(pattern)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment