import json import os import tempfile import time from types import SimpleNamespace import modules.paths as ph import modules.shared as sh from modules.processing import get_fixed_seed from modules.shared import cmd_opts from .defaults import get_guided_imgs_default_json from .deforum_controlnet import controlnet_component_names from .general_utils import get_os, substitute_placeholders def RootArgs(): return { "device": sh.device, "models_path": ph.models_path + '/Deforum', "half_precision": not cmd_opts.no_half, "mask_preset_names": ['everywhere', 'video_mask'], "frames_cache": [], "raw_batch_name": None, "raw_seed": None, "initial_info": None, "first_frame": None, "animation_prompts": None, "current_user_os": get_os(), "tmp_deforum_run_duplicated_folder": os.path.join(tempfile.gettempdir(), 'tmp_run_deforum') } def CoreArgs(): # TODO: change or do something with this ugliness return { "subseed": -1, "subseed_strength": 0, "timestring": "", "init_sample": None, "noise_mask": None, "seed_internal": 0 } def DeforumAnimArgs(): return { "animation_mode": '2D', # ['None', '2D', '3D', 'Video Input', 'Interpolation'] "max_frames": 120, "border": 'replicate', # ['wrap', 'replicate'] "angle": "0:(0)", "zoom": "0:(1.0025+0.002*sin(1.25*3.14*t/30))", "translation_x": "0:(0)", "translation_y": "0:(0)", "translation_z": "0:(1.75)", "transform_center_x": "0:(0.5)", "transform_center_y": "0:(0.5)", "rotation_3d_x": "0:(0)", "rotation_3d_y": "0:(0)", "rotation_3d_z": "0:(0)", "enable_perspective_flip": False, "perspective_flip_theta": "0:(0)", "perspective_flip_phi": "0:(0)", "perspective_flip_gamma": "0:(0)", "perspective_flip_fv": "0:(53)", "noise_schedule": "0: (0.065)", "strength_schedule": "0: (0.65)", "contrast_schedule": "0: (1.0)", "cfg_scale_schedule": "0: (7)", "enable_steps_scheduling": False, "steps_schedule": "0: (25)", "fov_schedule": "0: (70)", "aspect_ratio_schedule": "0: (1)", "aspect_ratio_use_old_formula": False, "near_schedule": "0: (200)", "far_schedule": "0: (10000)", "seed_schedule": '0:(s), 1:(-1), "max_f-2":(-1), "max_f-1":(s)', "pix2pix_img_cfg_scale_schedule": "0:(1.5)", "enable_subseed_scheduling": False, "subseed_schedule": "0:(1)", "subseed_strength_schedule": "0:(0)", "enable_sampler_scheduling": False, # Sampler Scheduling "sampler_schedule": '0: ("Euler a")', "use_noise_mask": False, # Composable mask scheduling "mask_schedule": '0: ("{video_mask}")', "noise_mask_schedule": '0: ("{video_mask}")', "enable_checkpoint_scheduling": False, # Checkpoint Scheduling "checkpoint_schedule": '0: ("model1.ckpt"), 100: ("model2.safetensors")', "enable_clipskip_scheduling": False, # CLIP skip Scheduling "clipskip_schedule": '0: (2)', "enable_noise_multiplier_scheduling": True, # Noise Multiplier Scheduling "noise_multiplier_schedule": '0: (1.05)', # resume params "resume_from_timestring": False, "resume_timestring": "20230129210106", # DDIM AND Ancestral ETA scheds "enable_ddim_eta_scheduling": False, "ddim_eta_schedule": "0:(0)", "enable_ancestral_eta_scheduling": False, "ancestral_eta_schedule": "0:(1)", # Anti-blur "amount_schedule": "0: (0.1)", "kernel_schedule": "0: (5)", "sigma_schedule": "0: (1.0)", "threshold_schedule": "0: (0.0)", # Coherence "color_coherence": 'LAB', # ['None', 'HSV', 'LAB', 'RGB', 'Video Input', 'Image'] "color_coherence_image_path": "", "color_coherence_video_every_N_frames": 1, "color_force_grayscale": False, "legacy_colormatch": False, "diffusion_cadence": '2', # ['1','2','3','4','5','6','7','8'] "optical_flow_cadence": 'None', # ['None', 'RAFT','DIS Medium', 'DIS Fine', 'Farneback'] "cadence_flow_factor_schedule": "0: (1)", "optical_flow_redo_generation": 'None', # ['None', 'RAFT', 'DIS Medium', 'DIS Fine', 'Farneback'] "redo_flow_factor_schedule": "0: (1)", "diffusion_redo": '0', # **Noise settings:** "noise_type": 'perlin', # ['uniform', 'perlin'] # Perlin params "perlin_w": 8, "perlin_h": 8, "perlin_octaves": 4, "perlin_persistence": 0.5, # **3D Depth Warping:** "use_depth_warping": True, "depth_algorithm": 'Midas-3-Hybrid', # ['Midas+AdaBins (old)','Zoe+AdaBins (old)', 'Midas-3-Hybrid','Midas-3.1-BeitLarge', 'AdaBins', 'Zoe', 'Leres'] Midas-3.1-BeitLarge is temporarily removed 04-05-23 until fixed "midas_weight": 0.2, # midas/ zoe weight - only relevant in old/ legacy depth_algorithm modes. see above ^ "padding_mode": 'border', # ['border', 'reflection', 'zeros'] "sampling_mode": 'bicubic', # ['bicubic', 'bilinear', 'nearest'] "save_depth_maps": False, # **Video Input:** "video_init_path": 'https://deforum.github.io/a1/V1.mp4', "extract_nth_frame": 1, "extract_from_frame": 0, "extract_to_frame": -1, # minus 1 for unlimited frames "overwrite_extracted_frames": True, "use_mask_video": False, "video_mask_path": 'https://deforum.github.io/a1/VM1.mp4', # **Hybrid Video for 2D/3D Animation Mode:** "hybrid_comp_alpha_schedule": "0:(0.5)", "hybrid_comp_mask_blend_alpha_schedule": "0:(0.5)", "hybrid_comp_mask_contrast_schedule": "0:(1)", "hybrid_comp_mask_auto_contrast_cutoff_high_schedule": "0:(100)", "hybrid_comp_mask_auto_contrast_cutoff_low_schedule": "0:(0)", "hybrid_flow_factor_schedule": "0:(1)", "hybrid_generate_inputframes": False, "hybrid_generate_human_masks": "None", # ['None','PNGs','Video', 'Both'] "hybrid_use_first_frame_as_init_image": True, "hybrid_motion": "None", # ['None','Optical Flow','Perspective','Affine'] "hybrid_motion_use_prev_img": False, "hybrid_flow_consistency": False, "hybrid_consistency_blur": 2, "hybrid_flow_method": "RAFT", # ['RAFT', 'DIS Medium', 'DIS Fine', 'Farneback'] "hybrid_composite": 'None', # ['None', 'Normal', 'Before Motion', 'After Generation'] "hybrid_use_init_image": False, "hybrid_comp_mask_type": "None", # ['None', 'Depth', 'Video Depth', 'Blend', 'Difference'] "hybrid_comp_mask_inverse": False, "hybrid_comp_mask_equalize": "None", # ['None','Before','After','Both'] "hybrid_comp_mask_auto_contrast": False, "hybrid_comp_save_extra_frames": False } def DeforumArgs(): return { "W": 512, # width "H": 512, # height # whether to show gradio's info section for all params in the ui. it's a realtime toggle "show_info_on_ui": True, # **Webui stuff** "tiling": False, "restore_faces": False, "seed_enable_extras": False, "seed_resize_from_w": 0, "seed_resize_from_h": 0, # **Sampling Settings** "seed": -1, "sampler": 'euler_ancestral', "steps": 25, # **Batch Settings** "batch_name": "Deforum_{timestring}", "seed_behavior": "iter", "seed_iter_N": 1, # **Init Settings** "use_init": False, "strength": 0.8, "strength_0_no_init": True, "init_image": "https://deforum.github.io/a1/I1.png", # Whiter areas of the mask are areas that change more "use_mask": False, "use_alpha_as_mask": False, "mask_file": "https://deforum.github.io/a1/M1.jpg", "invert_mask": False, # Adjust mask image, 1.0 is no adjustment. Should be positive numbers. "mask_contrast_adjust": 1.0, "mask_brightness_adjust": 1.0, # Overlay the masked image at the end of the generation so it does not get degraded by encoding and decoding "overlay_mask": True, # Blur edges of final overlay mask, if used. Minimum = 0 (no blur) "mask_overlay_blur": 4, "fill": 1, "full_res_mask": True, "full_res_mask_padding": 4, "reroll_blank_frames": 'reroll', "reroll_patience": 10 } def LoopArgs(): return { "use_looper": False, "init_images": get_guided_imgs_default_json(), "image_strength_schedule": "0:(0.75)", "blendFactorMax": "0:(0.35)", "blendFactorSlope": "0:(0.25)", "tweening_frames_schedule": "0:(20)", "color_correction_factor": "0:(0.075)" } def ParseqArgs(): return { "parseq_manifest": None, "parseq_use_deltas": True } def DeforumOutputArgs(): return { "skip_video_creation": False, "fps": 15, "make_gif": False, "delete_imgs": False, # True will delete all imgs after a successful mp4 creation "image_path": "C:/SD/20230124234916_%09d.png", "add_soundtrack": 'None', # ["File","Init Video"] "soundtrack_path": "https://deforum.github.io/a1/A1.mp3", # End-Run upscaling "r_upscale_video": False, "r_upscale_factor": 'x2', # ['2x', 'x3', 'x4'], "r_upscale_model": 'realesr-animevideov3', # 'realesr-animevideov3' (default of realesrgan engine, does 2-4x), the rest do only 4x:'realesrgan-x4plus', 'realesrgan-x4plus-anime' "r_upscale_keep_imgs": True, "store_frames_in_ram": False, # **Interpolate Video Settings** "frame_interpolation_engine": "None", # ["None", "RIFE v4.6", "FILM"] "frame_interpolation_x_amount": 2, # [2 to 1000 depends on the engine] "frame_interpolation_slow_mo_enabled": False, "frame_interpolation_slow_mo_amount": 2, # [2 to 10] "frame_interpolation_keep_imgs": False } def get_component_names(): return ['override_settings_with_file', 'custom_settings_file', *DeforumAnimArgs().keys(), 'animation_prompts', 'animation_prompts_positive', 'animation_prompts_negative', *DeforumArgs().keys(), *DeforumOutputArgs().keys(), *ParseqArgs().keys(), *LoopArgs().keys(), *controlnet_component_names()] def get_settings_component_names(): return [name for name in get_component_names()] def pack_args(args_dict): args_dict = {name: args_dict[name] for name in DeforumArgs()} args_dict.update({name: CoreArgs()[name] for name in CoreArgs()}) return args_dict def pack_anim_args(args_dict): return {name: args_dict[name] for name in DeforumAnimArgs()} def pack_video_args(args_dict): return {name: args_dict[name] for name in DeforumOutputArgs()} def pack_parseq_args(args_dict): return {name: args_dict[name] for name in ParseqArgs()} def pack_loop_args(args_dict): return {name: args_dict[name] for name in LoopArgs()} def pack_controlnet_args(args_dict): return {name: args_dict[name] for name in controlnet_component_names()} def process_args(args_dict_main, run_id): from .settings import load_args override_settings_with_file = args_dict_main['override_settings_with_file'] custom_settings_file = args_dict_main['custom_settings_file'] args_dict = pack_args(args_dict_main) anim_args_dict = pack_anim_args(args_dict_main) video_args_dict = pack_video_args(args_dict_main) parseq_args_dict = pack_parseq_args(args_dict_main) loop_args_dict = pack_loop_args(args_dict_main) controlnet_args_dict = pack_controlnet_args(args_dict_main) root = SimpleNamespace(**RootArgs()) p = args_dict_main['p'] root.animation_prompts = json.loads(args_dict_main['animation_prompts']) args_loaded_ok = True # can use this later to error cleanly upon wrong gen param in ui if override_settings_with_file: args_loaded_ok = load_args(args_dict_main, args_dict, anim_args_dict, parseq_args_dict, loop_args_dict, controlnet_args_dict, video_args_dict, custom_settings_file, root, run_id) positive_prompts = args_dict_main['animation_prompts_positive'] negative_prompts = args_dict_main['animation_prompts_negative'] negative_prompts = negative_prompts.replace('--neg', '') # remove --neg from negative_prompts if received by mistake for key in root.animation_prompts: animationPromptCurr = root.animation_prompts[key] root.animation_prompts[key] = f"{positive_prompts} {animationPromptCurr} {'' if '--neg' in animationPromptCurr else '--neg'} {negative_prompts}" os.makedirs(root.models_path, exist_ok=True) args = SimpleNamespace(**args_dict) anim_args = SimpleNamespace(**anim_args_dict) video_args = SimpleNamespace(**video_args_dict) parseq_args = SimpleNamespace(**parseq_args_dict) loop_args = SimpleNamespace(**loop_args_dict) controlnet_args = SimpleNamespace(**controlnet_args_dict) if args.seed == -1: root.raw_seed = -1 args.seed = get_fixed_seed(args.seed) if root.raw_seed != -1: root.raw_seed = args.seed args.timestring = time.strftime('%Y%m%d%H%M%S') args.strength = max(0.0, min(1.0, args.strength)) args.prompts = json.loads(args_dict_main['animation_prompts']) args.positive_prompts = args_dict_main['animation_prompts_positive'] args.negative_prompts = args_dict_main['animation_prompts_negative'] if not args.use_init and not anim_args.hybrid_use_init_image: args.init_image = None if anim_args.animation_mode == 'None': anim_args.max_frames = 1 elif anim_args.animation_mode == 'Video Input': args.use_init = True current_arg_list = [args, anim_args, video_args, parseq_args] full_base_folder_path = os.path.join(os.getcwd(), p.outpath_samples) root.raw_batch_name = args.batch_name args.batch_name = substitute_placeholders(args.batch_name, current_arg_list, full_base_folder_path) args.outdir = os.path.join(p.outpath_samples, str(args.batch_name)) args.outdir = os.path.join(os.getcwd(), args.outdir) os.makedirs(args.outdir, exist_ok=True) return args_loaded_ok, root, args, anim_args, video_args, parseq_args, loop_args, controlnet_args