parent
95c58f667f
commit
7f8fda4e15
|
|
@ -22,6 +22,8 @@ Once the image generation begins, the intermediate images will start saving in a
|
|||
Please be aware that _Image creation progress preview mode_ in the webui's settings affects how the intermediate images are created.
|
||||
|
||||
You can also make a video out of the intermediate images:
|
||||
<p><img src="images/13655-sample.gif"/>
|
||||
<p>GIF:<br>
|
||||
<img src="images/13655-sample.gif"/>
|
||||
<img src="images/13642-sample.gif"/>
|
||||
<p>MP4, with interpolation:<br>
|
||||
<video src='https://user-images.githubusercontent.com/99896447/213034519-7b6ed42f-39d5-4994-a8b7-c85ec92bda84.mp4' autoplay loop></video>
|
||||
|
|
@ -16,6 +16,74 @@ import gradio as gr; gr.__version__
|
|||
|
||||
orig_callback_state = KDiffusionSampler.callback_state
|
||||
|
||||
|
||||
def make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug):
|
||||
if ssii_is_active and ssii_video and not state.skipped and not state.interrupted:
|
||||
logger = logging.getLogger(__name__)
|
||||
# ffmpeg requires sequential numbers in filenames (that is exactly +1)
|
||||
p.intermed_files.sort(key=lambda x: x[0])
|
||||
prev_batch = None
|
||||
for real_i, (batch_no, name_org, _) in enumerate(p.intermed_files):
|
||||
if prev_batch != batch_no:
|
||||
i = 0
|
||||
num_seq = '{:03}'.format(i)
|
||||
name_seq = re.sub(r'^\d+-(\d{3})', f'{name_org.split("-")[0]}-{num_seq}', name_org)
|
||||
p.intermed_files[real_i] = (batch_no, name_org, name_seq)
|
||||
path_name_org = os.path.join(p.intermed_outpath, name_org)
|
||||
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
|
||||
os.replace(path_name_org, path_name_seq)
|
||||
logger.debug(f"replace {path_name_org} / {path_name_seq}")
|
||||
i = i + 1
|
||||
prev_batch = batch_no
|
||||
frames_per_image = i
|
||||
|
||||
for intermed_pattern in p.intermed_pattern.values():
|
||||
img_file = intermed_pattern.replace("%%%", "%03d") + ".png"
|
||||
vid_file = intermed_pattern.replace("%%%-", "") + "." + ssii_video_format
|
||||
if hasattr(p, "enable_hr"):
|
||||
if p.enable_hr and ssii_video_hires == "1":
|
||||
img_file = img_file.replace("-p2-", "-p1-")
|
||||
vid_file = vid_file.replace("-p2-", "-p1-")
|
||||
path_img_file = os.path.join(p.intermed_outpath, img_file)
|
||||
path_vid_file = os.path.join(p.intermed_outpath, vid_file)
|
||||
if ssii_smooth:
|
||||
pts = (round(ssii_seconds / frames_per_image, 5))
|
||||
logger.debug(f"pts: {pts}")
|
||||
if pts < 1:
|
||||
pts = "1"
|
||||
else:
|
||||
pts = str(pts)
|
||||
if ssii_video_format == "gif":
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: "-benchmark -framerate 1"},
|
||||
outputs={path_vid_file: f'-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a [v3]; [v3]setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
|
||||
)
|
||||
else:
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: "-benchmark -framerate 1"},
|
||||
outputs={path_vid_file: f'-filter_complex "setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
|
||||
)
|
||||
else:
|
||||
if ssii_video_format == "gif":
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
|
||||
outputs={path_vid_file: '-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a"'}
|
||||
)
|
||||
else:
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
|
||||
outputs={path_vid_file: None}
|
||||
)
|
||||
ff.run()
|
||||
|
||||
# Back to original numbering
|
||||
for (batch_no, name_org, name_seq) in reversed(p.intermed_files):
|
||||
path_name_org = os.path.join(p.intermed_outpath, name_org)
|
||||
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
|
||||
os.replace(path_name_seq, path_name_org)
|
||||
logger.debug(f"replace {path_name_seq} / {path_name_org}")
|
||||
return
|
||||
|
||||
class Script(scripts.Script):
|
||||
def title(self):
|
||||
return "Save intermediate images during the sampling process"
|
||||
|
|
@ -90,7 +158,7 @@ class Script(scripts.Script):
|
|||
return [ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug]
|
||||
|
||||
def save_image_only_get_name(image, path, basename, seed=None, prompt=None, extension='png', info=None, short_filename=False, no_prompt=False, grid=False, pnginfo_section_name='parameters', p=None, existing_info=None, forced_filename=None, suffix="", save_to_dirs=None):
|
||||
#for description see modules.images.save_image, same code up saving of files
|
||||
# for description see modules.images.save_image, same code up saving of files
|
||||
|
||||
namegen = FilenameGenerator(p, seed, prompt, image)
|
||||
|
||||
|
|
@ -176,7 +244,20 @@ class Script(scripts.Script):
|
|||
logger.debug(f"Step: {current_step}")
|
||||
logger.debug(f"hr: {hr}")
|
||||
|
||||
#Highres. fix requires 2 passes
|
||||
if current_step == 0:
|
||||
# Deal with batch_count > 1
|
||||
if hasattr(p, 'intermed_batch_iter'):
|
||||
if p.iteration > p.intermed_batch_iter:
|
||||
p.intermed_batch_iter = p.iteration
|
||||
# Reset per-batch_count-attributes
|
||||
delattr(p, "intermed_final_pass")
|
||||
delattr(p, "intermed_max_step")
|
||||
# Make video for previous batch_count
|
||||
make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug)
|
||||
else:
|
||||
p.intermed_batch_iter = p.iteration
|
||||
|
||||
# Highres. fix requires 2 passes
|
||||
if not hasattr(p, 'intermed_final_pass'):
|
||||
if hr:
|
||||
p.intermed_first_pass = True
|
||||
|
|
@ -185,7 +266,7 @@ class Script(scripts.Script):
|
|||
p.intermed_first_pass = True
|
||||
p.intermed_final_pass = True
|
||||
|
||||
#Check if pass 1 has finished
|
||||
# Check if pass 1 has finished
|
||||
if hasattr(p, 'intermed_max_step'):
|
||||
if current_step >= p.intermed_max_step:
|
||||
p.intermed_max_step = current_step
|
||||
|
|
@ -196,7 +277,7 @@ class Script(scripts.Script):
|
|||
else:
|
||||
p.intermed_max_step = current_step
|
||||
|
||||
#ssii_stop_at_n must be a multiple of ssii_every_n
|
||||
# ssii_stop_at_n must be a multiple of ssii_every_n
|
||||
if not hasattr(p, 'intermed_ssii_stop_at_n'):
|
||||
if ssii_stop_at_n % ssii_every_n == 0:
|
||||
p.intermed_ssii_stop_at_n = ssii_stop_at_n
|
||||
|
|
@ -205,6 +286,7 @@ class Script(scripts.Script):
|
|||
|
||||
if current_step % ssii_every_n == 0:
|
||||
for index in range(0, p.batch_size):
|
||||
# Live preview only works on first batch_pos
|
||||
if ssii_intermediate_type == "According to Live preview subject setting" and index == 0:
|
||||
image = state.current_image
|
||||
elif ssii_intermediate_type == "Noisy":
|
||||
|
|
@ -214,6 +296,7 @@ class Script(scripts.Script):
|
|||
|
||||
logger.debug(f"ssii_intermediate_type, ssii_every_n, ssii_stop_at_n: {ssii_intermediate_type}, {ssii_every_n}, {ssii_stop_at_n}")
|
||||
logger.debug(f"Step: {current_step}")
|
||||
logger.debug(f"batch_count, iteration, batch_size, batch_pos: {p.n_iter}, {p.iteration}, {p.batch_size}, {index}")
|
||||
|
||||
# Inits per seed
|
||||
if current_step == 0 and p.intermed_first_pass:
|
||||
|
|
@ -263,46 +346,52 @@ class Script(scripts.Script):
|
|||
logger.debug(f"p.all_seeds: {p.all_seeds}")
|
||||
logger.debug(f"p.cfg_scale: {p.cfg_scale}")
|
||||
logger.debug(f"p.sampler_name: {p.sampler_name}")
|
||||
logger.debug(f"p.batch_size: {p.batch_size}")
|
||||
|
||||
intermed_suffix = p.intermed_outpath_suffix.replace(str(int(p.seed)), str(int(p.all_seeds[index])), 1)
|
||||
intermed_pattern = p.intermed_outpath_number[index] + "-%%%-" + intermed_suffix
|
||||
if hr:
|
||||
if p.intermed_final_pass:
|
||||
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p2")
|
||||
else:
|
||||
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p1")
|
||||
p.intermed_pattern[int(p.all_seeds[index])] = intermed_pattern
|
||||
filename = intermed_pattern.replace("%%%", f"{current_step:03}")
|
||||
|
||||
#don't save first step
|
||||
if current_step > 0:
|
||||
#generate png-info
|
||||
infotext = create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments=[], position_in_batch=index % p.batch_size, iteration=index // p.batch_size)
|
||||
infotext = f'{infotext}, intermediate: {current_step:03d}'
|
||||
|
||||
if current_step == p.intermed_ssii_stop_at_n:
|
||||
if (hr and p.intermed_final_pass) or not hr:
|
||||
#early stop for this seed reached, prevent normal save, save as final image
|
||||
p.do_not_save_samples = True
|
||||
save_image(image, p.outpath_samples, "", p.all_seeds[index], p.prompt, opts.samples_format, info=infotext, p=p)
|
||||
if index == p.batch_size - 1:
|
||||
#early stop for final seed and final pass reached, interrupt further processing
|
||||
state.interrupt()
|
||||
|
||||
# Don't continue with no image (can happen with live preview subject setting)
|
||||
if image is None:
|
||||
logger.debug("image is None")
|
||||
else:
|
||||
intermed_seed_index = p.iteration * p.batch_size + index
|
||||
intermed_seed = int(p.all_seeds[intermed_seed_index])
|
||||
logger.debug(f"intermed_seed_index, intermed_seed: {intermed_seed_index}, {intermed_seed}")
|
||||
intermed_suffix = p.intermed_outpath_suffix.replace(str(int(p.seed)), str(intermed_seed), 1)
|
||||
intermed_pattern = p.intermed_outpath_number[index] + "-%%%-" + intermed_suffix
|
||||
if hr:
|
||||
if p.intermed_final_pass:
|
||||
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p2")
|
||||
else:
|
||||
#save intermediate image
|
||||
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p1")
|
||||
p.intermed_pattern[intermed_seed] = intermed_pattern
|
||||
filename = intermed_pattern.replace("%%%", f"{current_step:03}")
|
||||
|
||||
# Don't save first step
|
||||
if current_step > 0:
|
||||
# generate png-info
|
||||
infotext = create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments=[], position_in_batch=index % p.batch_size, iteration=index // p.batch_size)
|
||||
infotext = f'{infotext}, intermediate: {current_step:03d}'
|
||||
|
||||
if current_step == p.intermed_ssii_stop_at_n:
|
||||
if (hr and p.intermed_final_pass) or not hr:
|
||||
# early stop for this seed reached, prevent normal save, save as final image
|
||||
p.do_not_save_samples = True
|
||||
save_image(image, p.outpath_samples, "", intermed_seed, p.prompt, opts.samples_format, info=infotext, p=p)
|
||||
if index == p.batch_size - 1:
|
||||
# early stop for final seed and final pass reached, interrupt further processing
|
||||
state.interrupt()
|
||||
else:
|
||||
# save intermediate image
|
||||
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
|
||||
filename_clean = re.sub(r"[^\d-]", "%", filename)
|
||||
logger.debug(f"filename: {filename_clean}")
|
||||
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
|
||||
p.intermed_files.append((index, filename + ".png", None))
|
||||
else:
|
||||
# save intermediate image
|
||||
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
|
||||
filename_clean = re.sub(r"[^\d-]", "%", filename)
|
||||
logger.debug(f"filename: {filename_clean}")
|
||||
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
|
||||
p.intermed_files.append((index, filename + ".png", None))
|
||||
else:
|
||||
#save intermediate image
|
||||
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
|
||||
filename_clean = re.sub(r"[^\d-]", "%", filename)
|
||||
logger.debug(f"filename: {filename_clean}")
|
||||
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
|
||||
p.intermed_files.append((index, filename + ".png", None))
|
||||
return orig_callback_state(self, d)
|
||||
|
||||
setattr(KDiffusionSampler, "callback_state", callback_state)
|
||||
|
|
@ -310,68 +399,5 @@ class Script(scripts.Script):
|
|||
def postprocess(self, p, processed, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug):
|
||||
setattr(KDiffusionSampler, "callback_state", orig_callback_state)
|
||||
|
||||
# Make a video file
|
||||
if ssii_is_active and ssii_video and not state.skipped and not state.interrupted:
|
||||
logger = logging.getLogger(__name__)
|
||||
# ffmpeg requires sequential numbers in filenames (that is exactly +1)
|
||||
p.intermed_files.sort(key=lambda x: x[0])
|
||||
prev_batch = None
|
||||
for real_i, (batch_no, name_org, _) in enumerate(p.intermed_files):
|
||||
if prev_batch != batch_no:
|
||||
i = 0
|
||||
num_seq = '{:03}'.format(i)
|
||||
name_seq = re.sub(r'^\d+-(\d{3})', f'{name_org.split("-")[0]}-{num_seq}', name_org)
|
||||
p.intermed_files[real_i] = (batch_no, name_org, name_seq)
|
||||
path_name_org = os.path.join(p.intermed_outpath, name_org)
|
||||
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
|
||||
os.replace(path_name_org, path_name_seq)
|
||||
logger.debug(f"replace {path_name_org} / {path_name_seq}")
|
||||
i = i + 1
|
||||
prev_batch = batch_no
|
||||
frames_per_image = i
|
||||
|
||||
for intermed_pattern in p.intermed_pattern.values():
|
||||
img_file = intermed_pattern.replace("%%%", "%03d") + ".png"
|
||||
vid_file = intermed_pattern.replace("%%%-", "") + "." + ssii_video_format
|
||||
if hasattr(p, "enable_hr"):
|
||||
if p.enable_hr and ssii_video_hires == "1":
|
||||
img_file = img_file.replace("-p2-", "-p1-")
|
||||
vid_file = vid_file.replace("-p2-", "-p1-")
|
||||
path_img_file = os.path.join(p.intermed_outpath, img_file)
|
||||
path_vid_file = os.path.join(p.intermed_outpath, vid_file)
|
||||
if ssii_smooth:
|
||||
pts = (round(ssii_seconds / frames_per_image, 5))
|
||||
logger.debug(f"pts: {pts}")
|
||||
if pts < 1:
|
||||
pts = "1"
|
||||
else:
|
||||
pts = str(pts)
|
||||
if ssii_video_format == "gif":
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: "-benchmark -framerate 1"},
|
||||
outputs={path_vid_file: f'-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a [v3]; [v3]setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
|
||||
)
|
||||
else:
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: "-benchmark -framerate 1"},
|
||||
outputs={path_vid_file: f'-filter_complex "setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
|
||||
)
|
||||
else:
|
||||
if ssii_video_format == "gif":
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
|
||||
outputs={path_vid_file: '-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a"'}
|
||||
)
|
||||
else:
|
||||
ff = FFmpeg(
|
||||
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
|
||||
outputs={path_vid_file: None}
|
||||
)
|
||||
ff.run()
|
||||
|
||||
# Back to original numbering
|
||||
for (batch_no, name_org, name_seq) in reversed(p.intermed_files):
|
||||
path_name_org = os.path.join(p.intermed_outpath, name_org)
|
||||
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
|
||||
os.replace(path_name_seq, path_name_org)
|
||||
logger.debug(f"replace {path_name_seq} / {path_name_org}")
|
||||
# Make video for last batch_count
|
||||
make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug)
|
||||
|
|
|
|||
Loading…
Reference in New Issue