diff --git a/scripts/deforum_helpers/blocking_file_list.py b/scripts/deforum_helpers/blocking_file_list.py new file mode 100644 index 000000000..528506924 --- /dev/null +++ b/scripts/deforum_helpers/blocking_file_list.py @@ -0,0 +1,25 @@ +import os +import time + +class BlockingFileList: + def __init__(self, base_directory, expected_file_count=0, extension=".jpg"): + self.base_directory = base_directory + self.expected_file_count = expected_file_count + self.extension = extension + + def __getitem__(self, index): + file_path = os.path.join(self.base_directory, str(index) + self.extension) + timeout = 30 # Maximum wait time of 30s + start_time = time.time() + + while not os.path.exists(file_path): + waited = time.time() - start_time + if waited >= timeout: + raise FileNotFoundError(f"File {file_path} not found after waiting for {timeout} seconds") + print(f"Could not find file {file_path}. Waiting for it to appear (waited {waited}/{timeout})...") + time.sleep(1) # Wait for 1 second before checking again + + return file_path + + def __len__(self): + return self.expected_file_count \ No newline at end of file diff --git a/scripts/deforum_helpers/hybrid_video.py b/scripts/deforum_helpers/hybrid_video.py index fdff95d71..f1e60af81 100644 --- a/scripts/deforum_helpers/hybrid_video.py +++ b/scripts/deforum_helpers/hybrid_video.py @@ -26,6 +26,8 @@ from .human_masking import video2humanmasks from .load_images import load_image from .video_audio_utilities import vid2frames, get_quick_vid_info, get_frame_name +from .blocking_file_list import BlockingFileList +from modules.shared import opts def delete_all_imgs_in_folder(folder_path): files = list(pathlib.Path(folder_path).glob('*.jpg')) @@ -78,11 +80,15 @@ def hybrid_generation(args, anim_args, root): inputfiles = sorted(pathlib.Path(video_in_frame_path).glob('*.jpg')) if not anim_args.hybrid_use_init_image: - # determine max frames from length of input frames + if opts.data.get("deforum_allow_blocking_input_framelists", False): + print(f"Will wait for input frames to appear in {video_in_frame_path}") + inputfiles = BlockingFileList(hybrid_frame_path, anim_args.max_frames, ".jpg") + elif len(inputfiles) < 1: + raise Exception(f"Error: No input frames found in {video_in_frame_path}! Please check your input video path and whether you've opted to extract input frames.") + anim_args.max_frames = len(inputfiles) - if anim_args.max_frames < 1: - raise Exception(f"Error: No input frames found in {video_in_frame_path}! Please check your input video path and whether you've opted to extract input frames.") - print(f"Using {anim_args.max_frames} input frames from {video_in_frame_path}...") + + print(f"Using {anim_args.max_frames} input frames from {video_in_frame_path}...") # use first frame as init if anim_args.hybrid_use_first_frame_as_init_image: diff --git a/scripts/deforum_helpers/ui_settings.py b/scripts/deforum_helpers/ui_settings.py index ec0fd91a8..21077e205 100644 --- a/scripts/deforum_helpers/ui_settings.py +++ b/scripts/deforum_helpers/ui_settings.py @@ -35,3 +35,4 @@ def on_ui_settings(): opts.add_option("deforum_save_gen_info_as_srt_params", OptionInfo(['Noise Schedule'], "Choose which animation params are to be saved to the .srt file (Frame # and Seed will always be saved):", ui_components.DropdownMulti, lambda: {"interactive": True, "choices": srt_ui_params}, section=section)) opts.add_option("deforum_preview", OptionInfo("Off", "Generate preview video during generation? (Preview does not include frame interpolation or upscaling.)", gr.Dropdown, {"interactive": True, "choices": ['Off', 'On', 'On, concurrent (don\'t pause generation)']}, section=section)) opts.add_option("deforum_preview_interval_frames", OptionInfo(100, "Generate preview every N frames", gr.Slider, {"interactive": True, "minimum": 10, "maximum": 500}, section=section)) + opts.add_option("deforum_allow_blocking_input_framelists", OptionInfo(False, "If a hybrid video input frame is not found, wait for up to 30s for it to appear. This allows hybrid video input frames to be generated by concurrent processes.", gr.Checkbox, {"interactive": True}, section=section)) \ No newline at end of file