Spaces:
Configuration error
Configuration error
import importlib | |
import os | |
import platform | |
import shutil | |
import subprocess as sp | |
import sys | |
import gradio as gr | |
import modules | |
import modules.scripts as scripts | |
from modules import ( | |
script_callbacks, | |
shared, | |
call_queue, | |
sd_samplers, | |
ui_prompt_styles, | |
sd_models, | |
) | |
from modules.call_queue import wrap_gradio_gpu_call | |
from modules.images import image_data | |
from modules.shared import opts | |
from modules.ui import ( | |
ordered_ui_categories, | |
create_sampler_and_steps_selection, | |
switch_values_symbol, | |
create_override_settings_dropdown, | |
detect_image_size_symbol, | |
plaintext_to_html, | |
paste_symbol, | |
clear_prompt_symbol, | |
restore_progress_symbol, | |
) | |
from modules.ui_common import ( | |
folder_symbol, | |
update_generation_info, | |
create_refresh_button, | |
) | |
from modules.ui_components import ( | |
ResizeHandleRow, | |
FormRow, | |
ToolButton, | |
FormGroup, | |
InputAccordion, | |
) | |
from scripts import m2m_hook as patches | |
from scripts import m2m_util | |
from scripts import mov2mov | |
from scripts.mov2mov import scripts_mov2mov | |
from scripts.m2m_config import mov2mov_outpath_samples, mov2mov_output_dir | |
from scripts.movie_editor import MovieEditor | |
id_part = "mov2mov" | |
def save_video(video): | |
path = "logs/movies" | |
if not os.path.exists(path): | |
os.makedirs(path, exist_ok=True) | |
index = len([path for path in os.listdir(path) if path.endswith(".mp4")]) + 1 | |
video_path = os.path.join(path, str(index).zfill(5) + ".mp4") | |
shutil.copyfile(video, video_path) | |
filename = os.path.relpath(video_path, path) | |
return gr.File.update(value=video_path, visible=True), plaintext_to_html( | |
f"Saved: {filename}" | |
) | |
class Toprow: | |
"""Creates a top row UI with prompts, generate button, styles, extra little buttons for things, and enables some functionality related to their operation""" | |
def __init__(self, is_img2img, id_part=None): | |
if not id_part: | |
id_part = "img2img" if is_img2img else "txt2img" | |
self.id_part = id_part | |
with gr.Row(elem_id=f"{id_part}_toprow", variant="compact"): | |
with gr.Column(elem_id=f"{id_part}_prompt_container", scale=6): | |
with gr.Row(): | |
with gr.Column(scale=80): | |
with gr.Row(): | |
self.prompt = gr.Textbox( | |
label="Prompt", | |
elem_id=f"{id_part}_prompt", | |
show_label=False, | |
lines=3, | |
placeholder="Prompt (press Ctrl+Enter or Alt+Enter to generate)", | |
elem_classes=["prompt"], | |
) | |
self.prompt_img = gr.File( | |
label="", | |
elem_id=f"{id_part}_prompt_image", | |
file_count="single", | |
type="binary", | |
visible=False, | |
) | |
with gr.Row(): | |
with gr.Column(scale=80): | |
with gr.Row(): | |
self.negative_prompt = gr.Textbox( | |
label="Negative prompt", | |
elem_id=f"{id_part}_neg_prompt", | |
show_label=False, | |
lines=3, | |
placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)", | |
elem_classes=["prompt"], | |
) | |
self.button_interrogate = None | |
self.button_deepbooru = None | |
if is_img2img: | |
with gr.Column(scale=1, elem_classes="interrogate-col"): | |
self.button_interrogate = gr.Button( | |
"Interrogate\nCLIP", elem_id="interrogate" | |
) | |
self.button_deepbooru = gr.Button( | |
"Interrogate\nDeepBooru", elem_id="deepbooru" | |
) | |
with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"): | |
with gr.Row( | |
elem_id=f"{id_part}_generate_box", elem_classes="generate-box" | |
): | |
self.interrupt = gr.Button( | |
"Interrupt", | |
elem_id=f"{id_part}_interrupt", | |
elem_classes="generate-box-interrupt", | |
) | |
self.skip = gr.Button( | |
"Skip", | |
elem_id=f"{id_part}_skip", | |
elem_classes="generate-box-skip", | |
) | |
self.submit = gr.Button( | |
"Generate", elem_id=f"{id_part}_generate", variant="primary" | |
) | |
self.skip.click( | |
fn=lambda: shared.state.skip(), | |
inputs=[], | |
outputs=[], | |
) | |
self.interrupt.click( | |
fn=lambda: shared.state.interrupt(), | |
inputs=[], | |
outputs=[], | |
) | |
with gr.Row(elem_id=f"{id_part}_tools"): | |
self.paste = ToolButton(value=paste_symbol, elem_id="paste") | |
self.clear_prompt_button = ToolButton( | |
value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt" | |
) | |
self.restore_progress_button = ToolButton( | |
value=restore_progress_symbol, | |
elem_id=f"{id_part}_restore_progress", | |
visible=False, | |
) | |
self.token_counter = gr.HTML( | |
value="<span>0/75</span>", | |
elem_id=f"{id_part}_token_counter", | |
elem_classes=["token-counter"], | |
) | |
self.token_button = gr.Button( | |
visible=False, elem_id=f"{id_part}_token_button" | |
) | |
self.negative_token_counter = gr.HTML( | |
value="<span>0/75</span>", | |
elem_id=f"{id_part}_negative_token_counter", | |
elem_classes=["token-counter"], | |
) | |
self.negative_token_button = gr.Button( | |
visible=False, elem_id=f"{id_part}_negative_token_button" | |
) | |
self.clear_prompt_button.click( | |
fn=lambda *x: x, | |
_js="confirm_clear_prompt", | |
inputs=[self.prompt, self.negative_prompt], | |
outputs=[self.prompt, self.negative_prompt], | |
) | |
self.ui_styles = ui_prompt_styles.UiPromptStyles( | |
id_part, self.prompt, self.negative_prompt | |
) | |
self.prompt_img.change( | |
fn=modules.images.image_data, | |
inputs=[self.prompt_img], | |
outputs=[self.prompt, self.prompt_img], | |
show_progress=False, | |
) | |
def create_output_panel(tabname, outdir): | |
def open_folder(f): | |
if not os.path.exists(f): | |
print( | |
f'Folder "{f}" does not exist. After you create an image, the folder will be created.' | |
) | |
return | |
elif not os.path.isdir(f): | |
print( | |
f""" | |
WARNING | |
An open_folder request was made with an argument that is not a folder. | |
This could be an error or a malicious attempt to run code on your computer. | |
Requested path was: {f} | |
""", | |
file=sys.stderr, | |
) | |
return | |
if not shared.cmd_opts.hide_ui_dir_config: | |
path = os.path.normpath(f) | |
if platform.system() == "Windows": | |
os.startfile(path) | |
elif platform.system() == "Darwin": | |
sp.Popen(["open", path]) | |
elif "microsoft-standard-WSL2" in platform.uname().release: | |
sp.Popen(["wsl-open", path]) | |
else: | |
sp.Popen(["xdg-open", path]) | |
with gr.Column(variant="panel", elem_id=f"{tabname}_results"): | |
with gr.Group(elem_id=f"{tabname}_gallery_container"): | |
result_gallery = gr.Gallery( | |
label="Output", | |
show_label=False, | |
elem_id=f"{tabname}_gallery", | |
columns=4, | |
preview=True, | |
height=shared.opts.gallery_height or None, | |
) | |
result_video = gr.PlayableVideo( | |
label="Output Video", show_label=False, elem_id=f"{tabname}_video" | |
) | |
generation_info = None | |
with gr.Column(): | |
with gr.Row( | |
elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons" | |
): | |
open_folder_button = ToolButton( | |
folder_symbol, | |
elem_id=f"{tabname}_open_folder", | |
visible=not shared.cmd_opts.hide_ui_dir_config, | |
tooltip="Open images output directory.", | |
) | |
if tabname != "extras": | |
save = ToolButton( | |
"💾", | |
elem_id=f"save_{tabname}", | |
tooltip=f"Save the image to a dedicated directory ({shared.opts.outdir_save}).", | |
) | |
open_folder_button.click( | |
fn=lambda: open_folder(shared.opts.outdir_samples or outdir), | |
inputs=[], | |
outputs=[], | |
) | |
download_files = gr.File( | |
None, | |
file_count="multiple", | |
interactive=False, | |
show_label=False, | |
visible=False, | |
elem_id=f"download_files_{tabname}", | |
) | |
with gr.Group(): | |
html_info = gr.HTML( | |
elem_id=f"html_info_{tabname}", elem_classes="infotext" | |
) | |
html_log = gr.HTML( | |
elem_id=f"html_log_{tabname}", elem_classes="html-log" | |
) | |
generation_info = gr.Textbox( | |
visible=False, elem_id=f"generation_info_{tabname}" | |
) | |
if tabname == "txt2img" or tabname == "img2img" or tabname == "mov2mov": | |
generation_info_button = gr.Button( | |
visible=False, elem_id=f"{tabname}_generation_info_button" | |
) | |
generation_info_button.click( | |
fn=update_generation_info, | |
_js="function(x, y, z){ return [x, y, selected_gallery_index()] }", | |
inputs=[generation_info, html_info, html_info], | |
outputs=[html_info, html_info], | |
show_progress=False, | |
) | |
save.click( | |
fn=call_queue.wrap_gradio_call(save_video), | |
inputs=[result_video], | |
outputs=[ | |
download_files, | |
html_log, | |
], | |
show_progress=False, | |
) | |
return result_gallery, result_video, generation_info, html_info, html_log | |
def create_refiner(): | |
with InputAccordion( | |
False, label="Refiner", elem_id=f"{id_part}_enable" | |
) as enable_refiner: | |
with gr.Row(): | |
refiner_checkpoint = gr.Dropdown( | |
label="Checkpoint", | |
elem_id=f"{id_part}_checkpoint", | |
choices=sd_models.checkpoint_tiles(), | |
value="", | |
tooltip="switch to another model in the middle of generation", | |
) | |
create_refresh_button( | |
refiner_checkpoint, | |
sd_models.list_models, | |
lambda: {"choices": sd_models.checkpoint_tiles()}, | |
f"{id_part}_checkpoint_refresh", | |
) | |
refiner_switch_at = gr.Slider( | |
value=0.8, | |
label="Switch at", | |
minimum=0.01, | |
maximum=1.0, | |
step=0.01, | |
elem_id=f"{id_part}_switch_at", | |
tooltip="fraction of sampling steps when the switch to refiner model should happen; 1=never, 0.5=switch in the middle of generation", | |
) | |
return enable_refiner, refiner_checkpoint, refiner_switch_at | |
def on_ui_tabs(): | |
scripts_mov2mov.initialize_scripts(is_img2img=True) | |
# with gr.Blocks(analytics_enabled=False) as mov2mov_interface: | |
with gr.TabItem( | |
"mov2mov", id=f"tab_{id_part}", elem_id=f"tab_{id_part}" | |
) as mov2mov_interface: | |
toprow = Toprow(is_img2img=False, id_part=id_part) | |
dummy_component = gr.Label(visible=False) | |
with gr.Tab( | |
"Generation", id=f"{id_part}_generation" | |
) as mov2mov_generation_tab, ResizeHandleRow(equal_height=False): | |
with gr.Column(variant="compact", elem_id="mov2mov_settings"): | |
with gr.Tabs(elem_id=f"mode_{id_part}"): | |
init_mov = gr.Video( | |
label="Video for mov2mov", | |
elem_id=f"{id_part}_mov", | |
show_label=False, | |
source="upload", | |
) | |
with FormRow(): | |
resize_mode = gr.Radio( | |
label="Resize mode", | |
elem_id=f"{id_part}_resize_mode", | |
choices=[ | |
"Just resize", | |
"Crop and resize", | |
"Resize and fill", | |
"Just resize (latent upscale)", | |
], | |
type="index", | |
value="Just resize", | |
) | |
scripts_mov2mov.prepare_ui() | |
for category in ordered_ui_categories(): | |
if category == "sampler": | |
steps, sampler_name = create_sampler_and_steps_selection( | |
sd_samplers.visible_sampler_names(), id_part | |
) | |
elif category == "dimensions": | |
with FormRow(): | |
with gr.Column(elem_id=f"{id_part}_column_size", scale=4): | |
with gr.Tabs(): | |
with gr.Tab( | |
label="Resize to", | |
elem_id=f"{id_part}_tab_resize_to", | |
) as tab_scale_to: | |
with FormRow(): | |
with gr.Column( | |
elem_id=f"{id_part}_column_size", | |
scale=4, | |
): | |
width = gr.Slider( | |
minimum=64, | |
maximum=2048, | |
step=8, | |
label="Width", | |
value=512, | |
elem_id=f"{id_part}_width", | |
) | |
height = gr.Slider( | |
minimum=64, | |
maximum=2048, | |
step=8, | |
label="Height", | |
value=512, | |
elem_id=f"{id_part}_height", | |
) | |
with gr.Column( | |
elem_id=f"{id_part}_dimensions_row", | |
scale=1, | |
elem_classes="dimensions-tools", | |
): | |
res_switch_btn = ToolButton( | |
value=switch_values_symbol, | |
elem_id=f"{id_part}_res_switch_btn", | |
) | |
detect_image_size_btn = ToolButton( | |
value=detect_image_size_symbol, | |
elem_id=f"{id_part}_detect_image_size_btn", | |
) | |
elif category == "denoising": | |
denoising_strength = gr.Slider( | |
minimum=0.0, | |
maximum=1.0, | |
step=0.01, | |
label="Denoising strength", | |
value=0.75, | |
elem_id=f"{id_part}_denoising_strength", | |
) | |
noise_multiplier = gr.Slider( | |
minimum=0, | |
maximum=1.5, | |
step=0.01, | |
label="Noise multiplier", | |
elem_id=f"{id_part}_noise_multiplier", | |
value=1, | |
) | |
with gr.Row(elem_id=f"{id_part}_frames_setting"): | |
movie_frames = gr.Slider( | |
minimum=10, | |
maximum=60, | |
step=1, | |
label="Movie FPS", | |
elem_id=f"{id_part}_movie_frames", | |
value=30, | |
) | |
max_frames = gr.Number( | |
label="Max FPS", | |
value=-1, | |
elem_id=f"{id_part}_max_frames", | |
) | |
elif category == "cfg": | |
with gr.Row(): | |
cfg_scale = gr.Slider( | |
minimum=1.0, | |
maximum=30.0, | |
step=0.5, | |
label="CFG Scale", | |
value=7.0, | |
elem_id=f"{id_part}_cfg_scale", | |
) | |
image_cfg_scale = gr.Slider( | |
minimum=0, | |
maximum=3.0, | |
step=0.05, | |
label="Image CFG Scale", | |
value=1.5, | |
elem_id=f"{id_part}_image_cfg_scale", | |
visible=False, | |
) | |
elif category == "checkboxes": | |
with FormRow(elem_classes="checkboxes-row", variant="compact"): | |
pass | |
elif category == "accordions": | |
with gr.Row( | |
elem_id=f"{id_part}_accordions", elem_classes="accordions" | |
): | |
scripts_mov2mov.setup_ui_for_section(category) | |
elif category == "override_settings": | |
with FormRow(elem_id=f"{id_part}_override_settings_row") as row: | |
override_settings = create_override_settings_dropdown( | |
"mov2mov", row | |
) | |
elif category == "scripts": | |
editor = MovieEditor(id_part, init_mov, movie_frames) | |
editor.render() | |
with FormGroup(elem_id=f"{id_part}_script_container"): | |
custom_inputs = scripts_mov2mov.setup_ui() | |
if category not in {"accordions"}: | |
scripts_mov2mov.setup_ui_for_section(category) | |
( | |
mov2mov_gallery, | |
result_video, | |
generation_info, | |
html_info, | |
html_log, | |
) = create_output_panel(id_part, opts.mov2mov_output_dir) | |
res_switch_btn.click( | |
fn=None, | |
_js="function(){switchWidthHeight('mov2mov')}", | |
inputs=None, | |
outputs=None, | |
show_progress=False, | |
) | |
# calc video size | |
detect_image_size_btn.click( | |
fn=calc_video_w_h, | |
inputs=[init_mov, width, height], | |
outputs=[width, height], | |
) | |
mov2mov_args = dict( | |
fn=wrap_gradio_gpu_call(mov2mov.mov2mov, extra_outputs=[None, "", ""]), | |
_js="submit_mov2mov", | |
inputs=[ | |
dummy_component, | |
toprow.prompt, | |
toprow.negative_prompt, | |
toprow.ui_styles.dropdown, | |
init_mov, | |
steps, | |
sampler_name, | |
cfg_scale, | |
image_cfg_scale, | |
denoising_strength, | |
height, | |
width, | |
resize_mode, | |
override_settings, | |
# refiner | |
# enable_refiner, refiner_checkpoint, refiner_switch_at, | |
# mov2mov params | |
noise_multiplier, | |
movie_frames, | |
max_frames, | |
# editor | |
editor.gr_enable_movie_editor, | |
editor.gr_df, | |
editor.gr_eb_weight, | |
] | |
+ custom_inputs, | |
outputs=[ | |
result_video, | |
generation_info, | |
html_info, | |
html_log, | |
], | |
show_progress=False, | |
) | |
toprow.submit.click(**mov2mov_args) | |
return [(mov2mov_interface, "mov2mov", f"{id_part}_tabs")] | |
def calc_video_w_h(video, width, height): | |
if not video: | |
return width, height | |
return m2m_util.calc_video_w_h(video) | |
def on_ui_settings(): | |
section = ("mov2mov", "Mov2Mov") | |
shared.opts.add_option( | |
"mov2mov_outpath_samples", | |
shared.OptionInfo( | |
mov2mov_outpath_samples, "Mov2Mov output path for image", section=section | |
), | |
) | |
shared.opts.add_option( | |
"mov2mov_output_dir", | |
shared.OptionInfo( | |
mov2mov_output_dir, "Mov2Mov output path for video", section=section | |
), | |
) | |
img2img_toprow: gr.Row = None | |
def block_context_init(self, *args, **kwargs): | |
origin_block_context_init(self, *args, **kwargs) | |
if self.elem_id == "tab_img2img": | |
self.parent.__enter__() | |
on_ui_tabs() | |
self.parent.__exit__() | |
def on_app_reload(): | |
global origin_block_context_init | |
if origin_block_context_init: | |
patches.undo(__name__, obj=gr.blocks.BlockContext, field="__init__") | |
origin_block_context_init = None | |
origin_block_context_init = patches.patch( | |
__name__, | |
obj=gr.blocks.BlockContext, | |
field="__init__", | |
replacement=block_context_init, | |
) | |
script_callbacks.on_before_reload(on_app_reload) | |
script_callbacks.on_ui_settings(on_ui_settings) | |
# script_callbacks.on_ui_tabs(on_ui_tabs) | |