mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
video: support for scripts/extensions
Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
+4
-3
@@ -1,10 +1,11 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2026-07-27
|
||||
## Update for 2026-07-28
|
||||
|
||||
- **Features**
|
||||
- optimized server startup
|
||||
- video processing preserve audio
|
||||
- startup: optimized server startup
|
||||
- process: preserve audio when processing video
|
||||
- video: support for scripts/extensions
|
||||
- **Fixes**
|
||||
- seedvr quality
|
||||
|
||||
|
||||
Submodule extensions-builtin/sdnext-kanvas updated: dc47fa2129...b985104298
@@ -131,6 +131,11 @@ def print_profile(profiler: cProfile.Profile, msg: str):
|
||||
profile_print(msg, local_profiler=profiler)
|
||||
|
||||
|
||||
def profile(*_args, **_kwargs):
|
||||
# legacy to avoid import errors
|
||||
pass
|
||||
|
||||
|
||||
def package_version(package):
|
||||
try:
|
||||
return importlib.metadata.version(package)
|
||||
|
||||
+36
-48
@@ -1,7 +1,6 @@
|
||||
from threading import Lock
|
||||
from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.exceptions import HTTPException
|
||||
from modules.api.helpers import decode_base64_to_image, encode_pil_to_base64
|
||||
from modules import errors, shared, postprocessing
|
||||
from modules.api import models, helpers
|
||||
@@ -20,6 +19,7 @@ class ResPreprocess(BaseModel):
|
||||
model: str = Field(default='', title="Model", description="The processor model used")
|
||||
image: str = Field(default='', title="Image", description="The processed image in base64 format")
|
||||
|
||||
|
||||
class ReqMask(BaseModel):
|
||||
image: str = Field(title="Image", description="The base64 encoded image")
|
||||
type: str = Field(title="Mask type", description="Type of masking image to return")
|
||||
@@ -27,6 +27,10 @@ class ReqMask(BaseModel):
|
||||
model: str | None = Field(title="Model", description="The model to use for preprocessing")
|
||||
params: dict | None = Field(default={}, title="Settings", description="Preprocessor settings")
|
||||
|
||||
class ResMask(BaseModel):
|
||||
mask: str = Field(default='', title="Image", description="The processed image in base64 format")
|
||||
|
||||
|
||||
class ReqFace(BaseModel):
|
||||
image: str = Field(title="Image", description="The base64 encoded image")
|
||||
model: str | None = Field(title="Model", description="The model to use for detection")
|
||||
@@ -38,8 +42,6 @@ class ResFace(BaseModel):
|
||||
images: list[str] = Field(title="Image", description="The base64 encoded images of detected faces")
|
||||
scores: list[float] = Field(title="Scores", description="The scores of the detected faces")
|
||||
|
||||
class ResMask(BaseModel):
|
||||
mask: str = Field(default='', title="Image", description="The processed image in base64 format")
|
||||
|
||||
class ItemPreprocess(BaseModel):
|
||||
name: str = Field(title="Name", description="Preprocessor name")
|
||||
@@ -215,51 +217,37 @@ class APIProcess:
|
||||
seed = req.seed or -1
|
||||
seed = processing_helpers.get_fixed_seed(seed)
|
||||
prompt = ''
|
||||
if req.type in ('text', 'image'):
|
||||
from modules.scripts_manager import scripts_txt2img
|
||||
default_model = 'google/gemma-3-4b-it' if req.type == 'image' else 'google/gemma-3-1b-it'
|
||||
model = default_model if req.model is None or len(req.model) < 4 else req.model
|
||||
instance = [s for s in scripts_txt2img.scripts if 'prompt_enhance.py' in s.filename][0]
|
||||
prompt = instance.enhance(
|
||||
model=model,
|
||||
prompt=req.prompt,
|
||||
system=req.system_prompt,
|
||||
prefix=req.prefix,
|
||||
suffix=req.suffix,
|
||||
sample=req.do_sample,
|
||||
min_tokens=req.min_tokens,
|
||||
max_tokens=req.max_tokens,
|
||||
temperature=req.temperature,
|
||||
penalty=req.repetition_penalty,
|
||||
top_k=req.top_k,
|
||||
top_p=req.top_p,
|
||||
thinking=req.thinking,
|
||||
keep_thinking=req.keep_thinking,
|
||||
use_vision=req.use_vision,
|
||||
prefill=req.prefill or '',
|
||||
keep_prefill=req.keep_prefill,
|
||||
image=decode_base64_to_image(req.image) if req.image else None,
|
||||
seed=seed,
|
||||
nsfw=req.nsfw,
|
||||
custom_args=req.custom_args,
|
||||
process_words=req.process_words,
|
||||
semantic_threshold=req.semantic_threshold,
|
||||
embedding_similarity=req.embedding_similarity,
|
||||
use_openai=req.use_openai
|
||||
)
|
||||
elif req.type == 'video':
|
||||
from modules.ui_video_vlm import enhance_prompt
|
||||
model = 'Google Gemma 3 4B' if req.model is None or len(req.model) < 4 else req.model
|
||||
prompt = enhance_prompt(
|
||||
enable=True,
|
||||
image=decode_base64_to_image(req.image),
|
||||
prompt=req.prompt,
|
||||
model=model,
|
||||
system_prompt=req.system_prompt,
|
||||
nsfw=req.nsfw,
|
||||
)
|
||||
else:
|
||||
raise HTTPException(status_code=400, detail="prompt enhancement: invalid type")
|
||||
from modules.scripts_manager import scripts_txt2img
|
||||
default_model = 'google/gemma-3-4b-it' if req.type == 'image' else 'google/gemma-3-1b-it'
|
||||
model = default_model if req.model is None or len(req.model) < 4 else req.model
|
||||
instance = [s for s in scripts_txt2img.scripts if 'prompt_enhance.py' in s.filename][0]
|
||||
prompt = instance.enhance(
|
||||
model=model,
|
||||
prompt=req.prompt,
|
||||
system=req.system_prompt,
|
||||
prefix=req.prefix,
|
||||
suffix=req.suffix,
|
||||
sample=req.do_sample,
|
||||
min_tokens=req.min_tokens,
|
||||
max_tokens=req.max_tokens,
|
||||
temperature=req.temperature,
|
||||
penalty=req.repetition_penalty,
|
||||
top_k=req.top_k,
|
||||
top_p=req.top_p,
|
||||
thinking=req.thinking,
|
||||
keep_thinking=req.keep_thinking,
|
||||
use_vision=req.use_vision,
|
||||
prefill=req.prefill or '',
|
||||
keep_prefill=req.keep_prefill,
|
||||
image=decode_base64_to_image(req.image) if req.image else None,
|
||||
seed=seed,
|
||||
nsfw=req.nsfw,
|
||||
custom_args=req.custom_args,
|
||||
process_words=req.process_words,
|
||||
semantic_threshold=req.semantic_threshold,
|
||||
embedding_similarity=req.embedding_similarity,
|
||||
use_openai=req.use_openai
|
||||
)
|
||||
res = models.ResPromptEnhance(prompt=prompt, seed=seed)
|
||||
return res
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ def change_sections(duration, mp4_fps, mp4_interpolate, latent_ws, variant):
|
||||
return gr.update(value=f'Target video: {num_frames} frames in {num_sections} sections'), gr.update(lines=max(2, 2*num_sections//3))
|
||||
|
||||
|
||||
def create_ui(prompt, negative, styles, _overrides, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
def create_ui(prompt, negative, styles, _overrides, script_inputs, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
with gr.Row():
|
||||
with gr.Column(variant='compact', elem_id="framepack_settings", elem_classes=['settings-column'], scale=1):
|
||||
with gr.Row():
|
||||
@@ -114,7 +114,7 @@ def create_ui(prompt, negative, styles, _overrides, mp4_fps, mp4_interpolate, mp
|
||||
framepack_dict = dict(
|
||||
fn=run_framepack,
|
||||
_js="submit_framepack",
|
||||
inputs=state_inputs + framepack_inputs,
|
||||
inputs=state_inputs + framepack_inputs + script_inputs,
|
||||
outputs=framepack_outputs,
|
||||
show_progress='hidden',
|
||||
)
|
||||
|
||||
@@ -114,7 +114,7 @@ def unload_model():
|
||||
yield gr.update(), gr.update(), 'Model unloaded'
|
||||
|
||||
|
||||
def run_framepack(task_id, _ui_state, init_image, end_image, start_weight, end_weight, vision_weight, prompt, system_prompt, optimized_prompt, section_prompt, negative_prompt, styles, seed, resolution, duration, latent_ws, steps, cfg_scale, cfg_distilled, cfg_rescale, shift, use_teacache, use_cfgzero, use_preview, mp4_fps, mp4_codec, mp4_sf, mp4_video, mp4_frames, mp4_thumb, mp4_opt, mp4_ext, mp4_interpolate, attention, vae_type, variant, vlm_enhance, vlm_model, vlm_system_prompt):
|
||||
def run_framepack(task_id, _ui_state, init_image, end_image, start_weight, end_weight, vision_weight, prompt, system_prompt, optimized_prompt, section_prompt, negative_prompt, styles, seed, resolution, duration, latent_ws, steps, cfg_scale, cfg_distilled, cfg_rescale, shift, use_teacache, use_cfgzero, use_preview, mp4_fps, mp4_codec, mp4_sf, mp4_video, mp4_frames, mp4_thumb, mp4_opt, mp4_ext, mp4_interpolate, attention, vae_type, variant, vlm_enhance, vlm_model, vlm_system_prompt, *_args, **_kwargs):
|
||||
variant = variant or 'bi-directional'
|
||||
if init_image is None:
|
||||
init_image = np.zeros((resolution, resolution, 3), dtype=np.uint8)
|
||||
|
||||
@@ -3,7 +3,7 @@ import time
|
||||
import torch
|
||||
from PIL import Image
|
||||
|
||||
from modules import shared, errors, timer, memstats, progress, processing, sd_models, sd_samplers, devices, extra_networks, call_queue
|
||||
from modules import shared, errors, timer, memstats, progress, processing, sd_models, sd_samplers, devices, extra_networks, call_queue, scripts_manager
|
||||
from modules.logger import log
|
||||
from modules.ltx import ltx_capabilities
|
||||
from modules.ltx.ltx_diffusers_patch import apply_patch as apply_ltx_diffusers_patch
|
||||
@@ -151,6 +151,8 @@ def run_ltx(task_id,
|
||||
mp4_thumb: bool,
|
||||
audio_enable: bool,
|
||||
_overrides,
|
||||
*args,
|
||||
**_kwargs,
|
||||
):
|
||||
|
||||
def abort(e, ok: bool = False, p=None):
|
||||
@@ -282,13 +284,15 @@ def run_ltx(task_id,
|
||||
vae_tile_frames=16,
|
||||
)
|
||||
processing.fix_seed(p)
|
||||
p.scripts = None
|
||||
p.script_args = None
|
||||
p.do_not_save_grid = True
|
||||
p.do_not_save_samples = not mp4_frames
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video)
|
||||
p.ops.append('video')
|
||||
|
||||
p.scripts = scripts_manager.scripts_video
|
||||
p.script_args = args
|
||||
processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
|
||||
|
||||
p.task_args['num_inference_steps'] = p.steps
|
||||
p.task_args['width'] = p.width
|
||||
p.task_args['height'] = p.height
|
||||
|
||||
@@ -55,7 +55,7 @@ def _model_change(model_name: str):
|
||||
)
|
||||
|
||||
|
||||
def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
def create_ui(prompt, negative, styles, overrides, script_inputs, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
with gr.Row():
|
||||
with gr.Column(variant='compact', elem_id="ltx_settings", elem_classes=['settings-column'], scale=1):
|
||||
with gr.Row():
|
||||
@@ -175,7 +175,7 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
video_dict = dict(
|
||||
fn=ltx_process.run_ltx,
|
||||
_js="submit_ltx",
|
||||
inputs=state_inputs + video_inputs,
|
||||
inputs=state_inputs + video_inputs + script_inputs,
|
||||
outputs=video_outputs,
|
||||
show_progress='hidden',
|
||||
)
|
||||
|
||||
+3
-1
@@ -6,14 +6,16 @@ from modules.scripts_manager import * # pylint: disable=wildcard-import
|
||||
scripts_txt2img = None
|
||||
scripts_img2img = None
|
||||
scripts_control = None
|
||||
scripts_video = None
|
||||
scripts_current = None
|
||||
scripts_postproc = None
|
||||
|
||||
|
||||
def register_runners():
|
||||
global scripts_txt2img, scripts_img2img, scripts_control, scripts_current, scripts_postproc # pylint: disable=global-statement
|
||||
global scripts_txt2img, scripts_img2img, scripts_control, scripts_video, scripts_current, scripts_postproc # pylint: disable=global-statement
|
||||
scripts_txt2img = scripts_manager.scripts_txt2img
|
||||
scripts_img2img = scripts_manager.scripts_img2img
|
||||
scripts_control = scripts_manager.scripts_control
|
||||
scripts_video = scripts_manager.scripts_video
|
||||
scripts_current = scripts_manager.scripts_current
|
||||
scripts_postproc = scripts_manager.scripts_postproc
|
||||
|
||||
@@ -52,6 +52,8 @@ class Script:
|
||||
alwayson = False
|
||||
is_txt2img = False
|
||||
is_img2img = False
|
||||
is_control = False
|
||||
is_video = False
|
||||
api_info: ItemScript | None = None
|
||||
group = None
|
||||
infotext_fields: list | None = None
|
||||
@@ -320,10 +322,11 @@ def load_scripts():
|
||||
t.record(os.path.basename(scriptfile.basedir) if scriptfile.basedir != paths.script_path else scriptfile.filename)
|
||||
sys.path = syspath
|
||||
|
||||
global scripts_txt2img, scripts_img2img, scripts_control, scripts_postproc # pylint: disable=global-statement
|
||||
global scripts_txt2img, scripts_img2img, scripts_control, scripts_video, scripts_postproc # pylint: disable=global-statement
|
||||
scripts_txt2img = ScriptRunner('txt2img')
|
||||
scripts_img2img = ScriptRunner('img2img')
|
||||
scripts_control = ScriptRunner('control')
|
||||
scripts_video = ScriptRunner('video')
|
||||
scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
|
||||
return t, time.time()-t0
|
||||
|
||||
@@ -373,12 +376,14 @@ class ScriptRunner:
|
||||
self.inputs: list = [None]
|
||||
self.time = 0
|
||||
|
||||
def add_script(self, script_class, path, is_img2img, is_control):
|
||||
def add_script(self, script_class, path, is_img2img, is_control, is_video):
|
||||
try:
|
||||
script = script_class()
|
||||
script.filename = path
|
||||
script.is_txt2img = not is_img2img
|
||||
script.is_img2img = is_img2img
|
||||
script.is_control = is_control
|
||||
script.is_video = is_video
|
||||
if path.startswith(paths.extensions_dir) and not path.startswith(paths.extensions_builtin_dir):
|
||||
script.external = True
|
||||
if is_control and script.external:
|
||||
@@ -393,6 +398,8 @@ class ScriptRunner:
|
||||
visibility = AlwaysVisible
|
||||
else:
|
||||
visibility = v1 or v2
|
||||
elif is_video:
|
||||
visibility = getattr(script, 'video_capable', False)
|
||||
else:
|
||||
visibility = script.show(script.is_img2img)
|
||||
if visibility == AlwaysVisible:
|
||||
@@ -406,7 +413,7 @@ class ScriptRunner:
|
||||
log.error(f'Script initialize: {path} {e}')
|
||||
errors.display(e, 'script')
|
||||
|
||||
def initialize_scripts(self, is_img2img=False, is_control=False):
|
||||
def initialize_scripts(self, is_img2img=False, is_control=False, is_video=False):
|
||||
from modules import scripts_auto_postprocessing
|
||||
|
||||
self.scripts.clear()
|
||||
@@ -428,14 +435,14 @@ class ScriptRunner:
|
||||
except Exception:
|
||||
sorted_scripts = scripts_data
|
||||
for script_class, path, _basedir, _script_module in sorted_scripts:
|
||||
self.add_script(script_class, path, is_img2img, is_control)
|
||||
self.add_script(script_class, path, is_img2img, is_control, is_video)
|
||||
|
||||
try:
|
||||
sorted_scripts = sorted(self.auto_processing_scripts, key=lambda x: x.script_class().title().lower())
|
||||
except Exception:
|
||||
sorted_scripts = self.auto_processing_scripts
|
||||
for script_class, path, _basedir, _script_module in sorted_scripts:
|
||||
self.add_script(script_class, path, is_img2img, is_control)
|
||||
self.add_script(script_class, path, is_img2img, is_control, is_video)
|
||||
|
||||
def prepare_ui(self):
|
||||
self.inputs = [None]
|
||||
@@ -817,6 +824,7 @@ class ScriptRunner:
|
||||
scripts_txt2img: ScriptRunner = None
|
||||
scripts_img2img: ScriptRunner = None
|
||||
scripts_control: ScriptRunner = None
|
||||
scripts_video: ScriptRunner = None
|
||||
scripts_current: ScriptRunner = None
|
||||
scripts_postproc: scripts_postprocessing.ScriptPostprocessingRunner = None
|
||||
reload_scripts = load_scripts # compatibility alias
|
||||
@@ -827,3 +835,4 @@ def reload_script_body_only():
|
||||
scripts_txt2img.reload_sources(cache)
|
||||
scripts_img2img.reload_sources(cache)
|
||||
scripts_control.reload_sources(cache)
|
||||
scripts_video.reload_sources(cache)
|
||||
|
||||
+14
-6
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
import gradio as gr
|
||||
from modules import shared, timer, images, ui_common, ui_sections, generation_parameters_copypaste
|
||||
from modules import shared, timer, images, ui_common, ui_sections, generation_parameters_copypaste, scripts_manager
|
||||
from modules.logger import log
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ debug = log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lam
|
||||
|
||||
def create_ui():
|
||||
log.debug('UI initialize: tab=video')
|
||||
|
||||
scripts_manager.scripts_current = scripts_manager.scripts_video
|
||||
scripts_manager.scripts_video.initialize_scripts(is_img2img=False, is_control=False, is_video=True)
|
||||
|
||||
with gr.Blocks(analytics_enabled=False) as _video_interface:
|
||||
prompt, styles, negative, generate_btn, _reprocess, paste, networks_button, _token_counter, _token_button, _token_counter_negative, _token_button_negative = ui_sections.create_toprow(
|
||||
is_img2img=False,
|
||||
@@ -31,25 +35,31 @@ def create_ui():
|
||||
with gr.Tab('Output', id='video-outputs-tab') as _video_outputs_tab:
|
||||
from modules.video_models import video_ui
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb = video_ui.create_ui_outputs()
|
||||
with gr.Tab('Extras', elem_id='video_script_container'):
|
||||
video_script_inputs = scripts_manager.scripts_video.setup_ui(parent='video', accordion=True)
|
||||
with gr.Tab('Generic', id='video-core-tab') as video_core_tab:
|
||||
from modules.video_models import video_ui
|
||||
engine, model, steps, sampler_index, width, height, frames, seed = video_ui.create_ui(
|
||||
prompt, negative, styles, overrides,
|
||||
prompt, negative, styles,
|
||||
overrides, video_script_inputs,
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb,
|
||||
)
|
||||
with gr.Tab('FramePack', id='framepack-tab') as framepack_tab:
|
||||
from modules.framepack import framepack_ui
|
||||
framepack_ui.create_ui(
|
||||
prompt, negative, styles, overrides,
|
||||
prompt, negative, styles,
|
||||
overrides, video_script_inputs,
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb,
|
||||
)
|
||||
with gr.Tab('LTX', id='ltx-tab') as ltx_tab:
|
||||
from modules.ltx import ltx_ui
|
||||
ltx_ui.create_ui(
|
||||
prompt, negative, styles, overrides,
|
||||
prompt, negative, styles,
|
||||
overrides, video_script_inputs,
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb,
|
||||
)
|
||||
|
||||
|
||||
paste_fields = [
|
||||
(prompt, "Prompt"), # cannot add more fields as they are not defined yet
|
||||
(negative, "Negative prompt"),
|
||||
@@ -75,5 +85,3 @@ def create_ui():
|
||||
ltx_tab.select(fn=lambda: 'ltx', inputs=[], outputs=[current_tab])
|
||||
|
||||
generate_btn.click(fn=None, _js='submit_video_wrapper', inputs=[current_tab], outputs=[])
|
||||
|
||||
# from framepack_api import create_api # pylint: disable=wrong-import-order
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# legacy module as video now uses main prompt enhancer
|
||||
# except for framepack
|
||||
|
||||
import gradio as gr
|
||||
from PIL import Image
|
||||
from modules.logger import log
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
from modules import shared, extra_networks, ui_video_vlm
|
||||
|
||||
|
||||
def prepare_prompts(p, init_image, prompt:str, vlm_enhance:bool, vlm_model:str, vlm_system_prompt:str):
|
||||
p.prompt = shared.prompt_styles.apply_styles_to_prompt(p.prompt, p.styles)
|
||||
p.negative_prompt = shared.prompt_styles.apply_negative_styles_to_prompt(p.negative_prompt, p.styles)
|
||||
shared.prompt_styles.apply_styles_to_extra(p)
|
||||
p.prompts, p.network_data = extra_networks.parse_prompts([p.prompt])
|
||||
extra_networks.activate(p)
|
||||
prompt = p.prompts[0]
|
||||
|
||||
new_prompt = ui_video_vlm.enhance_prompt(
|
||||
enable=vlm_enhance,
|
||||
model=vlm_model,
|
||||
image=init_image,
|
||||
prompt=prompt,
|
||||
system_prompt=vlm_system_prompt,
|
||||
)
|
||||
if new_prompt is not None and len(new_prompt) > 0:
|
||||
prompt = new_prompt
|
||||
|
||||
p.styles = []
|
||||
p.task_args['prompt'] = p.prompt
|
||||
p.task_args['negative_prompt'] = p.negative_prompt
|
||||
@@ -1,17 +1,27 @@
|
||||
import os
|
||||
import copy
|
||||
import time
|
||||
from modules import shared, errors, sd_models, processing, devices, images, ui_common
|
||||
from modules import shared, errors, sd_models, processing, devices, images, ui_common, scripts_manager
|
||||
from modules.logger import log
|
||||
from modules.video_models import models_def, video_utils, video_load, video_vae, video_overrides, video_save, video_prompt
|
||||
from modules.video_models import models_def, video_utils, video_load, video_vae, video_overrides, video_save
|
||||
from modules.paths import resolve_output_path
|
||||
|
||||
|
||||
debug = log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
|
||||
|
||||
def generate(*args, **kwargs):
|
||||
task_id, ui_state, engine, model, prompt, negative, styles, width, height, frames, steps, sampler_index, sampler_shift, dynamic_shift, seed, guidance_scale, guidance_true, init_image, init_strength, last_image, vae_type, vae_tile_frames, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb, vlm_enhance, vlm_model, vlm_system_prompt, override_settings = args
|
||||
def generate(task_id, ui_state,
|
||||
engine, model,
|
||||
prompt, negative, styles,
|
||||
width, height, frames, steps,
|
||||
sampler_index, sampler_shift, dynamic_shift,
|
||||
seed, guidance_scale, guidance_true,
|
||||
init_image, init_strength, last_image,
|
||||
vae_type, vae_tile_frames,
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb,
|
||||
override_settings,
|
||||
*args, **kwargs
|
||||
):
|
||||
|
||||
if engine is None or model is None or engine == 'None' or model == 'None':
|
||||
return video_utils.queue_err('model not selected')
|
||||
@@ -54,9 +64,12 @@ def generate(*args, **kwargs):
|
||||
if p.vae_type == 'Remote' and not selected.vae_remote:
|
||||
log.warning(f'Video: model={selected.name} remote vae not supported')
|
||||
p.vae_type = 'Default'
|
||||
p.scripts = None
|
||||
p.script_args = None
|
||||
|
||||
p.state = ui_state
|
||||
p.scripts = scripts_manager.scripts_video
|
||||
p.script_args = args
|
||||
processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
|
||||
|
||||
p.do_not_save_grid = True
|
||||
p.do_not_save_samples = not mp4_frames
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video)
|
||||
@@ -101,9 +114,7 @@ def generate(*args, **kwargs):
|
||||
shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model)
|
||||
devices.torch_gc(force=True, reason='video')
|
||||
|
||||
|
||||
# set args
|
||||
video_prompt.prepare_prompts(p, init_image, prompt, vlm_enhance, vlm_model, vlm_system_prompt)
|
||||
processing.fix_seed(p)
|
||||
video_vae.set_vae_params(p)
|
||||
p.task_args['num_inference_steps'] = p.steps
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
import gradio as gr
|
||||
from modules import sd_models, ui_common, ui_sections, ui_symbols, ui_video_vlm, call_queue
|
||||
from modules import sd_models, ui_common, ui_sections, ui_symbols, call_queue
|
||||
from modules.logger import log
|
||||
from modules.ui_components import ToolButton
|
||||
from modules.video_models import models_def, video_utils
|
||||
@@ -105,7 +105,7 @@ def create_ui_outputs():
|
||||
return mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb
|
||||
|
||||
|
||||
def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
def create_ui(prompt, negative, styles, overrides, script_inputs, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb):
|
||||
with gr.Row():
|
||||
with gr.Column(variant='compact', elem_id="video_settings", elem_classes=['settings-column'], scale=1):
|
||||
with gr.Row():
|
||||
@@ -143,8 +143,6 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
vae_type = gr.Dropdown(label='VAE decode', choices=['Default', 'Tiny', 'Remote', 'Upscale'], value='Default', elem_id="video_vae_type")
|
||||
vae_tile_frames = gr.Slider(label='Tile frames', minimum=1, maximum=64, step=1, value=16, elem_id="video_vae_tile_frames")
|
||||
|
||||
vlm_enhance, vlm_model, vlm_system_prompt = ui_video_vlm.create_ui(prompt_element=prompt, image_element=init_image)
|
||||
|
||||
# output panel with gallery and video tabs
|
||||
with gr.Column(elem_id='video-output-column', scale=2) as _column_output:
|
||||
with gr.Tabs(elem_classes=['video-output-tabs'], elem_id='video-output-tabs'):
|
||||
@@ -174,7 +172,6 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
init_image, init_strength, last_image,
|
||||
vae_type, vae_tile_frames,
|
||||
mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, mp4_thumb,
|
||||
vlm_enhance, vlm_model, vlm_system_prompt,
|
||||
overrides,
|
||||
]
|
||||
video_outputs = [
|
||||
@@ -188,7 +185,7 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
video_dict = dict(
|
||||
fn=call_queue.wrap_gradio_gpu_call(video_run.generate, extra_outputs=[gr.update(), gr.update(), gr.update(), gr.update()], name='Video'),
|
||||
_js="submit_video",
|
||||
inputs=state_inputs + video_inputs,
|
||||
inputs=state_inputs + video_inputs + script_inputs,
|
||||
outputs=video_outputs,
|
||||
show_progress='hidden',
|
||||
)
|
||||
|
||||
@@ -150,6 +150,7 @@ def on_update(selected):
|
||||
|
||||
|
||||
class AutocompleteScript(scripts_manager.Script):
|
||||
video_capable = scripts_manager.AlwaysVisible
|
||||
|
||||
def show(self, is_img2img):
|
||||
return scripts_manager.AlwaysVisible
|
||||
|
||||
@@ -136,9 +136,10 @@ def process(
|
||||
|
||||
|
||||
# defines script for dual-mode usage
|
||||
# see below for all available options and callbacks
|
||||
# <https://github.com/vladmandic/automatic/blob/master/modules/scripts.py>
|
||||
class ScriptNudeNet(scripts.Script):
|
||||
# see below for all available options and callbacks
|
||||
# <https://github.com/vladmandic/automatic/blob/master/modules/scripts.py#L26>
|
||||
video_capable = scripts.AlwaysVisible
|
||||
|
||||
def title(self):
|
||||
return 'NudeNet'
|
||||
|
||||
@@ -249,6 +249,12 @@ class Options:
|
||||
Base the prompt on what is present in the image, its style, and its atmosphere.
|
||||
Use concrete, image-generation language and avoid unrelated fluff or commentary.
|
||||
''')
|
||||
t2v_prompt: str = textwrap.dedent('''\
|
||||
''')
|
||||
i2v_prompt: str = textwrap.dedent('''\
|
||||
''')
|
||||
i2v_noprompt: str = textwrap.dedent('''\
|
||||
''')
|
||||
nsfw_ok: str = textwrap.dedent('''\
|
||||
NSFW, nudity and explicit content and language are allowed.
|
||||
''')
|
||||
@@ -304,6 +310,7 @@ class PromptEnhanceScript(scripts_manager.Script):
|
||||
busy: bool = False
|
||||
server = None
|
||||
options = Options()
|
||||
video_capable = scripts_manager.AlwaysVisible
|
||||
|
||||
def title(self):
|
||||
return 'Prompt enhance'
|
||||
@@ -835,7 +842,7 @@ class PromptEnhanceScript(scripts_manager.Script):
|
||||
|
||||
log.debug(f'Prompt enhance: cls={self.llm.__class__.__name__} model="{model}" tokens={input_len} args={gen_kwargs} custom={custom}')
|
||||
defaults = {k: v for k, v in helpers.get_default_args(self.llm).items() if k not in gen_kwargs}
|
||||
log.debug(f'Prompt enhance: defaults={defaults}')
|
||||
debug_log(f'Prompt enhance: defaults={defaults}')
|
||||
|
||||
outputs = self.llm.generate(**inputs, **gen_kwargs)
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ export async function getToken(): Promise<{ user: string | undefined; token: str
|
||||
const data = (await res.json()) as TokenResponse;
|
||||
user = data.user;
|
||||
token = data.token;
|
||||
log('getToken', user);
|
||||
log('getToken', { user });
|
||||
}
|
||||
}
|
||||
return { user, token };
|
||||
|
||||
+5
-1
@@ -2261,8 +2261,12 @@ div:has(>#tab-gallery-folders) {
|
||||
}
|
||||
|
||||
.video-model-link {
|
||||
color: var(--button-primary-background-fill);
|
||||
color: var(--button-primary-background-fill) !important;
|
||||
font-weight: normal;
|
||||
font-size: 0.9em;
|
||||
box-sizing: content-box;
|
||||
position: relative;
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
.controlnet-controls .styler {
|
||||
|
||||
Vendored
+6
-6
@@ -9891,7 +9891,7 @@ async function getToken() {
|
||||
const data = await res.json();
|
||||
user = data.user;
|
||||
token = data.token;
|
||||
log("getToken", user);
|
||||
log("getToken", { user });
|
||||
}
|
||||
}
|
||||
return { user, token };
|
||||
@@ -10025,7 +10025,7 @@ function executeCallbacks(queue, arg) {
|
||||
const t0 = performance.now();
|
||||
callback(arg);
|
||||
const t1 = performance.now();
|
||||
if (t1 - t0 > 250) log("callbackSlow", callback.name || callback, `time=${Math.round(t1 - t0)}`);
|
||||
if (t1 - t0 > 250) log("callbackSlow", { callback: callback.name || callback, time: Math.round(t1 - t0) });
|
||||
timer(callback.name || "anonymousCallback", t1 - t0);
|
||||
} catch (e) {
|
||||
error(`executeCallbacks: ${callback} ${e}`);
|
||||
@@ -10553,12 +10553,12 @@ function sortExtraNetworks(fixed = "no") {
|
||||
}
|
||||
const desc = sortDesc[sortVal];
|
||||
const t1 = performance.now();
|
||||
log("sortNetworks", { name: pagename, val: sortVal, order: desc, fixed: fixed === "fixed", items: num, time: Math.round(t1 - t0) });
|
||||
log("sortNetworks", { page: pagename, key: sortVal, order: desc, items: num, time: Math.round(t1 - t0) });
|
||||
timer(`sortExtraNetworks:${desc}`, t1 - t0);
|
||||
return desc;
|
||||
}
|
||||
async function markSelectedCards(selected, page = "") {
|
||||
log("markSelectedCards", selected, page);
|
||||
log("markSelectedCards", { page, selected });
|
||||
selectedNetworks[page] = selected;
|
||||
gradioApp().querySelectorAll(".extra-network-cards .card").forEach((el2) => {
|
||||
if (page.length > 0 && el2.dataset.page !== page) return;
|
||||
@@ -10578,7 +10578,7 @@ function extractLoraNames(prompt) {
|
||||
}
|
||||
function cardClicked(textToAdd) {
|
||||
const tabName = getENActiveTab();
|
||||
log("cardClicked", tabName, textToAdd);
|
||||
log("cardClicked", { tab: tabName, text: textToAdd });
|
||||
const textarea = activePromptTextarea[tabName];
|
||||
if (textarea.value.indexOf(textToAdd) !== -1) textarea.value = textarea.value.replace(textToAdd, "");
|
||||
else textarea.value += textToAdd;
|
||||
@@ -12447,7 +12447,7 @@ var ConnectionMonitorState = class _ConnectionMonitorState {
|
||||
if (online !== this.online) {
|
||||
this.online = online;
|
||||
this.ts = /* @__PURE__ */ new Date();
|
||||
debug("monitorState", { online: _ConnectionMonitorState.online, ts: _ConnectionMonitorState.ts });
|
||||
debug("monitorState", { online: _ConnectionMonitorState.online, ts: _ConnectionMonitorState.ts?.toLocaleTimeString() });
|
||||
}
|
||||
if (data?.updated) this.version = data.updated;
|
||||
if (data?.commit) this.commit = data.commit;
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
+4
-4
@@ -309,18 +309,18 @@ function sortExtraNetworks(fixed = 'no') {
|
||||
}
|
||||
const desc = sortDesc[sortVal];
|
||||
const t1 = performance.now();
|
||||
log('sortNetworks', { name: pagename, val: sortVal, order: desc, fixed: fixed === 'fixed', items: num, time: Math.round(t1 - t0) });
|
||||
log('sortNetworks', { page: pagename, key: sortVal, order: desc, items: num, time: Math.round(t1 - t0) });
|
||||
timer(`sortExtraNetworks:${desc}`, t1 - t0);
|
||||
return desc;
|
||||
}
|
||||
|
||||
function refreshENInput(tabName) {
|
||||
log('refreshNetworks', tabName, gradioApp().querySelector(`#${tabName}_extra_networks textarea`)?.value);
|
||||
log('refreshNetworks', { tab: tabName, value: gradioApp().querySelector(`#${tabName}_extra_networks textarea`)?.value });
|
||||
gradioApp().querySelector(`#${tabName}_extra_networks textarea`)?.dispatchEvent(new Event('input'));
|
||||
}
|
||||
|
||||
export async function markSelectedCards(selected, page = '') {
|
||||
log('markSelectedCards', selected, page);
|
||||
log('markSelectedCards', { page, selected });
|
||||
selectedNetworks[page] = selected;
|
||||
gradioApp().querySelectorAll('.extra-network-cards .card').forEach((el) => {
|
||||
if (page.length > 0 && el.dataset.page !== page) return; // filter by page
|
||||
@@ -342,7 +342,7 @@ function extractLoraNames(prompt) {
|
||||
|
||||
function cardClicked(textToAdd) {
|
||||
const tabName = getENActiveTab();
|
||||
log('cardClicked', tabName, textToAdd);
|
||||
log('cardClicked', { tab: tabName, text: textToAdd });
|
||||
const textarea = activePromptTextarea[tabName];
|
||||
if (textarea.value.indexOf(textToAdd) !== -1) textarea.value = textarea.value.replace(textToAdd, '');
|
||||
else textarea.value += textToAdd;
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ export class ConnectionMonitorState {
|
||||
if (online !== this.online) {
|
||||
this.online = online;
|
||||
this.ts = new Date();
|
||||
debug('monitorState', { online: ConnectionMonitorState.online, ts: ConnectionMonitorState.ts });
|
||||
debug('monitorState', { online: ConnectionMonitorState.online, ts: ConnectionMonitorState.ts?.toLocaleTimeString() });
|
||||
}
|
||||
if (data?.updated) this.version = data.updated;
|
||||
if (data?.commit) this.commit = data.commit;
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ export function executeCallbacks(queue: any[], arg?: any) {
|
||||
const t0 = performance.now();
|
||||
callback(arg);
|
||||
const t1 = performance.now();
|
||||
if (t1 - t0 > 250) log('callbackSlow', callback.name || callback, `time=${Math.round(t1 - t0)}`);
|
||||
if (t1 - t0 > 250) log('callbackSlow', { callback: callback.name || callback, time: Math.round(t1 - t0) });
|
||||
timer(callback.name || 'anonymousCallback', t1 - t0);
|
||||
} catch (e) {
|
||||
error(`executeCallbacks: ${callback} ${e}`);
|
||||
|
||||
Reference in New Issue
Block a user