mirror of
https://github.com/Wan-Video/Wan2.1.git
synced 2025-12-15 11:43:21 +00:00
added multiple ways to extract settings from past video generations
This commit is contained in:
parent
4cc142039e
commit
c9aa2c3230
@ -21,6 +21,10 @@ WanGP supports the Wan (and derived models), Hunyuan Video and LTV Video models
|
||||
|
||||
|
||||
## 🔥 Latest News!!
|
||||
* May 26 2025: 👋 Wan 2.1GP v5.3 : Happy with a Video generation and want to do more generations using the same settings but you can't remember what you did or you find it to hard to copy / paste one per one each setting from the file metadata ? Rejoice ! There are now multiple ways to turn this tedious process into a one click task:
|
||||
- Select one Video recently generated in the Video Gallery and click *Use Selected Video Settings*
|
||||
- Click *Drop File Here* and select a Video you saved somewhere, if the settings metadata have been saved with the Video you will be able to extract them automatically
|
||||
- Click *Export Settings to File* to save on your harddrive the current settings. You will be able to use them later again by clicking *Drop File Here* and select this time a Settings json file
|
||||
* May 23 2025: 👋 Wan 2.1GP v5.21 : Improvements for Vace: better transitions between Sliding Windows,Support for Image masks in Matanyone, new Extend Video for Vace, different types of automated background removal
|
||||
* May 20 2025: 👋 Wan 2.1GP v5.2 : Added support for Wan CausVid which is a distilled Wan model that can generate nice looking videos in only 4 to 12 steps.
|
||||
The great thing is that Kijai (Kudos to him !) has created a CausVid Lora that can be combined with any existing Wan t2v model 14B like Wan Vace 14B.
|
||||
|
||||
@ -1113,7 +1113,7 @@ class LTXVideoPipeline(DiffusionPipeline):
|
||||
)
|
||||
|
||||
latent_model_input = (
|
||||
torch.cat([latents] * num_conds) if num_conds > 1 else latents
|
||||
torch.cat([latents] * num_conds) if num_conds > 1 else latents
|
||||
)
|
||||
latent_model_input = self.scheduler.scale_model_input(
|
||||
latent_model_input, t
|
||||
|
||||
@ -124,7 +124,7 @@ class WanT2V:
|
||||
reactive = [i * m + 0 * (1 - m) for i, m in zip(frames, masks)]
|
||||
inactive = self.vae.encode(inactive, tile_size = tile_size)
|
||||
self.toto = inactive[0].clone()
|
||||
if overlapped_latents != None :
|
||||
if overlapped_latents != None :
|
||||
# inactive[0][:, 0:1] = self.vae.encode([frames[0][:, 0:1]], tile_size = tile_size)[0] # redundant
|
||||
inactive[0][:, 1:overlapped_latents.shape[1] + 1] = overlapped_latents
|
||||
|
||||
@ -303,6 +303,7 @@ class WanT2V:
|
||||
overlapped_latents = None,
|
||||
return_latent_slice = None,
|
||||
overlap_noise = 0,
|
||||
conditioning_latents_size = 0,
|
||||
model_filename = None,
|
||||
**bbargs
|
||||
):
|
||||
@ -445,8 +446,9 @@ class WanT2V:
|
||||
if vace:
|
||||
ref_images_count = len(input_ref_images[0]) if input_ref_images != None and input_ref_images[0] != None else 0
|
||||
kwargs.update({'vace_context' : z, 'vace_context_scale' : context_scale})
|
||||
if overlapped_latents != None:
|
||||
if overlapped_latents != None :
|
||||
overlapped_latents_size = overlapped_latents.shape[1] + 1
|
||||
# overlapped_latents_size = 3
|
||||
z_reactive = [ zz[0:16, 0:overlapped_latents_size + ref_images_count].clone() for zz in z]
|
||||
|
||||
|
||||
@ -456,22 +458,33 @@ class WanT2V:
|
||||
self.model.compute_teacache_threshold(self.model.teacache_start_step, timesteps, self.model.teacache_multiplier)
|
||||
if callback != None:
|
||||
callback(-1, None, True)
|
||||
prev = 50/1000
|
||||
for i, t in enumerate(tqdm(timesteps)):
|
||||
if overlapped_latents != None:
|
||||
|
||||
timestep = [t]
|
||||
if overlapped_latents != None :
|
||||
# overlap_noise_factor = overlap_noise *(i/(len(timesteps)-1)) / 1000
|
||||
overlap_noise_factor = overlap_noise / 1000
|
||||
# overlap_noise_factor = (1000-t )/ 1000 # overlap_noise / 1000
|
||||
# latent_noise_factor = 1 #max(min(1, (t - overlap_noise) / 1000 ),0)
|
||||
latent_noise_factor = t / 1000
|
||||
for zz, zz_r, ll in zip(z, z_reactive, [latents]):
|
||||
pass
|
||||
zz[0:16, ref_images_count:overlapped_latents_size + ref_images_count] = zz_r[:, ref_images_count:] * (1.0 - overlap_noise_factor) + torch.randn_like(zz_r[:, ref_images_count:] ) * overlap_noise_factor
|
||||
ll[:, 0:overlapped_latents_size + ref_images_count] = zz_r * (1.0 - latent_noise_factor) + torch.randn_like(zz_r ) * latent_noise_factor
|
||||
# zz[0:16, ref_images_count:overlapped_latents_size + ref_images_count] = zz_r[:, ref_images_count:] * (1.0 - overlap_noise_factor) + torch.randn_like(zz_r[:, ref_images_count:] ) * overlap_noise_factor
|
||||
# ll[:, 0:overlapped_latents_size + ref_images_count] = zz_r * (1.0 - latent_noise_factor) + torch.randn_like(zz_r ) * latent_noise_factor
|
||||
|
||||
if conditioning_latents_size > 0 and overlap_noise > 0:
|
||||
pass
|
||||
overlap_noise_factor = overlap_noise / 1000
|
||||
latents[:, conditioning_latents_size + ref_images_count:] = latents[:, conditioning_latents_size + ref_images_count:] * (1.0 - overlap_noise_factor) + torch.randn_like(latents[:, conditioning_latents_size + ref_images_count:]) * overlap_noise_factor
|
||||
timestep = [torch.tensor([t.item()] * (conditioning_latents_size + ref_images_count) + [t.item() - overlap_noise]*(len(timesteps) - conditioning_latents_size - ref_images_count))]
|
||||
|
||||
if target_camera != None:
|
||||
latent_model_input = torch.cat([latents, source_latents], dim=1)
|
||||
else:
|
||||
latent_model_input = latents
|
||||
kwargs["slg_layers"] = slg_layers if int(slg_start * sampling_steps) <= i < int(slg_end * sampling_steps) else None
|
||||
|
||||
timestep = [t]
|
||||
offload.set_step_no_for_lora(self.model, i)
|
||||
timestep = torch.stack(timestep)
|
||||
kwargs["current_step"] = i
|
||||
|
||||
263
wgp.py
263
wgp.py
@ -43,6 +43,7 @@ AUTOSAVE_FILENAME = "queue.zip"
|
||||
PROMPT_VARS_MAX = 10
|
||||
|
||||
target_mmgp_version = "3.4.7"
|
||||
WanGP_version = "5.3"
|
||||
prompt_enhancer_image_caption_model, prompt_enhancer_image_caption_processor, prompt_enhancer_llm_model, prompt_enhancer_llm_tokenizer = None, None, None, None
|
||||
|
||||
from importlib.metadata import version
|
||||
@ -434,6 +435,7 @@ def process_prompt_and_add_tasks(state, model_choice):
|
||||
"prompt" : single_prompt,
|
||||
"image_start": start,
|
||||
"image_end" : end,
|
||||
"video_source": None,
|
||||
}
|
||||
inputs.update(extra_inputs)
|
||||
add_video_task(**inputs)
|
||||
@ -1535,7 +1537,7 @@ wan_choices_i2v=["ckpts/wan2.1_image2video_480p_14B_mbf16.safetensors", "ckpts/w
|
||||
"ckpts/wan2.1_fantasy_speaking_14B_bf16.safetensors"]
|
||||
ltxv_choices= ["ckpts/ltxv_0.9.7_13B_dev_bf16.safetensors", "ckpts/ltxv_0.9.7_13B_dev_quanto_bf16_int8.safetensors", "ckpts/ltxv_0.9.7_13B_distilled_lora128_bf16.safetensors"]
|
||||
|
||||
hunyuan_choices= ["ckpts/hunyuan_video_720_bf16.safetensors", "ckpts/hunyuan_video_720_quanto_int8.safetensors", "ckpts/hunyuan_video_i2v_720_bf16.safetensors", "ckpts/hunyuan_video_i2v_720_quanto_int8v2.safetensors",
|
||||
hunyuan_choices= ["ckpts/hunyuan_video_720_bf16.safetensors", "ckpts/hunyuan_video_720_quanto_int8.safetensors", "ckpts/hunyuan_video_i2v_720_bf16v2.safetensors", "ckpts/hunyuan_video_i2v_720_quanto_int8v2.safetensors",
|
||||
"ckpts/hunyuan_video_custom_720_bf16.safetensors", "ckpts/hunyuan_video_custom_720_quanto_bf16_int8.safetensors" ]
|
||||
|
||||
transformer_choices = wan_choices_t2v + wan_choices_i2v + ltxv_choices + hunyuan_choices
|
||||
@ -2323,13 +2325,13 @@ def apply_changes( state,
|
||||
transformer_dtype_policy = server_config["transformer_dtype_policy"]
|
||||
text_encoder_quantization = server_config["text_encoder_quantization"]
|
||||
transformer_types = server_config["transformer_types"]
|
||||
state["model_filename"] = get_model_filename(get_model_type(state["model_filename"]), transformer_quantization, transformer_dtype_policy)
|
||||
|
||||
model_filename = get_model_filename(get_model_type(state["model_filename"]), transformer_quantization, transformer_dtype_policy)
|
||||
state["model_filename"] = model_filename
|
||||
if all(change in ["attention_mode", "vae_config", "boost", "save_path", "metadata_type", "clear_file_list", "fit_canvas"] for change in changes ):
|
||||
model_choice = gr.Dropdown()
|
||||
else:
|
||||
reload_needed = True
|
||||
model_choice = generate_dropdown_model_list()
|
||||
model_choice = generate_dropdown_model_list(model_filename)
|
||||
|
||||
header = generate_header(state["model_filename"], compile=compile, attention_mode= attention_mode)
|
||||
return "<DIV ALIGN=CENTER>The new configuration has been succesfully applied</DIV>", header, model_choice, gr.Row(visible= server_config["enhancer_enabled"] == 1)
|
||||
@ -2699,6 +2701,8 @@ def generate_video(
|
||||
torch.set_grad_enabled(False)
|
||||
|
||||
file_list = gen["file_list"]
|
||||
file_settings_list = gen["file_settings_list"]
|
||||
|
||||
prompt_no = gen["prompt_no"]
|
||||
|
||||
fit_canvas = server_config.get("fit_canvas", 0)
|
||||
@ -2796,7 +2800,8 @@ def generate_video(
|
||||
seed = None if seed == -1 else seed
|
||||
# negative_prompt = "" # not applicable in the inference
|
||||
image2video = test_class_i2v(model_filename)
|
||||
enable_RIFLEx = RIFLEx_setting == 0 and video_length > (6* 16) or RIFLEx_setting == 1
|
||||
current_video_length = video_length
|
||||
enable_RIFLEx = RIFLEx_setting == 0 and current_video_length > (6* 16) or RIFLEx_setting == 1
|
||||
# VAE Tiling
|
||||
device_mem_capacity = torch.cuda.get_device_properties(None).total_memory / 1048576
|
||||
|
||||
@ -2849,7 +2854,7 @@ def generate_video(
|
||||
source_video = None
|
||||
target_camera = None
|
||||
if "recam" in model_filename:
|
||||
source_video = preprocess_video("", width=width, height=height,video_in=video_source, max_frames= video_length, start_frame = 0, fit_canvas= fit_canvas == 1)
|
||||
source_video = preprocess_video("", width=width, height=height,video_in=video_source, max_frames= current_video_length, start_frame = 0, fit_canvas= fit_canvas == 1)
|
||||
target_camera = model_mode
|
||||
|
||||
audio_proj_split = None
|
||||
@ -2859,8 +2864,8 @@ def generate_video(
|
||||
from fantasytalking.infer import parse_audio
|
||||
import librosa
|
||||
duration = librosa.get_duration(path=audio_guide)
|
||||
video_length = min(int(fps * duration // 4) * 4 + 5, video_length)
|
||||
audio_proj_split, audio_context_lens = parse_audio(audio_guide, num_frames= video_length, fps= fps, device= processing_device )
|
||||
current_video_length = min(int(fps * duration // 4) * 4 + 5, current_video_length)
|
||||
audio_proj_split, audio_context_lens = parse_audio(audio_guide, num_frames= current_video_length, fps= fps, device= processing_device )
|
||||
audio_scale = 1.0
|
||||
|
||||
import random
|
||||
@ -2884,19 +2889,19 @@ def generate_video(
|
||||
else:
|
||||
reuse_frames = 0
|
||||
if (diffusion_forcing or ltxv) and source_video != None:
|
||||
video_length += sliding_window_overlap
|
||||
sliding_window = (vace or diffusion_forcing or ltxv) and video_length > sliding_window_size
|
||||
current_video_length += sliding_window_overlap
|
||||
sliding_window = (vace or diffusion_forcing or ltxv) and current_video_length > sliding_window_size
|
||||
|
||||
discard_last_frames = sliding_window_discard_last_frames
|
||||
default_max_frames_to_generate = video_length
|
||||
default_max_frames_to_generate = current_video_length
|
||||
if sliding_window:
|
||||
left_after_first_window = video_length - sliding_window_size + discard_last_frames
|
||||
left_after_first_window = current_video_length - sliding_window_size + discard_last_frames
|
||||
initial_total_windows= 1 + math.ceil(left_after_first_window / (sliding_window_size - discard_last_frames - reuse_frames))
|
||||
video_length = sliding_window_size
|
||||
current_video_length = sliding_window_size
|
||||
else:
|
||||
initial_total_windows = 1
|
||||
|
||||
first_window_video_length = video_length
|
||||
first_window_video_length = current_video_length
|
||||
original_prompts = prompts.copy()
|
||||
gen["sliding_window"] = sliding_window
|
||||
while not abort:
|
||||
@ -2917,7 +2922,7 @@ def generate_video(
|
||||
window_no = 0
|
||||
extra_windows = 0
|
||||
guide_start_frame = 0
|
||||
video_length = first_window_video_length
|
||||
current_video_length = first_window_video_length
|
||||
gen["extra_windows"] = 0
|
||||
gen["total_windows"] = 1
|
||||
gen["window_no"] = 1
|
||||
@ -2967,7 +2972,7 @@ def generate_video(
|
||||
num_frames_generated -= reuse_frames
|
||||
if (max_frames_to_generate - prefix_video_frames_count - num_frames_generated) < latent_size:
|
||||
break
|
||||
video_length = min(sliding_window_size, ((max_frames_to_generate - num_frames_generated - prefix_video_frames_count + reuse_frames + discard_last_frames) // latent_size) * latent_size + 1 )
|
||||
current_video_length = min(sliding_window_size, ((max_frames_to_generate - num_frames_generated - prefix_video_frames_count + reuse_frames + discard_last_frames) // latent_size) * latent_size + 1 )
|
||||
|
||||
total_windows = initial_total_windows + extra_windows
|
||||
gen["total_windows"] = total_windows
|
||||
@ -3015,11 +3020,11 @@ def generate_video(
|
||||
|
||||
if preprocess_type != None :
|
||||
send_cmd("progress", progress_args)
|
||||
video_guide_copy = preprocess_video(preprocess_type, width=width, height=height,video_in=video_guide, max_frames= video_length if window_no == 1 else video_length - reuse_frames, start_frame = guide_start_frame, fit_canvas = fit_canvas, target_fps = fps)
|
||||
video_guide_copy = preprocess_video(preprocess_type, width=width, height=height,video_in=video_guide, max_frames= current_video_length if window_no == 1 else current_video_length - reuse_frames, start_frame = guide_start_frame, fit_canvas = fit_canvas, target_fps = fps)
|
||||
keep_frames_parsed, error = parse_keep_frames_video_guide(keep_frames_video_guide, max_frames_to_generate)
|
||||
if len(error) > 0:
|
||||
raise gr.Error(f"invalid keep frames {keep_frames_video_guide}")
|
||||
keep_frames_parsed = keep_frames_parsed[guide_start_frame: guide_start_frame + video_length]
|
||||
keep_frames_parsed = keep_frames_parsed[guide_start_frame: guide_start_frame + current_video_length]
|
||||
|
||||
if window_no == 1:
|
||||
image_size = (height, width) # default frame dimensions until it is set by video_src (if there is any)
|
||||
@ -3028,13 +3033,18 @@ def generate_video(
|
||||
src_video, src_mask, src_ref_images = wan_model.prepare_source([video_guide_copy],
|
||||
[video_mask_copy ],
|
||||
[image_refs_copy],
|
||||
video_length, image_size = image_size, device ="cpu",
|
||||
current_video_length, image_size = image_size, device ="cpu",
|
||||
original_video= "O" in video_prompt_type,
|
||||
keep_frames=keep_frames_parsed,
|
||||
start_frame = guide_start_frame,
|
||||
pre_src_video = [pre_video_guide],
|
||||
fit_into_canvas = fit_canvas
|
||||
)
|
||||
if window_no == 1:
|
||||
conditioning_latents_size = ( (prefix_video_frames_count-1) // latent_size) + 1 if prefix_video_frames_count > 0 else 0
|
||||
else:
|
||||
conditioning_latents_size = ( (reuse_frames-1) // latent_size) + 1
|
||||
|
||||
status = get_latest_status(state)
|
||||
gen["progress_status"] = status
|
||||
gen["progress_phase"] = ("Encoding Prompt", -1 )
|
||||
@ -3062,7 +3072,7 @@ def generate_video(
|
||||
input_masks = src_mask,
|
||||
input_video= pre_video_guide if diffusion_forcing or ltxv else source_video,
|
||||
target_camera= target_camera,
|
||||
frame_num=(video_length // latent_size)* latent_size + 1,
|
||||
frame_num=(current_video_length // latent_size)* latent_size + 1,
|
||||
height = height,
|
||||
width = width,
|
||||
fit_into_canvas = fit_canvas == 1,
|
||||
@ -3092,6 +3102,7 @@ def generate_video(
|
||||
overlapped_latents = overlapped_latents,
|
||||
return_latent_slice= return_latent_slice,
|
||||
overlap_noise = sliding_window_overlap_noise,
|
||||
conditioning_latents_size = conditioning_latents_size,
|
||||
model_filename = model_filename,
|
||||
)
|
||||
except Exception as e:
|
||||
@ -3160,7 +3171,7 @@ def generate_video(
|
||||
if gen.get("extra_windows",0) > 0:
|
||||
sliding_window = True
|
||||
if sliding_window :
|
||||
guide_start_frame += video_length
|
||||
guide_start_frame += current_video_length
|
||||
if discard_last_frames > 0:
|
||||
sample = sample[: , :-discard_last_frames]
|
||||
guide_start_frame -= discard_last_frames
|
||||
@ -3259,7 +3270,7 @@ def generate_video(
|
||||
inputs.pop("task")
|
||||
configs = prepare_inputs_dict("metadata", inputs)
|
||||
configs["prompt"] = "\n".join(original_prompts)
|
||||
if prompt_enhancer_image_caption_model != None:
|
||||
if prompt_enhancer_image_caption_model != None and prompt_enhancer !=None and len(prompt_enhancer)>0:
|
||||
configs["enhanced_prompt"] = "\n".join(prompts)
|
||||
configs["generation_time"] = round(end_time-start_time)
|
||||
metadata_choice = server_config.get("metadata_type","metadata")
|
||||
@ -3274,6 +3285,8 @@ def generate_video(
|
||||
|
||||
print(f"New video saved to Path: "+video_path)
|
||||
file_list.append(video_path)
|
||||
file_settings_list.append(configs)
|
||||
|
||||
send_cmd("output")
|
||||
|
||||
seed += 1
|
||||
@ -3520,6 +3533,7 @@ def process_tasks(state):
|
||||
gen = get_gen_info(state)
|
||||
clear_file_list = server_config.get("clear_file_list", 0)
|
||||
file_list = gen.get("file_list", [])
|
||||
file_settings_list = gen.get("file_settings_list", [])
|
||||
if clear_file_list > 0:
|
||||
file_list_current_size = len(file_list)
|
||||
keep_file_from = max(file_list_current_size - clear_file_list, 0)
|
||||
@ -3527,11 +3541,13 @@ def process_tasks(state):
|
||||
choice = gen.get("selected",0)
|
||||
choice = max(choice- files_removed, 0)
|
||||
file_list = file_list[ keep_file_from: ]
|
||||
file_settings_list = file_settings_list[ keep_file_from: ]
|
||||
else:
|
||||
file_list = []
|
||||
choice = 0
|
||||
gen["selected"] = choice
|
||||
gen["file_list"] = file_list
|
||||
gen["file_settings_list"] = file_settings_list
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
@ -4005,12 +4021,12 @@ def prepare_inputs_dict(target, inputs ):
|
||||
|
||||
if target == "state":
|
||||
return inputs
|
||||
unsaved_params = ["image_start", "image_end", "image_refs", "video_guide", "video_source", "video_mask", "audio_guide", "embedded_guidance_scale"]
|
||||
unsaved_params = ["image_start", "image_end", "image_refs", "video_guide", "video_source", "video_mask", "audio_guide"]
|
||||
for k in unsaved_params:
|
||||
inputs.pop(k)
|
||||
|
||||
model_filename = state["model_filename"]
|
||||
inputs["type"] = "WanGP by DeepBeepMeep - " + get_model_name(model_filename)
|
||||
inputs["type"] = f"WanGP v{WanGP_version} by DeepBeepMeep - " + get_model_name(model_filename)
|
||||
|
||||
if target == "settings":
|
||||
return inputs
|
||||
@ -4021,10 +4037,10 @@ def prepare_inputs_dict(target, inputs ):
|
||||
if not server_config.get("enhancer_enabled", 0) == 1:
|
||||
inputs.pop("prompt_enhancer")
|
||||
|
||||
if not "recam" in model_filename or not "diffusion_forcing" in model_filename:
|
||||
if not "recam" in model_filename and not "diffusion_forcing" in model_filename:
|
||||
inputs.pop("model_mode")
|
||||
|
||||
if not "Vace" in model_filename or not "phantom" in model_filename or not "hunyuan_video_custom" in model_filename:
|
||||
if not "Vace" in model_filename and not "phantom" in model_filename and not "hunyuan_video_custom" in model_filename:
|
||||
unsaved_params = ["keep_frames_video_guide", "video_prompt_type", "remove_background_images_ref"]
|
||||
for k in unsaved_params:
|
||||
inputs.pop(k)
|
||||
@ -4035,7 +4051,7 @@ def prepare_inputs_dict(target, inputs ):
|
||||
inputs.pop(k)
|
||||
|
||||
|
||||
if not "Vace" in model_filename or "diffusion_forcing" in model_filename or "ltxv" in model_filename:
|
||||
if not "Vace" in model_filename and not "diffusion_forcing" in model_filename and not "ltxv" in model_filename:
|
||||
unsaved_params = [ "sliding_window_size", "sliding_window_overlap", "sliding_window_overlap_noise", "sliding_window_discard_last_frames"]
|
||||
for k in unsaved_params:
|
||||
inputs.pop(k)
|
||||
@ -4043,6 +4059,8 @@ def prepare_inputs_dict(target, inputs ):
|
||||
if not "fantasy" in model_filename:
|
||||
inputs.pop("audio_guidance_scale")
|
||||
|
||||
if not "hunyuan" in model_filename:
|
||||
inputs.pop("embedded_guidance_scale")
|
||||
|
||||
if target == "metadata":
|
||||
inputs = {k: v for k,v in inputs.items() if v != None }
|
||||
@ -4055,7 +4073,85 @@ def get_function_arguments(func, locals):
|
||||
for k in args_names:
|
||||
kwargs[k] = locals[k]
|
||||
return kwargs
|
||||
|
||||
|
||||
def export_settings(state):
|
||||
model_filename = state["model_filename"]
|
||||
model_type = get_model_type(model_filename)
|
||||
settings = state[model_type]
|
||||
settings["state"] = state
|
||||
settings = prepare_inputs_dict("metadata", settings)
|
||||
settings["model_filename"] = model_filename
|
||||
text = json.dumps(settings, indent=4)
|
||||
text_base64 = base64.b64encode(text.encode('utf8')).decode('utf-8')
|
||||
return text_base64
|
||||
|
||||
def use_video_settings(state, files):
|
||||
gen = get_gen_info(state)
|
||||
choice = gen.get("selected",-1)
|
||||
file_list = gen.get("file_list", None)
|
||||
if file_list !=None and choice >=0 and len(file_list)>0:
|
||||
file_settings_list = gen["file_settings_list"]
|
||||
configs = file_settings_list[choice]
|
||||
model_filename = configs["model_filename"]
|
||||
model_type = get_model_type(model_filename)
|
||||
defaults = state.get(model_type, None)
|
||||
defaults = get_default_settings(model_filename) if defaults == None else defaults
|
||||
defaults.update(configs)
|
||||
current_model_filename = state["model_filename"]
|
||||
prompt = configs.get("prompt", "")
|
||||
state[model_type] = defaults
|
||||
gr.Info(f"Settings Loaded from Video with prompt '{prompt[:100]}'")
|
||||
if model_type == get_model_type(current_model_filename):
|
||||
return gr.update(), str(time.time())
|
||||
else:
|
||||
return generate_dropdown_model_list(model_filename), gr.update()
|
||||
else:
|
||||
gr.Info(f"No Video is Selected")
|
||||
|
||||
return gr.update(), gr.update()
|
||||
|
||||
def load_settings_from_file(state, file_path):
|
||||
gen = get_gen_info(state)
|
||||
if file_path==None:
|
||||
return gr.update(), gr.update(), None
|
||||
|
||||
configs = None
|
||||
if file_path.endswith(".json"):
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
configs = json.load(f)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
from mutagen.mp4 import MP4
|
||||
tags = None
|
||||
try:
|
||||
file = MP4(file_path)
|
||||
tags = file.tags['©cmt'][0]
|
||||
except:
|
||||
pass
|
||||
if tags != None:
|
||||
configs = json.loads(tags)
|
||||
if configs == None:
|
||||
gr.Info("File not supported")
|
||||
return gr.update(), gr.update(), None
|
||||
|
||||
prompt = configs.get("prompt", "")
|
||||
current_model_filename = state["model_filename"]
|
||||
model_filename = configs["model_filename"]
|
||||
model_type = get_model_type(model_filename)
|
||||
defaults = state.get(model_type, None)
|
||||
defaults = get_default_settings(model_filename) if defaults == None else defaults
|
||||
defaults.update(configs)
|
||||
state[model_type]= defaults
|
||||
if tags != None:
|
||||
gr.Info(f"Settings Loaded from Video generated with prompt '{prompt[:100]}'")
|
||||
else:
|
||||
gr.Info(f"Settings Loaded from Settings file with prompt '{prompt[:100]}'")
|
||||
if model_type == get_model_type(current_model_filename):
|
||||
return gr.update(), str(time.time()), None
|
||||
else:
|
||||
return generate_dropdown_model_list(model_filename), gr.update(), None
|
||||
|
||||
def save_inputs(
|
||||
target,
|
||||
@ -4420,7 +4516,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
if ltxv:
|
||||
model_mode = gr.Dropdown(
|
||||
choices=[
|
||||
],
|
||||
], value=None,
|
||||
visible= False
|
||||
)
|
||||
else:
|
||||
@ -4470,7 +4566,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
columns=[3], rows=[1], object_fit="contain", height="auto", selected_index=0, interactive= True, visible="E" in image_prompt_type_value, value= ui_defaults.get("image_end", None))
|
||||
|
||||
video_source = gr.Video(visible=False)
|
||||
model_mode = gr.Dropdown(visible=False)
|
||||
model_mode = gr.Dropdown(value=None, visible=False)
|
||||
keep_frames_video_source = gr.Text(visible=False)
|
||||
|
||||
with gr.Column(visible= vace or phantom or hunyuan_video_custom) as video_prompt_column:
|
||||
@ -4784,14 +4880,19 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
|
||||
with gr.Row():
|
||||
save_settings_btn = gr.Button("Set Settings as Default", visible = not args.lock_config)
|
||||
|
||||
export_settings_from_file_btn = gr.Button("Export Settings to File", visible = not args.lock_config)
|
||||
use_video_settings_btn = gr.Button("Use Selected Video Settings", visible = not args.lock_config)
|
||||
with gr.Row():
|
||||
settings_file = gr.File(height=41,label="Load Settings From Video / Json")
|
||||
settings_base64_output = gr.Text(interactive= False, visible=False, value = "")
|
||||
if not update_form:
|
||||
with gr.Column():
|
||||
gen_status = gr.Text(interactive= False, label = "Status")
|
||||
status_trigger = gr.Text(interactive= False, visible=False)
|
||||
output = gr.Gallery( label="Generated videos", show_label=False, elem_id="gallery" , columns=[3], rows=[1], object_fit="contain", height=450, selected_index=0, interactive= False)
|
||||
output_trigger = gr.Text(interactive= False, visible=False)
|
||||
|
||||
refresh_form_trigger = gr.Text(interactive= False, visible=False)
|
||||
|
||||
generate_btn = gr.Button("Generate")
|
||||
add_to_queue_btn = gr.Button("Add New Prompt To Queue", visible = False)
|
||||
|
||||
@ -4891,6 +4992,8 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
gen["status_display"] = True
|
||||
return time.time()
|
||||
|
||||
start_quit_timer_js, cancel_quit_timer_js, trigger_zip_download_js, trigger_settings_download_js = get_js()
|
||||
|
||||
status_trigger.change(refresh_status_async, inputs= [state] , outputs= [gen_status], show_progress_on= [gen_status])
|
||||
|
||||
output_trigger.change(refresh_gallery,
|
||||
@ -4907,8 +5010,49 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
locals_dict = locals()
|
||||
gen_inputs = [locals_dict[k] for k in inputs_names] + [state]
|
||||
save_settings_btn.click( fn=validate_wizard_prompt, inputs =[state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars] , outputs= [prompt]).then(
|
||||
save_inputs, inputs =[target_settings] + gen_inputs, outputs = [])
|
||||
save_inputs, inputs =[target_settings] + gen_inputs, outputs = [])
|
||||
|
||||
use_video_settings_btn.click(fn=validate_wizard_prompt,
|
||||
inputs= [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars] ,
|
||||
outputs= [prompt]
|
||||
).then(fn=save_inputs,
|
||||
inputs =[target_state] + gen_inputs,
|
||||
outputs= None
|
||||
).then( fn=use_video_settings, inputs =[state, output] , outputs= [model_choice, refresh_form_trigger])
|
||||
|
||||
export_settings_from_file_btn.click(fn=validate_wizard_prompt,
|
||||
inputs= [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars] ,
|
||||
outputs= [prompt]
|
||||
).then(fn=save_inputs,
|
||||
inputs =[target_state] + gen_inputs,
|
||||
outputs= None
|
||||
).then(fn=export_settings,
|
||||
inputs =[state],
|
||||
outputs= [settings_base64_output]
|
||||
).then(
|
||||
fn=None,
|
||||
inputs=[settings_base64_output],
|
||||
outputs=None,
|
||||
js=trigger_settings_download_js
|
||||
)
|
||||
|
||||
|
||||
settings_file.upload(fn=validate_wizard_prompt,
|
||||
inputs= [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars] ,
|
||||
outputs= [prompt]
|
||||
).then(fn=save_inputs,
|
||||
inputs =[target_state] + gen_inputs,
|
||||
outputs= None
|
||||
).then(fn=load_settings_from_file, inputs =[state, settings_file] , outputs= [model_choice, refresh_form_trigger, settings_file])
|
||||
|
||||
|
||||
refresh_form_trigger.change(fn= fill_inputs,
|
||||
inputs=[state],
|
||||
outputs=gen_inputs + extra_inputs
|
||||
).then(fn=validate_wizard_prompt,
|
||||
inputs= [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars],
|
||||
outputs= [prompt]
|
||||
)
|
||||
|
||||
model_choice.change(fn=validate_wizard_prompt,
|
||||
inputs= [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars] ,
|
||||
@ -4916,10 +5060,10 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
).then(fn=save_inputs,
|
||||
inputs =[target_state] + gen_inputs,
|
||||
outputs= None
|
||||
).then(fn= change_model,
|
||||
).then(fn= change_model,
|
||||
inputs=[state, model_choice],
|
||||
outputs= [header]
|
||||
).then(fn= fill_inputs,
|
||||
).then(fn= fill_inputs,
|
||||
inputs=[state],
|
||||
outputs=gen_inputs + extra_inputs
|
||||
).then(fn= preload_model_when_switching,
|
||||
@ -4988,7 +5132,6 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
|
||||
)
|
||||
|
||||
|
||||
start_quit_timer_js, cancel_quit_timer_js, trigger_zip_download_js = get_timer_js()
|
||||
|
||||
single_hidden_trigger_btn.click(
|
||||
fn=show_countdown_info_from_state,
|
||||
@ -5348,9 +5491,9 @@ def generate_info_tab():
|
||||
gr.Markdown("Please note that if your turn on compilation, the first denoising step of the first video generation will be slow due to the compilation. Therefore all your tests should be done with compilation turned off.")
|
||||
|
||||
|
||||
def generate_dropdown_model_list():
|
||||
def generate_dropdown_model_list(model_filename):
|
||||
dropdown_types= transformer_types if len(transformer_types) > 0 else model_types
|
||||
current_model_type = get_model_type(transformer_filename)
|
||||
current_model_type = get_model_type(model_filename)
|
||||
if current_model_type not in dropdown_types:
|
||||
dropdown_types.append(current_model_type)
|
||||
model_list = []
|
||||
@ -5385,7 +5528,7 @@ def select_tab(tab_state, evt:gr.SelectData):
|
||||
tab_state["tab_no"] = new_tab_no
|
||||
return gr.Tabs()
|
||||
|
||||
def get_timer_js():
|
||||
def get_js():
|
||||
start_quit_timer_js = """
|
||||
() => {
|
||||
function findAndClickGradioButton(elemId) {
|
||||
@ -5454,9 +5597,41 @@ def get_timer_js():
|
||||
}
|
||||
}
|
||||
"""
|
||||
return start_quit_timer_js, cancel_quit_timer_js, trigger_zip_download_js
|
||||
|
||||
def create_demo():
|
||||
trigger_settings_download_js = """
|
||||
(base64String) => {
|
||||
if (!base64String) {
|
||||
console.log("No base64 settings data received, skipping download.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const byteCharacters = atob(base64String);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const blob = new Blob([byteArray], { type: 'application/text' });
|
||||
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = url;
|
||||
a.download = 'settings.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
console.log("settings download triggered.");
|
||||
} catch (e) {
|
||||
console.error("Error processing base64 data or triggering download:", e);
|
||||
}
|
||||
}
|
||||
"""
|
||||
return start_quit_timer_js, cancel_quit_timer_js, trigger_zip_download_js, trigger_settings_download_js
|
||||
|
||||
def create_ui():
|
||||
global vmc_event_handler
|
||||
css = """
|
||||
#model_list{
|
||||
@ -5699,7 +5874,7 @@ def create_demo():
|
||||
theme = gr.themes.Soft(font=["Verdana"], primary_hue="sky", neutral_hue="slate", text_size="md")
|
||||
|
||||
with gr.Blocks(css=css, theme=theme, title= "WanGP") as main:
|
||||
gr.Markdown("<div align=center><H1>Wan<SUP>GP</SUP> v5.21 <FONT SIZE=4>by <I>DeepBeepMeep</I></FONT> <FONT SIZE=3>") # (<A HREF='https://github.com/deepbeepmeep/Wan2GP'>Updates</A>)</FONT SIZE=3></H1></div>")
|
||||
gr.Markdown(f"<div align=center><H1>Wan<SUP>GP</SUP> v{WanGP_version} <FONT SIZE=4>by <I>DeepBeepMeep</I></FONT> <FONT SIZE=3>") # (<A HREF='https://github.com/deepbeepmeep/Wan2GP'>Updates</A>)</FONT SIZE=3></H1></div>")
|
||||
global model_list
|
||||
|
||||
tab_state = gr.State({ "tab_no":0 })
|
||||
@ -5712,7 +5887,7 @@ def create_demo():
|
||||
model_choice = gr.Dropdown(visible=False, value= get_model_type(transformer_filename))
|
||||
else:
|
||||
gr.Markdown("<div class='title-with-lines'><div class=line width=100%></div></div>")
|
||||
model_choice = generate_dropdown_model_list()
|
||||
model_choice = generate_dropdown_model_list(transformer_filename)
|
||||
gr.Markdown("<div class='title-with-lines'><div class=line width=100%></div></div>")
|
||||
with gr.Row():
|
||||
header = gr.Markdown(generate_header(transformer_filename, compile, attention_mode), visible= True)
|
||||
@ -5753,7 +5928,7 @@ if __name__ == "__main__":
|
||||
server_name = "0.0.0.0"
|
||||
if len(server_name) == 0:
|
||||
server_name = os.getenv("SERVER_NAME", "localhost")
|
||||
demo = create_demo()
|
||||
demo = create_ui()
|
||||
if args.open_browser:
|
||||
import webbrowser
|
||||
if server_name.startswith("http"):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user