Created
December 3, 2021 13:10
-
-
Save ashe23/c550900b391c2f50addfa480f00905c8 to your computer and use it in GitHub Desktop.
Create video from images [Updated]
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
| # 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