mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 17:24:32 +02:00
@@ -1,5 +1,16 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2025-01-16
|
||||
|
||||
- **Gallery**:
|
||||
- add http fallback for slow/unreliable links
|
||||
- **Fixes**:
|
||||
- non-full vae decode
|
||||
- send-to image transfer
|
||||
- sana vae tiling
|
||||
- increase gallery timeouts
|
||||
- update ui element ids
|
||||
|
||||
## Update for 2025-01-15
|
||||
|
||||
### Highlights for 2025-01-15
|
||||
|
||||
Submodule extensions-builtin/sdnext-modernui updated: 2960e36797...c17c539281
+2
-2
@@ -492,7 +492,7 @@ def check_diffusers():
|
||||
t_start = time.time()
|
||||
if args.skip_all or args.skip_git:
|
||||
return
|
||||
sha = 'c944f0651f679728d4ec7b6488120ac49c2f1315' # diffusers commit hash
|
||||
sha = 'b785ddb654e4be3ae0066e231734754bdb2a191c' # diffusers commit hash
|
||||
pkg = pkg_resources.working_set.by_key.get('diffusers', None)
|
||||
minor = int(pkg.version.split('.')[1] if pkg is not None else 0)
|
||||
cur = opts.get('diffusers_version', '') if minor > 0 else ''
|
||||
@@ -876,7 +876,7 @@ def install_packages():
|
||||
if args.profile:
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
log.info('Verifying packages')
|
||||
# log.info('Install: verifying packages')
|
||||
clip_package = os.environ.get('CLIP_PACKAGE', "git+https://github.com/openai/CLIP.git")
|
||||
install(clip_package, 'clip', quiet=True)
|
||||
install('open-clip-torch', no_deps=True, quiet=True)
|
||||
|
||||
@@ -12,7 +12,7 @@ function dimensionChange(e, is_width, is_height) {
|
||||
if (tabIndex === 0) targetElement = gradioApp().querySelector('#img2img_image div[data-testid=image] img'); // img2img
|
||||
else if (tabIndex === 1) targetElement = gradioApp().querySelector('#img2img_sketch div[data-testid=image] img'); // Sketch
|
||||
else if (tabIndex === 2) targetElement = gradioApp().querySelector('#img2maskimg div[data-testid=image] img'); // Inpaint
|
||||
else if (tabIndex === 3) targetElement = gradioApp().querySelector('#inpaint_sketch div[data-testid=image] img'); // Inpaint sketch
|
||||
else if (tabIndex === 3) targetElement = gradioApp().querySelector('#composite div[data-testid=image] img'); // Inpaint sketch
|
||||
|
||||
if (targetElement) {
|
||||
let arPreviewRect = gradioApp().querySelector('#imageARPreview');
|
||||
|
||||
+45
-5
@@ -46,7 +46,7 @@ class GalleryFolder extends HTMLElement {
|
||||
else folder.shadow.children[1].classList.remove('gallery-folder-selected');
|
||||
}
|
||||
});
|
||||
div.addEventListener('click', fetchFiles); // eslint-disable-line no-use-before-define
|
||||
div.addEventListener('click', fetchFilesWS); // eslint-disable-line no-use-before-define
|
||||
this.shadow.appendChild(div);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +224,7 @@ async function getHash(str, algo = 'SHA-256') {
|
||||
}
|
||||
}
|
||||
|
||||
async function wsConnect(socket, timeout = 2000) {
|
||||
async function wsConnect(socket, timeout = 5000) {
|
||||
const intrasleep = 100;
|
||||
const ttl = timeout / intrasleep;
|
||||
const isOpened = () => (socket.readyState === WebSocket.OPEN);
|
||||
@@ -327,17 +327,57 @@ async function gallerySort(btn) {
|
||||
el.status.innerText = `Sort | ${arr.length.toLocaleString()} images | ${Math.floor(t1 - t0).toLocaleString()}ms`;
|
||||
}
|
||||
|
||||
async function fetchFiles(evt) { // fetch file-by-file list over websockets
|
||||
async function fetchFilesHT(evt) {
|
||||
el.status.innerText = `Folder | ${evt.target.name}`;
|
||||
const t0 = performance.now();
|
||||
const fragment = document.createDocumentFragment();
|
||||
el.status.innerText = `Folder | ${evt.target.name} | in-progress`;
|
||||
let numFiles = 0;
|
||||
|
||||
const res = await fetch(`/sdapi/v1/browser/files?folder=${encodeURI(evt.target.name)}`);
|
||||
if (!res || res.status !== 200) {
|
||||
el.status.innerText = `Folder | ${evt.target.name} | failed: ${res?.statusText}`;
|
||||
return;
|
||||
}
|
||||
const jsonData = await res.json();
|
||||
for (const line of jsonData) {
|
||||
const data = decodeURI(line).split('##F##');
|
||||
numFiles++;
|
||||
const f = new GalleryFile(data[0], data[1]);
|
||||
fragment.appendChild(f);
|
||||
}
|
||||
|
||||
el.files.appendChild(fragment);
|
||||
|
||||
const t1 = performance.now();
|
||||
log(`gallery: folder=${evt.target.name} num=${numFiles} time=${Math.floor(t1 - t0)}ms`);
|
||||
el.status.innerText = `Folder | ${evt.target.name} | ${numFiles.toLocaleString()} images | ${Math.floor(t1 - t0).toLocaleString()}ms`;
|
||||
addSeparators();
|
||||
}
|
||||
|
||||
async function fetchFilesWS(evt) { // fetch file-by-file list over websockets
|
||||
el.files.innerHTML = '';
|
||||
if (!url) return;
|
||||
if (ws && ws.readyState === WebSocket.OPEN) ws.close(); // abort previous request
|
||||
ws = new WebSocket(`${url}/sdapi/v1/browser/files`);
|
||||
await wsConnect(ws);
|
||||
let wsConnected = false;
|
||||
try {
|
||||
ws = new WebSocket(`${url}/sdapi/v1/browser/files`);
|
||||
wsConnected = await wsConnect(ws);
|
||||
} catch (err) {
|
||||
log('gallery: ws connect error', err);
|
||||
return;
|
||||
}
|
||||
log(`gallery: connected=${wsConnected} state=${ws?.readyState} url=${ws?.url}`);
|
||||
if (!wsConnected) {
|
||||
await fetchFilesHT(evt); // fallback to http
|
||||
return;
|
||||
}
|
||||
el.status.innerText = `Folder | ${evt.target.name}`;
|
||||
const t0 = performance.now();
|
||||
let numFiles = 0;
|
||||
let t1 = performance.now();
|
||||
let fragment = document.createDocumentFragment();
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
numFiles++;
|
||||
t1 = performance.now();
|
||||
|
||||
@@ -36,12 +36,6 @@ input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { margin-left
|
||||
.gradio-image { min-height: fit-content; }
|
||||
.gradio-image img { object-fit: contain; }
|
||||
*/
|
||||
/*
|
||||
.gradio-image { min-height: 200px !important; }
|
||||
.image-container { height: unset !important; }
|
||||
.control-image { height: unset !important; }
|
||||
#img2img_sketch, #img2maskimg, #inpaint_sketch { overflow: overlay !important; resize: auto; background: var(--panel-background-fill); z-index: 5; }
|
||||
*/
|
||||
|
||||
/* color elements */
|
||||
.gradio-dropdown, .block.gradio-slider, .block.gradio-checkbox, .block.gradio-textbox, .block.gradio-radio, .block.gradio-checkboxgroup, .block.gradio-number, .block.gradio-colorpicker { border-width: 0 !important; box-shadow: none !important;}
|
||||
|
||||
+19
-1
@@ -154,6 +154,24 @@ def register_api(app: FastAPI): # register api
|
||||
content = { 'error': str(e) }
|
||||
return JSONResponse(content=content)
|
||||
|
||||
@app.get("/sdapi/v1/browser/files", response_model=list)
|
||||
async def ht_files(folder: str):
|
||||
try:
|
||||
t0 = time.time()
|
||||
files = files_cache.directory_files(folder, recursive=True)
|
||||
lines = []
|
||||
for f in files:
|
||||
file = os.path.relpath(f, folder)
|
||||
msg = quote(folder) + '##F##' + quote(file)
|
||||
msg = msg[:1] + ":" + msg[4:] if msg[1:4] == "%3A" else msg
|
||||
lines.append(msg)
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Gallery: type=ht folder="{folder}" files={len(lines)} time={t1-t0:.3f}')
|
||||
return lines
|
||||
except Exception as e:
|
||||
shared.log.error(f'Gallery: {folder} {e}')
|
||||
return []
|
||||
|
||||
@app.websocket("/sdapi/v1/browser/files")
|
||||
async def ws_files(ws: WebSocket):
|
||||
try:
|
||||
@@ -173,7 +191,7 @@ def register_api(app: FastAPI): # register api
|
||||
await manager.send(ws, msg)
|
||||
await manager.send(ws, '#END#')
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Gallery: folder="{folder}" files={numFiles} time={t1-t0:.3f}')
|
||||
shared.log.debug(f'Gallery: type=ws folder="{folder}" files={numFiles} time={t1-t0:.3f}')
|
||||
except WebSocketDisconnect:
|
||||
debug('Browser WS unexpected disconnect')
|
||||
manager.disconnect(ws)
|
||||
|
||||
@@ -105,12 +105,12 @@ def create_buttons(tabs_list):
|
||||
return buttons
|
||||
|
||||
|
||||
def bind_buttons(buttons, send_image, send_generate_info):
|
||||
def bind_buttons(buttons, image_component, send_generate_info):
|
||||
"""old function for backwards compatibility; do not use this, use register_paste_params_button"""
|
||||
for tabname, button in buttons.items():
|
||||
source_text_component = send_generate_info if isinstance(send_generate_info, gr.components.Component) else None
|
||||
source_tabname = send_generate_info if isinstance(send_generate_info, str) else None
|
||||
bindings = ParamBinding(paste_button=button, tabname=tabname, source_text_component=source_text_component, source_image_component=send_image, source_tabname=source_tabname)
|
||||
bindings = ParamBinding(paste_button=button, tabname=tabname, source_text_component=source_text_component, source_image_component=image_component, source_tabname=source_tabname)
|
||||
register_paste_params_button(bindings)
|
||||
|
||||
|
||||
@@ -124,27 +124,18 @@ def connect_paste_params_buttons():
|
||||
if binding.tabname not in paste_fields:
|
||||
debug(f"Not not registered: tab={binding.tabname}")
|
||||
continue
|
||||
"""
|
||||
# legacy code that sets width/height based on image itself instead of metadata
|
||||
fields = paste_fields[binding.tabname]["fields"]
|
||||
|
||||
destination_image_component = paste_fields[binding.tabname]["init_img"]
|
||||
destination_width_component = next(iter([field for field, name in fields if name == "Size-1"] if fields else []), None)
|
||||
destination_height_component = next(iter([field for field, name in fields if name == "Size-2"] if fields else []), None)
|
||||
if binding.source_image_component and destination_image_component:
|
||||
if isinstance(binding.source_image_component, gr.Gallery):
|
||||
func = send_image_and_dimensions if destination_width_component else image_from_url_text
|
||||
jsfunc = "extract_image_from_gallery"
|
||||
else:
|
||||
func = send_image_and_dimensions if destination_width_component else lambda x: x
|
||||
jsfunc = None
|
||||
binding.paste_button.click(
|
||||
fn=func,
|
||||
_js=jsfunc,
|
||||
_js="extract_image_from_gallery" if isinstance(binding.source_image_component, gr.Gallery) else None,
|
||||
fn=send_image,
|
||||
inputs=[binding.source_image_component],
|
||||
outputs=[destination_image_component, destination_width_component, destination_height_component] if destination_width_component else [destination_image_component],
|
||||
outputs=[destination_image_component],
|
||||
show_progress=False,
|
||||
)
|
||||
"""
|
||||
fields = paste_fields[binding.tabname]["fields"]
|
||||
|
||||
override_settings_component = binding.override_settings_component or paste_fields[binding.tabname]["override_settings_component"]
|
||||
if binding.source_text_component is not None and fields is not None:
|
||||
connect_paste(binding.paste_button, fields, binding.source_text_component, override_settings_component, binding.tabname)
|
||||
@@ -165,15 +156,20 @@ def connect_paste_params_buttons():
|
||||
)
|
||||
|
||||
|
||||
def send_image(x):
|
||||
image = x if isinstance(x, Image.Image) else image_from_url_text(x)
|
||||
return image
|
||||
|
||||
|
||||
def send_image_and_dimensions(x):
|
||||
img = x if isinstance(x, Image.Image) else image_from_url_text(x)
|
||||
if shared.opts.send_size and isinstance(img, Image.Image):
|
||||
w = img.width
|
||||
h = img.height
|
||||
image = x if isinstance(x, Image.Image) else image_from_url_text(x)
|
||||
if shared.opts.send_size and isinstance(image, Image.Image):
|
||||
w = image.width
|
||||
h = image.height
|
||||
else:
|
||||
w = gr.update()
|
||||
h = gr.update()
|
||||
return img, w, h
|
||||
return image, w, h
|
||||
|
||||
|
||||
def create_override_settings_dict(text_pairs):
|
||||
|
||||
@@ -180,8 +180,8 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:t
|
||||
if not chi:
|
||||
args['complex_human_instruction'] = None
|
||||
if 'use_resolution_binning' in possible:
|
||||
args['use_resolution_binning'] = True
|
||||
p.extra_generation_params["Binning"] = True
|
||||
args['use_resolution_binning'] = False
|
||||
# p.extra_generation_params["Binning"] = True
|
||||
if prompt_parser_diffusers.embedder is not None and not prompt_parser_diffusers.embedder.scheduled_prompt: # not scheduled so we dont need it anymore
|
||||
prompt_parser_diffusers.embedder = None
|
||||
|
||||
|
||||
+15
-18
@@ -58,16 +58,11 @@ def full_vqgan_decode(latents, model):
|
||||
if scaling_factor:
|
||||
latents = latents * scaling_factor
|
||||
|
||||
vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default"
|
||||
vae_stats = f'name="{vae_name}" dtype={model.vqgan.dtype} device={model.vqgan.device}'
|
||||
latents_stats = f'shape={latents.shape} dtype={latents.dtype} device={latents.device}'
|
||||
stats = f'vae {vae_stats} latents {latents_stats}'
|
||||
|
||||
log_debug(f'VAE config: {model.vqgan.config}')
|
||||
try:
|
||||
decoded = model.vqgan.decode(latents).sample.clamp(0, 1)
|
||||
except Exception as e:
|
||||
shared.log.error(f'VAE decode: {stats} {e}')
|
||||
shared.log.error(f'VAE decode: {e}')
|
||||
errors.display(e, 'VAE decode')
|
||||
decoded = []
|
||||
|
||||
@@ -85,7 +80,8 @@ def full_vqgan_decode(latents, model):
|
||||
t1 = time.time()
|
||||
if debug:
|
||||
log_debug(f'VAE memory: {shared.mem_mon.read()}')
|
||||
shared.log.debug(f'VAE decode: {stats} time={round(t1-t0, 3)}')
|
||||
vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default"
|
||||
shared.log.debug(f'VAE decode: vae="{vae_name}" type="vqgan" dtype={model.vqgan.dtype} device={model.vqgan.device} time={round(t1-t0, 3)}')
|
||||
return decoded
|
||||
|
||||
|
||||
@@ -103,7 +99,6 @@ def full_vae_decode(latents, model):
|
||||
base_device = None
|
||||
if shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False):
|
||||
base_device = sd_models.move_base(model, devices.cpu)
|
||||
|
||||
elif shared.opts.diffusers_offload_mode != "sequential":
|
||||
sd_models.move_model(model.vae, devices.device)
|
||||
|
||||
@@ -134,17 +129,12 @@ def full_vae_decode(latents, model):
|
||||
if shift_factor:
|
||||
latents = latents + shift_factor
|
||||
|
||||
vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default"
|
||||
vae_stats = f'vae="{vae_name}" dtype={model.vae.dtype} device={model.vae.device} upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)}'
|
||||
latents_stats = f'latents={latents.shape}:{latents.device}:{latents.dtype}'
|
||||
stats = f'{vae_stats} {latents_stats}'
|
||||
|
||||
log_debug(f'VAE config: {model.vae.config}')
|
||||
try:
|
||||
with devices.inference_context():
|
||||
decoded = model.vae.decode(latents, return_dict=False)[0]
|
||||
except Exception as e:
|
||||
shared.log.error(f'VAE decode: {stats} {e}')
|
||||
shared.log.error(f'VAE decode: {e}')
|
||||
if 'out of memory' not in str(e):
|
||||
errors.display(e, 'VAE decode')
|
||||
decoded = []
|
||||
@@ -162,21 +152,24 @@ def full_vae_decode(latents, model):
|
||||
|
||||
elif shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False) and base_device is not None:
|
||||
sd_models.move_base(model, base_device)
|
||||
|
||||
t1 = time.time()
|
||||
if debug:
|
||||
log_debug(f'VAE memory: {shared.mem_mon.read()}')
|
||||
shared.log.debug(f'Decode: {stats} time={round(t1-t0, 3)}')
|
||||
vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default"
|
||||
shared.log.debug(f'Decode: vae="{vae_name}" upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)} latents={latents.shape}:{latents.device}:{latents.dtype} time={t1-t0:.3f}')
|
||||
return decoded
|
||||
|
||||
|
||||
def full_vae_encode(image, model):
|
||||
log_debug(f'VAE encode: name={sd_vae.loaded_vae_file if sd_vae.loaded_vae_file is not None else "baked"} dtype={model.vae.dtype} upcast={model.vae.config.get("force_upcast", None)}')
|
||||
if shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False) and hasattr(model, 'unet'):
|
||||
log_debug('Moving to CPU: model=UNet')
|
||||
unet_device = model.unet.device
|
||||
sd_models.move_model(model.unet, devices.cpu)
|
||||
if not shared.opts.diffusers_offload_mode == "sequential" and hasattr(model, 'vae'):
|
||||
sd_models.move_model(model.vae, devices.device)
|
||||
vae_name = sd_vae.loaded_vae_file if sd_vae.loaded_vae_file is not None else "default"
|
||||
log_debug(f'Encode vae="{vae_name}" dtype={model.vae.dtype} upcast={model.vae.config.get("force_upcast", None)}')
|
||||
encoded = model.vae.encode(image.to(model.vae.device, model.vae.dtype)).latent_dist.sample()
|
||||
if shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False) and hasattr(model, 'unet'):
|
||||
sd_models.move_model(model.unet, unet_device)
|
||||
@@ -184,7 +177,7 @@ def full_vae_encode(image, model):
|
||||
|
||||
|
||||
def taesd_vae_decode(latents):
|
||||
log_debug(f'VAE decode: name=TAESD images={len(latents)} latents={latents.shape} slicing={shared.opts.diffusers_vae_slicing}')
|
||||
t0 = time.time()
|
||||
if len(latents) == 0:
|
||||
return []
|
||||
if shared.opts.diffusers_vae_slicing and len(latents) > 1:
|
||||
@@ -193,11 +186,13 @@ def taesd_vae_decode(latents):
|
||||
decoded[i] = sd_vae_taesd.decode(latents[i])
|
||||
else:
|
||||
decoded = sd_vae_taesd.decode(latents)
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Decode: vae="taesd" latents={latents.shape}:{latents.dtype}:{latents.device} time={t1-t0:.3f}')
|
||||
return decoded
|
||||
|
||||
|
||||
def taesd_vae_encode(image):
|
||||
log_debug(f'VAE encode: name=TAESD image={image.shape}')
|
||||
shared.log.debug(f'Encode: vae="taesd" image={image.shape}')
|
||||
encoded = sd_vae_taesd.encode(image)
|
||||
return encoded
|
||||
|
||||
@@ -243,6 +238,8 @@ def vae_decode(latents, model, output_type='np', full_quality=True, width=None,
|
||||
decoded = 2.0 * decoded - 1.0 # typical normalized range
|
||||
|
||||
if torch.is_tensor(decoded):
|
||||
if len(decoded.shape) == 3 and decoded.shape[0] == 3:
|
||||
decoded = decoded.unsqueeze(0)
|
||||
if hasattr(model, 'video_processor'):
|
||||
imgs = model.video_processor.postprocess_video(decoded, output_type='pil')
|
||||
elif hasattr(model, 'image_processor'):
|
||||
|
||||
@@ -169,7 +169,7 @@ def create_ui(_blocks: gr.Blocks=None):
|
||||
video_skip_frames = gr.Slider(minimum=0, maximum=100, step=1, label='Skip input frames', value=0, elem_id="control_video_skip_frames")
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs()
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs(tab='control')
|
||||
|
||||
enable_hr, hr_sampler_index, hr_denoising_strength, hr_resize_mode, hr_resize_context, hr_upscaler, hr_force, hr_second_pass_steps, hr_scale, hr_resize_x, hr_resize_y, refiner_steps, refiner_start, refiner_prompt, refiner_negative = ui_sections.create_hires_inputs('control')
|
||||
detailer_enabled, detailer_prompt, detailer_negative, detailer_steps, detailer_strength = shared.yolo.ui('control')
|
||||
|
||||
@@ -131,7 +131,7 @@ def create_seed_inputs(tab, reuse_visible=True):
|
||||
return seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w
|
||||
|
||||
|
||||
def create_video_inputs():
|
||||
def create_video_inputs(tab:str):
|
||||
def video_type_change(video_type):
|
||||
return [
|
||||
gr.update(visible=video_type != 'None'),
|
||||
@@ -141,12 +141,12 @@ def create_video_inputs():
|
||||
]
|
||||
with gr.Column():
|
||||
video_codecs = ['None', 'GIF', 'PNG', 'MP4/MP4V', 'MP4/AVC1', 'MP4/JVT3', 'MKV/H264', 'AVI/DIVX', 'AVI/RGBA', 'MJPEG/MJPG', 'MPG/MPG1', 'AVR/AVR1']
|
||||
video_type = gr.Dropdown(label='Video type', choices=video_codecs, value='None')
|
||||
video_type = gr.Dropdown(label='Video type', choices=video_codecs, value='None', elem_id=f"{tab}_video_type")
|
||||
with gr.Column():
|
||||
video_duration = gr.Slider(label='Duration', minimum=0.25, maximum=300, step=0.25, value=2, visible=False)
|
||||
video_loop = gr.Checkbox(label='Loop', value=True, visible=False, elem_id="control_video_loop")
|
||||
video_pad = gr.Slider(label='Pad frames', minimum=0, maximum=24, step=1, value=1, visible=False)
|
||||
video_interpolate = gr.Slider(label='Interpolate frames', minimum=0, maximum=24, step=1, value=0, visible=False)
|
||||
video_duration = gr.Slider(label='Duration', minimum=0.25, maximum=300, step=0.25, value=2, visible=False, elem_id=f"{tab}_video_duration")
|
||||
video_loop = gr.Checkbox(label='Loop', value=True, visible=False, elem_id=f"{tab}_video_loop")
|
||||
video_pad = gr.Slider(label='Pad frames', minimum=0, maximum=24, step=1, value=1, visible=False, elem_id=f"{tab}_video_pad")
|
||||
video_interpolate = gr.Slider(label='Interpolate frames', minimum=0, maximum=24, step=1, value=0, visible=False, elem_id=f"{tab}_video_interpolate")
|
||||
video_type.change(fn=video_type_change, inputs=[video_type], outputs=[video_duration, video_loop, video_pad, video_interpolate])
|
||||
return video_type, video_duration, video_loop, video_pad, video_interpolate
|
||||
|
||||
|
||||
+5
-5
@@ -16,12 +16,12 @@
|
||||
"url": "git+https://github.com/vladmandic/automatic.git"
|
||||
},
|
||||
"scripts": {
|
||||
"venv": "source venv/bin/activate",
|
||||
"start": "python launch.py --debug",
|
||||
"ruff": "ruff check",
|
||||
"venv": ". venv/bin/activate",
|
||||
"start": "npm run venv; python launch.py --debug",
|
||||
"ruff": ". venv/bin/activate && ruff check",
|
||||
"eslint": "eslint javascript/ extensions-builtin/sdnext-modernui/javascript/",
|
||||
"pylint": "pylint *.py modules/ extensions-builtin/",
|
||||
"lint": "npm run eslint; npm run ruff; npm run pylint",
|
||||
"pylint": ". venv/bin/activate && pylint *.py modules/ extensions-builtin/ | grep -v '^*'",
|
||||
"lint": "npm run eslint && npm run ruff && npm run pylint",
|
||||
"test": "cli/test.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -37,7 +37,7 @@ class Script(scripts.Script):
|
||||
return not is_img2img if shared.native else False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML('<a href="https://huggingface.co/rhymes-ai/Allegro">  Allegro Video</a><br>')
|
||||
with gr.Row():
|
||||
@@ -46,7 +46,7 @@ class Script(scripts.Script):
|
||||
override_scheduler = gr.Checkbox(label='Override scheduler', value=True)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [num_frames, override_scheduler, video_type, duration, gif_loop, mp4_pad, mp4_interpolate]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, num_frames, override_scheduler, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
@@ -196,7 +196,7 @@ class Script(scripts.Script):
|
||||
return not is_img2img
|
||||
|
||||
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML("<span>  AnimateDiff</span><br>")
|
||||
with gr.Row():
|
||||
@@ -221,7 +221,7 @@ class Script(scripts.Script):
|
||||
fi_temporal = gr.Slider(label='Temporal frequency', minimum=0.0, maximum=1.0, step=0.05, value=0.25)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [adapter_index, frames, lora_index, strength, latent_mode, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, override_scheduler, fi_method, fi_iters, fi_order, fi_spatial, fi_temporal]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, adapter_index, frames, lora_index, strength, latent_mode, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, override_scheduler, fi_method, fi_iters, fi_order, fi_spatial, fi_temporal): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ class Script(scripts.Script):
|
||||
return shared.native
|
||||
|
||||
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML("<span>  CogVideoX</span><br>")
|
||||
with gr.Row():
|
||||
@@ -46,7 +46,7 @@ class Script(scripts.Script):
|
||||
video = gr.Video(value=None, label='Video', source='upload', width=256, height=256)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, loop, pad, interpolate = create_video_inputs()
|
||||
video_type, duration, loop, pad, interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [model, sampler, frames, guidance, offload, override, video_type, duration, loop, pad, interpolate, image, video]
|
||||
|
||||
def load(self, model):
|
||||
|
||||
@@ -60,7 +60,7 @@ class Script(scripts.Script):
|
||||
return not is_img2img if shared.native else False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML('<a href="https://huggingface.co/tencent/HunyuanVideo">  Hunyuan Video</a><br>')
|
||||
with gr.Row():
|
||||
@@ -72,7 +72,7 @@ class Script(scripts.Script):
|
||||
template = gr.TextArea(label='Prompt processor', lines=3, value=default_template)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [num_frames, tile_frames, override_scheduler, template, video_type, duration, gif_loop, mp4_pad, mp4_interpolate]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, num_frames, tile_frames, override_scheduler, template, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
@@ -20,7 +20,7 @@ class Script(scripts.Script):
|
||||
# return False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
def model_change(model_name):
|
||||
model = next(m for m in MODELS if m['name'] == model_name)
|
||||
return gr.update(value=model['info']), gr.update(visible=model_name == 'PIA'), gr.update(visible=model_name == 'VGen')
|
||||
@@ -47,7 +47,7 @@ class Script(scripts.Script):
|
||||
vg_fps = gr.Slider(label='Change rate', minimum=0.1, maximum=1.0, step=0.1, value=0.5)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
model_name.change(fn=model_change, inputs=[model_name], outputs=[model_info, fi_accordion, vgen_accordion])
|
||||
return [model_name, num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, fi_method, fi_iters, fi_order, fi_spatial, fi_temporal, vg_chunks, vg_fps]
|
||||
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ class Script(scripts.Script):
|
||||
return shared.native
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
def model_change(model):
|
||||
return gr.update(visible=model == 'custom')
|
||||
|
||||
@@ -84,7 +84,7 @@ class Script(scripts.Script):
|
||||
model_custom = gr.Textbox(value='', label='Path to model file', visible=False)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
model.change(fn=model_change, inputs=[model], outputs=[model_custom])
|
||||
return [model, model_custom, decode, sampler, num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, teacache_enable, teacache_threshold]
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ class Script(scripts.Script):
|
||||
return not is_img2img if shared.native else False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML('<a href="https://huggingface.co/genmo/mochi-1-preview">  Mochi.1 Video</a><br>')
|
||||
with gr.Row():
|
||||
num_frames = gr.Slider(label='Frames', minimum=9, maximum=257, step=1, value=45)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
@@ -22,7 +22,7 @@ class Script(scripts.Script):
|
||||
return is_img2img if shared.native else False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
with gr.Row():
|
||||
gr.HTML('<a href="https://huggingface.co/stabilityai/stable-video-diffusion-img2vid">  Stable Video Diffusion</a><br>')
|
||||
with gr.Row():
|
||||
@@ -39,7 +39,7 @@ class Script(scripts.Script):
|
||||
override_resolution = gr.Checkbox(label='Override resolution', value=True)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [model, num_frames, override_resolution, min_guidance_scale, max_guidance_scale, decode_chunk_size, motion_bucket_id, noise_aug_strength, video_type, duration, gif_loop, mp4_pad, mp4_interpolate]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, model, num_frames, override_resolution, min_guidance_scale, max_guidance_scale, decode_chunk_size, motion_bucket_id, noise_aug_strength, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
@@ -29,7 +29,7 @@ class Script(scripts.Script):
|
||||
return not is_img2img if shared.native else False
|
||||
|
||||
# return signature is array of gradio components
|
||||
def ui(self, _is_img2img):
|
||||
def ui(self, is_img2img):
|
||||
|
||||
def model_info_change(model_name):
|
||||
if model_name == 'None':
|
||||
@@ -50,7 +50,7 @@ class Script(scripts.Script):
|
||||
num_frames = gr.Slider(label='Frames', minimum=1, maximum=50, step=1, value=0)
|
||||
with gr.Row():
|
||||
from modules.ui_sections import create_video_inputs
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs()
|
||||
video_type, duration, gif_loop, mp4_pad, mp4_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
return [model_name, use_default, num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate]
|
||||
|
||||
def run(self, p: processing.StableDiffusionProcessing, model_name, use_default, num_frames, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ class Script(scripts.Script):
|
||||
create_video = gr.Checkbox(label='Create video', value=False, elem_id=self.elem_id("xyz_create_video"), container=False)
|
||||
|
||||
with gr.Row(visible=False) as ui_video:
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs()
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
create_video.change(fn=lambda x: gr.update(visible=x), inputs=[create_video], outputs=[ui_video])
|
||||
|
||||
with gr.Row():
|
||||
|
||||
@@ -71,7 +71,7 @@ class Script(scripts.Script):
|
||||
create_video = gr.Checkbox(label='Create video', value=False, elem_id=self.elem_id("xyz_create_video"), container=False)
|
||||
|
||||
with gr.Row(visible=False) as ui_video:
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs()
|
||||
video_type, video_duration, video_loop, video_pad, video_interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
|
||||
create_video.change(fn=lambda x: gr.update(visible=x), inputs=[create_video], outputs=[ui_video])
|
||||
|
||||
with gr.Row():
|
||||
|
||||
Reference in New Issue
Block a user