Spaces:
Runtime error
Runtime error
File size: 17,560 Bytes
55cc64a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# Detach 'deforum_helpers' from 'scripts' to prevent "No module named 'scripts.deforum_helpers'" error
# causing Deforum's tab not show up in some cases when you've might've broken the environment with webui packages updates
import sys, os, shutil
basedirs = [os.getcwd()]
if 'google.colab' in sys.modules:
basedirs.append('/content/gdrive/MyDrive/sd/stable-diffusion-webui') #hardcode as TheLastBen's colab seems to be the primal source
for basedir in basedirs:
deforum_paths_to_ensure = [basedir + '/extensions/deforum-for-automatic1111-webui/scripts', basedir + '/extensions/sd-webui-controlnet', basedir + '/extensions/deforum/scripts', basedir + '/scripts/deforum_helpers/src', basedir + '/extensions/deforum/scripts/deforum_helpers/src', basedir +'/extensions/deforum-for-automatic1111-webui/scripts/deforum_helpers/src',basedir]
for deforum_scripts_path_fix in deforum_paths_to_ensure:
if not deforum_scripts_path_fix in sys.path:
sys.path.extend([deforum_scripts_path_fix])
# Main deforum stuff
import deforum_helpers.args as deforum_args
import deforum_helpers.settings as deforum_settings
from deforum_helpers.save_images import dump_frames_cache, reset_frames_cache
from deforum_helpers.frame_interpolation import process_video_interpolation
import modules.scripts as wscripts
from modules import script_callbacks
import gradio as gr
import json
from modules.processing import Processed, StableDiffusionProcessingImg2Img, process_images
from PIL import Image
from deforum_helpers.video_audio_utilities import ffmpeg_stitch_video, make_gifski_gif
from deforum_helpers.upscaling import make_upscale_v2
import gc
import torch
from webui import wrap_gradio_gpu_call
import modules.shared as shared
from modules.shared import opts, cmd_opts, state
from modules.ui import create_output_panel, plaintext_to_html, wrap_gradio_call
from types import SimpleNamespace
def run_deforum(*args, **kwargs):
args_dict = {deforum_args.component_names[i]: args[i+2] for i in range(0, len(deforum_args.component_names))}
p = StableDiffusionProcessingImg2Img(
sd_model=shared.sd_model,
outpath_samples = opts.outdir_samples or opts.outdir_img2img_samples,
outpath_grids = opts.outdir_grids or opts.outdir_img2img_grids,
#we'll setup the rest later
)
print("\033[4;33mDeforum extension for auto1111 webui, v2.2b\033[0m")
args_dict['self'] = None
args_dict['p'] = p
root, args, anim_args, video_args, parseq_args, loop_args, controlnet_args = deforum_args.process_args(args_dict)
root.clipseg_model = None
root.initial_clipskip = opts.data["CLIP_stop_at_last_layers"]
root.basedirs = basedirs
for basedir in basedirs:
sys.path.extend([
basedir + '/scripts/deforum_helpers/src',
basedir + '/extensions/deforum/scripts/deforum_helpers/src',
basedir + '/extensions/deforum-for-automatic1111-webui/scripts/deforum_helpers/src',
])
# clean up unused memory
reset_frames_cache(root)
gc.collect()
torch.cuda.empty_cache()
from deforum_helpers.render import render_animation
from deforum_helpers.render_modes import render_input_video, render_animation_with_video_mask, render_interpolation
tqdm_backup = shared.total_tqdm
shared.total_tqdm = deforum_settings.DeforumTQDM(args, anim_args, parseq_args)
try:
# dispatch to appropriate renderer
if anim_args.animation_mode == '2D' or anim_args.animation_mode == '3D':
if anim_args.use_mask_video:
render_animation_with_video_mask(args, anim_args, video_args, parseq_args, loop_args, controlnet_args, root.animation_prompts, root) # allow mask video without an input video
else:
render_animation(args, anim_args, video_args, parseq_args, loop_args, controlnet_args, root.animation_prompts, root)
elif anim_args.animation_mode == 'Video Input':
render_input_video(args, anim_args, video_args, parseq_args, loop_args, controlnet_args, root.animation_prompts, root)#TODO: prettify code
elif anim_args.animation_mode == 'Interpolation':
render_interpolation(args, anim_args, video_args, parseq_args, loop_args, controlnet_args, root.animation_prompts, root)
else:
print('Other modes are not available yet!')
finally:
shared.total_tqdm = tqdm_backup
opts.data["CLIP_stop_at_last_layers"] = root.initial_clipskip
if video_args.store_frames_in_ram:
dump_frames_cache(root)
from base64 import b64encode
real_audio_track = None
if video_args.add_soundtrack != 'None':
real_audio_track = anim_args.video_init_path if video_args.add_soundtrack == 'Init Video' else video_args.soundtrack_path
# Delete folder with duplicated imgs from OS temp folder
shutil.rmtree(root.tmp_deforum_run_duplicated_folder, ignore_errors=True)
# Decide whether or not we need to try and frame interpolate laters
need_to_frame_interpolate = False
if video_args.frame_interpolation_engine != "None" and not video_args.skip_video_for_run_all and not video_args.store_frames_in_ram:
need_to_frame_interpolate = True
if video_args.skip_video_for_run_all:
print('Skipping video creation, uncheck skip_video_for_run_all if you want to run it')
else:
import subprocess
path_name_modifier = video_args.path_name_modifier
if video_args.render_steps: # render steps from a single image
fname = f"{path_name_modifier}_%05d.png"
all_step_dirs = [os.path.join(args.outdir, d) for d in os.listdir(args.outdir) if os.path.isdir(os.path.join(args.outdir,d))]
newest_dir = max(all_step_dirs, key=os.path.getmtime)
image_path = os.path.join(newest_dir, fname)
print(f"Reading images from {image_path}")
mp4_path = os.path.join(newest_dir, f"{args.timestring}_{path_name_modifier}.mp4")
max_video_frames = args.steps
else: # render images for a video
image_path = os.path.join(args.outdir, f"{args.timestring}_%05d.png")
mp4_path = os.path.join(args.outdir, f"{args.timestring}.mp4")
max_video_frames = anim_args.max_frames
exclude_keys = deforum_settings.get_keys_to_exclude('video')
video_settings_filename = os.path.join(args.outdir, f"{args.timestring}_video-settings.txt")
with open(video_settings_filename, "w+", encoding="utf-8") as f:
s = {}
for key, value in dict(video_args.__dict__).items():
if key not in exclude_keys:
s[key] = value
json.dump(s, f, ensure_ascii=False, indent=4)
# Stitch video using ffmpeg!
try:
ffmpeg_stitch_video(ffmpeg_location=video_args.ffmpeg_location, fps=video_args.fps, outmp4_path=mp4_path, stitch_from_frame=0, stitch_to_frame=max_video_frames, imgs_path=image_path, add_soundtrack=video_args.add_soundtrack, audio_path=real_audio_track, crf=video_args.ffmpeg_crf, preset=video_args.ffmpeg_preset)
mp4 = open(mp4_path,'rb').read()
data_url = "data:video/mp4;base64," + b64encode(mp4).decode()
deforum_args.i1_store = f'<p style=\"font-weight:bold;margin-bottom:0em\">Deforum v0.5-webui-beta</p><video controls loop><source src="{data_url}" type="video/mp4"></video>'
except Exception as e:
if need_to_frame_interpolate:
print(f"FFMPEG DID NOT STITCH ANY VIDEO. However, you requested to frame interpolate - so we will continue to frame interpolation, but you'll be left only with the interpolated frames and not a video, since ffmpeg couldn't run. Original ffmpeg error: {e}")
else:
print(f"** FFMPEG DID NOT STITCH ANY VIDEO ** Error: {e}")
pass
if root.initial_info is None:
root.initial_info = "An error has occured and nothing has been generated!"
root.initial_info += "\nPlease, report the bug to https://github.com/deforum-art/deforum-for-automatic1111-webui/issues"
import numpy as np
a = np.random.rand(args.W, args.H, 3)*255
root.first_frame = Image.fromarray(a.astype('uint8')).convert('RGB')
root.initial_seed = 6934
# FRAME INTERPOLATION TIME
if need_to_frame_interpolate:
print(f"Got a request to *frame interpolate* using {video_args.frame_interpolation_engine}")
process_video_interpolation(frame_interpolation_engine=video_args.frame_interpolation_engine, frame_interpolation_x_amount=video_args.frame_interpolation_x_amount,frame_interpolation_slow_mo_enabled=video_args.frame_interpolation_slow_mo_enabled, frame_interpolation_slow_mo_amount=video_args.frame_interpolation_slow_mo_amount, orig_vid_fps=video_args.fps, deforum_models_path=root.models_path, real_audio_track=real_audio_track, raw_output_imgs_path=args.outdir, img_batch_id=args.timestring, ffmpeg_location=video_args.ffmpeg_location, ffmpeg_crf=video_args.ffmpeg_crf, ffmpeg_preset=video_args.ffmpeg_preset, keep_interp_imgs=video_args.frame_interpolation_keep_imgs, orig_vid_name=None, resolution=None)
if video_args.make_gif and not video_args.skip_video_for_run_all and not video_args.store_frames_in_ram:
make_gifski_gif(imgs_raw_path = args.outdir, imgs_batch_id = args.timestring, fps = video_args.fps, models_folder = root.models_path, current_user_os = root.current_user_os)
# Upscale video once generation is done:
if video_args.r_upscale_video and not video_args.skip_video_for_run_all and not video_args.store_frames_in_ram:
# out mp4 path is defined in make_upscale func
make_upscale_v2(upscale_factor = video_args.r_upscale_factor, upscale_model = video_args.r_upscale_model, keep_imgs = video_args.r_upscale_keep_imgs, imgs_raw_path = args.outdir, imgs_batch_id = args.timestring, fps = video_args.fps, deforum_models_path = root.models_path, current_user_os = root.current_user_os, ffmpeg_location=video_args.ffmpeg_location, stitch_from_frame=0, stitch_to_frame=max_video_frames, ffmpeg_crf=video_args.ffmpeg_crf, ffmpeg_preset=video_args.ffmpeg_preset, add_soundtrack = video_args.add_soundtrack ,audio_path=real_audio_track)
root.initial_info += "\n The animation is stored in " + args.outdir
root.initial_info += "\n Timestring = " + args.timestring + '\n'
root.initial_info += "Only the first frame is shown in webui not to clutter the memory"
reset_frames_cache(root) # cleanup the RAM in any case
processed = Processed(p, [root.first_frame], root.initial_seed, root.initial_info)
if processed is None:
processed = process_images(p)
shared.total_tqdm.clear()
generation_info_js = processed.js()
if opts.samples_log_stdout:
print(generation_info_js)
if opts.do_not_show_images:
processed.images = []
return processed.images, generation_info_js, plaintext_to_html(processed.info), plaintext_to_html('')
def on_ui_tabs():
with gr.Blocks(analytics_enabled=False) as deforum_interface:
components = {}
dummy_component = gr.Label(visible=False)
with gr.Row(elem_id='deforum_progress_row').style(equal_height=False):
with gr.Column(scale=1, variant='panel'):
components = deforum_args.setup_deforum_setting_dictionary(None, True, True)
with gr.Column(scale=1):
with gr.Row():
btn = gr.Button("Click here after the generation to show the video")
components['btn'] = btn
close_btn = gr.Button("Close the video", visible=False)
with gr.Row():
i1 = gr.HTML(deforum_args.i1_store, elem_id='deforum_header')
components['i1'] = i1
# Show video
def show_vid():
return {
i1: gr.update(value=deforum_args.i1_store, visible=True),
close_btn: gr.update(visible=True),
btn: gr.update(value="Update the video", visible=True),
}
btn.click(
show_vid,
[],
[i1, close_btn, btn],
)
# Close video
def close_vid():
return {
i1: gr.update(value=deforum_args.i1_store_backup, visible=True),
close_btn: gr.update(visible=False),
btn: gr.update(value="Click here after the generation to show the video", visible=True),
}
close_btn.click(
close_vid,
[],
[i1, close_btn, btn],
)
id_part = 'deforum'
with gr.Row(elem_id=f"{id_part}_generate_box"):
skip = gr.Button('Skip', elem_id=f"{id_part}_skip", visible=False)
interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt", visible=True)
submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary')
skip.click(
fn=lambda: state.skip(),
inputs=[],
outputs=[],
)
interrupt.click(
fn=lambda: state.interrupt(),
inputs=[],
outputs=[],
)
deforum_gallery, generation_info, html_info, html_log = create_output_panel("deforum", opts.outdir_img2img_samples)
gr.HTML("<p>* Paths can be relative to webui folder OR full - absolute </p>")
with gr.Row():
settings_path = gr.Textbox("deforum_settings.txt", elem_id='deforum_settings_path', label="General Settings File")
#reuse_latest_settings_btn = gr.Button('Reuse Latest', elem_id='deforum_reuse_latest_settings_btn')#TODO
with gr.Row():
save_settings_btn = gr.Button('Save Settings', elem_id='deforum_save_settings_btn')
load_settings_btn = gr.Button('Load Settings', elem_id='deforum_load_settings_btn')
with gr.Row():
video_settings_path = gr.Textbox("deforum_video-settings.txt", elem_id='deforum_video_settings_path', label="Video Settings File")
#reuse_latest_video_settings_btn = gr.Button('Reuse Latest', elem_id='deforum_reuse_latest_video_settings_btn')#TODO
with gr.Row():
save_video_settings_btn = gr.Button('Save Video Settings', elem_id='deforum_save_video_settings_btn')
load_video_settings_btn = gr.Button('Load Video Settings', elem_id='deforum_load_video_settings_btn')
# components['prompts'].visible = False#hide prompts for the time being
#TODO clean up the code
components['save_sample_per_step'].visible = False
components['show_sample_per_step'].visible = False
components['display_samples'].visible = False
component_list = [components[name] for name in deforum_args.component_names]
submit.click(
fn=wrap_gradio_gpu_call(run_deforum, extra_outputs=[None, '', '']),
_js="submit_deforum",
inputs=[dummy_component, dummy_component] + component_list,
outputs=[
deforum_gallery,
generation_info,
html_info,
html_log,
],
)
settings_component_list = [components[name] for name in deforum_args.settings_component_names]
video_settings_component_list = [components[name] for name in deforum_args.video_args_names]
stuff = gr.HTML("") # wrap gradio call garbage
stuff.visible = False
save_settings_btn.click(
fn=wrap_gradio_call(deforum_settings.save_settings),
inputs=[settings_path] + settings_component_list,
outputs=[stuff],
)
load_settings_btn.click(
fn=wrap_gradio_call(deforum_settings.load_settings),
inputs=[settings_path]+ settings_component_list,
outputs=settings_component_list + [stuff],
)
save_video_settings_btn.click(
fn=wrap_gradio_call(deforum_settings.save_video_settings),
inputs=[video_settings_path] + video_settings_component_list,
outputs=[stuff],
)
load_video_settings_btn.click(
fn=wrap_gradio_call(deforum_settings.load_video_settings),
inputs=[video_settings_path] + video_settings_component_list,
outputs=video_settings_component_list + [stuff],
)
return [(deforum_interface, "Deforum", "deforum_interface")]
script_callbacks.on_ui_tabs(on_ui_tabs)
|