GiorgioV commited on
Commit
5168648
·
verified ·
1 Parent(s): 5dfb35e

Upload app-19.py

Browse files
Files changed (1) hide show
  1. app-19.py +463 -0
app-19.py ADDED
@@ -0,0 +1,463 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ import torch
3
+ from diffusers.pipelines.wan.pipeline_wan_i2v import WanImageToVideoPipeline
4
+ from diffusers.models.transformers.transformer_wan import WanTransformer3DModel
5
+ from diffusers.utils.export_utils import export_to_video
6
+ import gradio as gr
7
+ import tempfile
8
+ import numpy as np
9
+ from PIL import Image
10
+ import random
11
+ import gc
12
+ import os
13
+
14
+ from torchao.quantization import quantize_
15
+ from torchao.quantization import Float8DynamicActivationFloat8WeightConfig
16
+ from torchao.quantization import Int8WeightOnlyConfig
17
+
18
+ import aoti
19
+
20
+
21
+ MODEL_ID = "Wan-AI/Wan2.2-I2V-A14B-Diffusers"
22
+
23
+ MAX_DIM = 832
24
+ MIN_DIM = 480
25
+ SQUARE_DIM = 640
26
+ MULTIPLE_OF = 16
27
+
28
+ MAX_SEED = np.iinfo(np.int32).max
29
+
30
+ FIXED_FPS = 16
31
+ MIN_FRAMES_MODEL = 8
32
+ MAX_FRAMES_MODEL = 176#80
33
+
34
+ MIN_DURATION = round(MIN_FRAMES_MODEL/FIXED_FPS,1)
35
+ MAX_DURATION = round(MAX_FRAMES_MODEL/FIXED_FPS,1)
36
+
37
+
38
+ pipe = WanImageToVideoPipeline.from_pretrained(MODEL_ID,
39
+ transformer=WanTransformer3DModel.from_pretrained('cbensimon/Wan2.2-I2V-A14B-bf16-Diffusers',
40
+ subfolder='transformer',
41
+ torch_dtype=torch.bfloat16,
42
+ device_map='cuda',
43
+ ),
44
+ transformer_2=WanTransformer3DModel.from_pretrained('cbensimon/Wan2.2-I2V-A14B-bf16-Diffusers',
45
+ subfolder='transformer_2',
46
+ torch_dtype=torch.bfloat16,
47
+ device_map='cuda',
48
+ ),
49
+ torch_dtype=torch.bfloat16,
50
+ ).to('cuda')
51
+
52
+ # 加载并融合你的LoRA模型
53
+ #weight_name="Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
54
+ pipe.load_lora_weights(
55
+ "Kijai/WanVideo_comfy",
56
+ weight_name="LoRAs/Wan22_Lightx2v/Wan_2_2_I2V_A14B_HIGH_lightx2v_4step_lora_v1030_rank_64_bf16.safetensors",
57
+ adapter_name="lightx2v"
58
+ )
59
+ kwargs_lora = {}
60
+ kwargs_lora["load_into_transformer_2"] = True
61
+
62
+ #weight_name="Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
63
+ pipe.load_lora_weights(
64
+ "Kijai/WanVideo_comfy",
65
+ weight_name="LoRAs/Wan22-Lightning/old/Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors",
66
+ adapter_name="lightx2v_2", **kwargs_lora
67
+ )
68
+
69
+
70
+
71
+ # 新增:加载你提供的high noise LoRA
72
+
73
+ pipe.load_lora_weights(
74
+ "GiorgioV/LoRA_for_WAN_22",
75
+ weight_name="DR34ML4Y_I2V_14B_HIGH_V2.safetensors",
76
+ adapter_name="high_noise_lora",
77
+ token=os.environ.get("HF_TOKEN")
78
+ )
79
+ # 新增:加载你提供的low noise LoRA
80
+ pipe.load_lora_weights(
81
+ "Passman22231/DR34ML4Y_I2V_14B_LOW_V2",
82
+ weight_name="DR34ML4Y_I2V_14B_LOW_V2.safetensors",
83
+ adapter_name="low_noise_lora",
84
+ token=os.environ.get("HF_TOKEN"),
85
+ load_into_transformer_2=True
86
+ )
87
+
88
+ pipe.load_lora_weights(
89
+ "romanfratric234/WAN_2-1_Gangbang_Missionary_Sex_I2V",
90
+ weight_name="gangbang-final-000002.safetensors",
91
+ adapter_name="high_noise_lora_spec",
92
+ token=os.environ.get("HF_TOKEN")
93
+ )
94
+ # 新增:加载你提供的low noise LoRA
95
+ pipe.load_lora_weights(
96
+ "romanfratric234/WAN_2-1_Gangbang_Missionary_Sex_I2V",
97
+ weight_name="gangbang-final-000002.safetensors",
98
+ adapter_name="low_noise_lora_spec",
99
+ token=os.environ.get("HF_TOKEN"),
100
+ load_into_transformer_2=True
101
+ )
102
+
103
+
104
+
105
+ pipe.set_adapters(["lightx2v", "lightx2v_2",
106
+ "high_noise_lora", "low_noise_lora", "high_noise_lora_spec", "low_noise_lora_spec"], adapter_weights=[1.5, 1., 1., 1., 0.8, 1.])
107
+ # 修改了lora_scale
108
+ pipe.fuse_lora(adapter_names=["lightx2v", "high_noise_lora", "high_noise_lora_spec"], lora_scales=[3.0, 3.0, 3.0], components=["transformer"])
109
+ # 修改了lora_scale
110
+ pipe.fuse_lora(adapter_names=["lightx2v_2", "low_noise_lora", "low_noise_lora_spec"], lora_scales=[1.0, 1.0, 1.0], components=["transformer_2"])
111
+
112
+
113
+
114
+ ########testing all. 4 together
115
+
116
+
117
+ # 原始 v8normal LoRA
118
+
119
+ # pipe.load_lora_weights(
120
+ # "rahul7star/wan2.2Lora", weight_name="DR34ML4Y_I2V_14B_HIGH.safetensors", adapter_name="high_noise_lora", token=os.environ.get("HF_TOKEN")
121
+ # )
122
+ # pipe.load_lora_weights(
123
+ # "rahul7star/wan2.2Lora", weight_name="DR34ML4Y_I2V_14B_LOW.safetensors", adapter_name="low_noise_lora", token=os.environ.get("HF_TOKEN"), load_into_transformer_2=True
124
+ # )
125
+ # # dremal LoRA
126
+ # pipe.load_lora_weights(
127
+ # "rahul7star/wan2.2Lora", weight_name="wan2.2_i2v_highnoise_pov_missionary_v1.0.safetensors", adapter_name="high_dremal_lora", token=os.environ.get("HF_TOKEN")
128
+ # )
129
+ # pipe.load_lora_weights(
130
+ # "rahul7star/wan2.2Lora", weight_name="wan2.2_i2v_lownoise_pov_missionary_v1.0.safetensors", adapter_name="low_dremal_lora", token=os.environ.get("HF_TOKEN"), load_into_transformer_2=True
131
+ # )
132
+ # # missimd LoRA
133
+ # pipe.load_lora_weights(
134
+ # "rahul7star/wan2.2Lora", weight_name="Wan2.2-Doggy_high_noise.safetensors", adapter_name="high_missimd_lora", token=os.environ.get("HF_TOKEN")
135
+ # )
136
+ # pipe.load_lora_weights(
137
+ # "rahul7star/wan2.2Lora", weight_name="Wan2.2-Doggy_low_noise.safetensors", adapter_name="low_missimd_lora", token=os.environ.get("HF_TOKEN"), load_into_transformer_2=True
138
+ # )
139
+ # # ultrade LoRA
140
+ # pipe.load_lora_weights(
141
+ # "rahul7star/wan2.2Lora", weight_name="WAN-2.2-I2V-POV-Titfuck-Paizuri-HIGH-v1.0.safetensors", adapter_name="high_ultrade_lora", token=os.environ.get("HF_TOKEN")
142
+ # )
143
+ # pipe.load_lora_weights(
144
+ # "rahul7star/wan2.2Lora", weight_name="WAN-2.2-I2V-POV-Titfuck-Paizuri-LOW-v1.0.safetensors", adapter_name="low_ultrade_lora", token=os.environ.get("HF_TOKEN"), load_into_transformer_2=True
145
+ # )
146
+
147
+ # # 设置所有 LoRA 权重
148
+ # pipe.set_adapters(
149
+ # [
150
+ # "lightx2v", "lightx2v_2",
151
+ # "high_noise_lora", "low_noise_lora",
152
+ # "high_dremal_lora", "low_dremal_lora",
153
+ # "high_missimd_lora", "low_missimd_lora",
154
+ # "high_ultrade_lora", "low_ultrade_lora"
155
+ # ],
156
+ # adapter_weights=[1.7, 1.5, 0.4, 0.4, 0, 0, 0.7, 0.7, 0.4, 0.4]
157
+ # )
158
+ # # 融合 LoRA 到 transformer
159
+ # pipe.fuse_lora(
160
+ # adapter_names=[
161
+ # "lightx2v",
162
+ # "high_noise_lora",
163
+ # "high_dremal_lora",
164
+ # "high_missimd_lora",
165
+ # "high_ultrade_lora"
166
+ # ],
167
+ # lora_scales=[4.0, 3.0, 2.0, 2.0, 2.0],
168
+ # components=["transformer"]
169
+ # )
170
+ # # 融合 LoRA 到 transformer_2
171
+ # pipe.fuse_lora(
172
+ # adapter_names=[
173
+ # "lightx2v_2",
174
+ # "low_noise_lora",
175
+ # "low_dremal_lora",
176
+ # "low_missimd_lora",
177
+ # "low_ultrade_lora"
178
+ # ],
179
+ # lora_scales=[2.0, 1.5, 1.0, 1.0, 1.0],
180
+ # components=["transformer_2"]
181
+ # )
182
+
183
+
184
+ #############
185
+
186
+
187
+
188
+
189
+
190
+
191
+ pipe.unload_lora_weights()
192
+
193
+ quantize_(pipe.text_encoder, Int8WeightOnlyConfig())
194
+ quantize_(pipe.transformer, Float8DynamicActivationFloat8WeightConfig())
195
+ quantize_(pipe.transformer_2, Float8DynamicActivationFloat8WeightConfig())
196
+
197
+ aoti.aoti_blocks_load(pipe.transformer, 'rahul7star/WanAot', variant='fp8da')
198
+ aoti.aoti_blocks_load(pipe.transformer_2, 'rahul7star/WanAot', variant='fp8da')
199
+
200
+
201
+ default_prompt_i2v = "make this image come alive, cinematic motion, smooth animation"
202
+ default_negative_prompt = "色调艳丽, 过曝, 静态, 细节模糊不清, 字幕, 风格, 作品, 画作, 画面, 静止, 整体发灰, 最差质量, 低质量, JPEG压缩残留, 丑陋的, 残缺的, 多余的手指, 画得不好的手部, 画得不好的脸部, 畸形的, 毁容的, 形态畸形的肢体, 手指融合, 静止不动的画面, 杂乱的背景, 三条腿, 背景人很多, 倒着走, bruises, birthmarks, tattoos"
203
+
204
+ def resize_image(image: Image.Image) -> Image.Image:
205
+ """
206
+ Resizes an image to fit within the model's constraints, preserving aspect ratio as much as possible.
207
+ """
208
+ width, height = image.size
209
+
210
+ # Handle square case
211
+ if width == height:
212
+ return image.resize((SQUARE_DIM, SQUARE_DIM), Image.LANCZOS)
213
+
214
+ aspect_ratio = width / height
215
+
216
+ MAX_ASPECT_RATIO = MAX_DIM / MIN_DIM
217
+ MIN_ASPECT_RATIO = MIN_DIM / MAX_DIM
218
+
219
+ image_to_resize = image
220
+
221
+ if aspect_ratio > MAX_ASPECT_RATIO:
222
+ # Very wide image -> crop width to fit 832x480 aspect ratio
223
+ target_w, target_h = MAX_DIM, MIN_DIM
224
+ crop_width = int(round(height * MAX_ASPECT_RATIO))
225
+ left = (width - crop_width) // 2
226
+ image_to_resize = image.crop((left, 0, left + crop_width, height))
227
+ elif aspect_ratio < MIN_ASPECT_RATIO:
228
+ # Very tall image -> crop height to fit 480x832 aspect ratio
229
+ target_w, target_h = MIN_DIM, MAX_DIM
230
+ crop_height = int(round(width / MIN_ASPECT_RATIO))
231
+ top = (height - crop_height) // 2
232
+ image_to_resize = image.crop((0, top, width, top + crop_height))
233
+ else:
234
+ if width > height: # Landscape
235
+ target_w = MAX_DIM
236
+ target_h = int(round(target_w / aspect_ratio))
237
+ else: # Portrait
238
+ target_h = MAX_DIM
239
+ target_w = int(round(target_h * aspect_ratio))
240
+
241
+ final_w = round(target_w / MULTIPLE_OF) * MULTIPLE_OF
242
+ final_h = round(target_h / MULTIPLE_OF) * MULTIPLE_OF
243
+
244
+ final_w = max(MIN_DIM, min(MAX_DIM, final_w))
245
+ final_h = max(MIN_DIM, min(MAX_DIM, final_h))
246
+
247
+ return image_to_resize.resize((final_w, final_h), Image.LANCZOS)
248
+
249
+
250
+ HF_MODEL = os.environ.get("HF_UPLOAD_REPO", "rahul7star/wan22-aot-image-2025-dec")
251
+
252
+
253
+ # --- CPU-only upload function ---
254
+ def upload_image_and_prompt_cpu(input_image, prompt_text) -> str:
255
+ from datetime import datetime
256
+ import tempfile, os, uuid, shutil
257
+ from huggingface_hub import HfApi
258
+
259
+ # Instantiate the HfApi class
260
+ api = HfApi()
261
+
262
+ today_str = datetime.now().strftime("%Y-%m-%d")
263
+ unique_subfolder = f"Upload-Image-{uuid.uuid4().hex[:8]}"
264
+ hf_folder = f"{today_str}/{unique_subfolder}"
265
+
266
+ # Save image temporarily
267
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_img:
268
+ if isinstance(input_image, str):
269
+ shutil.copy(input_image, tmp_img.name)
270
+ else:
271
+ input_image.save(tmp_img.name, format="PNG")
272
+ tmp_img_path = tmp_img.name
273
+
274
+ # Upload image using HfApi instance
275
+ api.upload_file(
276
+ path_or_fileobj=tmp_img_path,
277
+ path_in_repo=f"{hf_folder}/input_image.png",
278
+ repo_id=HF_MODEL,
279
+ repo_type="model",
280
+ token=os.environ.get("HUGGINGFACE_HUB_TOKEN")
281
+ )
282
+
283
+ # Save prompt as summary.txt
284
+ summary_file = tempfile.NamedTemporaryFile(delete=False, suffix=".txt").name
285
+ with open(summary_file, "w", encoding="utf-8") as f:
286
+ f.write(prompt_text)
287
+
288
+ api.upload_file(
289
+ path_or_fileobj=summary_file,
290
+ path_in_repo=f"{hf_folder}/summary.txt",
291
+ repo_id=HF_MODEL,
292
+ repo_type="model",
293
+ token=os.environ.get("HUGGINGFACE_HUB_TOKEN")
294
+ )
295
+
296
+ # Cleanup
297
+ os.remove(tmp_img_path)
298
+ os.remove(summary_file)
299
+
300
+ return hf_folder
301
+
302
+ def get_num_frames(duration_seconds: float):
303
+ return 1 + int(np.clip(
304
+ int(round(duration_seconds * FIXED_FPS)),
305
+ MIN_FRAMES_MODEL,
306
+ MAX_FRAMES_MODEL,
307
+ ))
308
+
309
+
310
+ # --- Wrapper to upload image/prompt on CPU before GPU generation ---
311
+ def generate_video_with_upload(input_image, prompt, steps=4, negative_prompt=default_negative_prompt,
312
+ duration_seconds=2, guidance_scale=1, guidance_scale_2=1,
313
+ seed=44, randomize_seed=False):
314
+ # Upload on CPU (hidden, no UI)
315
+ try:
316
+ upload_image_and_prompt_cpu(input_image, prompt)
317
+ except Exception as e:
318
+ print("Upload failed:", e)
319
+
320
+ # Proceed with GPU video generation
321
+ return generate_video(input_image, prompt, steps,
322
+ negative_prompt, duration_seconds,
323
+ guidance_scale, guidance_scale_2, seed, randomize_seed)
324
+
325
+ # def get_duration(
326
+ # input_image,
327
+ # prompt,
328
+ # steps,
329
+ # negative_prompt,
330
+ # duration_seconds,
331
+ # guidance_scale,
332
+ # guidance_scale_2,
333
+ # seed,
334
+ # randomize_seed,
335
+ # progress,
336
+ # ):
337
+ # BASE_FRAMES_HEIGHT_WIDTH = 81 * 832 * 624
338
+ # BASE_STEP_DURATION = 15
339
+ # width, height = resize_image(input_image).size
340
+ # frames = get_num_frames(duration_seconds)
341
+ # factor = frames * width * height / BASE_FRAMES_HEIGHT_WIDTH
342
+ # step_duration = BASE_STEP_DURATION * factor ** 1.5
343
+ # return 10 + int(steps) * step_duration
344
+
345
+
346
+
347
+ @spaces.GPU(duration=120)
348
+ def generate_video(
349
+ input_image,
350
+ prompt,
351
+ steps = 4,
352
+ negative_prompt=default_negative_prompt,
353
+ duration_seconds = MAX_DURATION,
354
+ guidance_scale = 1,
355
+ guidance_scale_2 = 1,
356
+ seed = 42,
357
+ randomize_seed = False,
358
+ progress=gr.Progress(track_tqdm=True),
359
+ ):
360
+ """
361
+ Generate a video from an input image using the Wan 2.2 14B I2V model with Lightning LoRA.
362
+
363
+ This function takes an input image and generates a video animation based on the provided
364
+ prompt and parameters. It uses an FP8 qunatized Wan 2.2 14B Image-to-Video model in with Lightning LoRA
365
+ for fast generation in 4-8 steps.
366
+
367
+ Args:
368
+ input_image (PIL.Image): The input image to animate. Will be resized to target dimensions.
369
+ prompt (str): Text prompt describing the desired animation or motion.
370
+ steps (int, optional): Number of inference steps. More steps = higher quality but slower.
371
+ Defaults to 4. Range: 1-30.
372
+ negative_prompt (str, optional): Negative prompt to avoid unwanted elements.
373
+ Defaults to default_negative_prompt (contains unwanted visual artifacts).
374
+ duration_seconds (float, optional): Duration of the generated video in seconds.
375
+ Defaults to 2. Clamped between MIN_FRAMES_MODEL/FIXED_FPS and MAX_FRAMES_MODEL/FIXED_FPS.
376
+ guidance_scale (float, optional): Controls adherence to the prompt. Higher values = more adherence.
377
+ Defaults to 1.0. Range: 0.0-20.0.
378
+ guidance_scale_2 (float, optional): Controls adherence to the prompt. Higher values = more adherence.
379
+ Defaults to 1.0. Range: 0.0-20.0.
380
+ seed (int, optional): Random seed for reproducible results. Defaults to 42.
381
+ Range: 0 to MAX_SEED (2147483647).
382
+ randomize_seed (bool, optional): Whether to use a random seed instead of the provided seed.
383
+ Defaults to False.
384
+ progress (gr.Progress, optional): Gradio progress tracker. Defaults to gr.Progress(track_tqdm=True).
385
+
386
+ Returns:
387
+ tuple: A tuple containing:
388
+ - video_path (str): Path to the generated video file (.mp4)
389
+ - current_seed (int): The seed used for generation (useful when randomize_seed=True)
390
+
391
+ Raises:
392
+ gr.Error: If input_image is None (no image uploaded).
393
+
394
+ Note:
395
+ - Frame count is calculated as duration_seconds * FIXED_FPS (24)
396
+ - Output dimensions are adjusted to be multiples of MOD_VALUE (32)
397
+ - The function uses GPU acceleration via the @spaces.GPU decorator
398
+ - Generation time varies based on steps and duration (see get_duration function)
399
+ """
400
+ if input_image is None:
401
+ raise gr.Error("Please upload an input image.")
402
+
403
+ num_frames = get_num_frames(duration_seconds)
404
+ current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
405
+ resized_image = resize_image(input_image)
406
+ print("pompt is")
407
+ print(prompt)
408
+ if "child" in prompt.lower():
409
+ print("Found 'child' in prompt. Exiting loop.")
410
+ return
411
+
412
+ output_frames_list = pipe(
413
+ image=resized_image,
414
+ prompt=prompt,
415
+ negative_prompt=negative_prompt,
416
+ height=resized_image.height,
417
+ width=resized_image.width,
418
+ num_frames=num_frames,
419
+ guidance_scale=float(guidance_scale),
420
+ guidance_scale_2=float(guidance_scale_2),
421
+ num_inference_steps=int(steps),
422
+ generator=torch.Generator(device="cuda").manual_seed(current_seed),
423
+ ).frames[0]
424
+
425
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
426
+ video_path = tmpfile.name
427
+
428
+ export_to_video(output_frames_list, video_path, fps=FIXED_FPS)
429
+
430
+ return video_path, current_seed
431
+
432
+ with gr.Blocks() as demo:
433
+ gr.Markdown("# Wan22 AOT")
434
+ #gr.Markdown("run Wan 2.2 in just 4-8 steps, with [Lightning LoRA](https://huggingface.co/Kijai/WanVideo_comfy/tree/main/Wan22-Lightning), fp8 quantization & AoT compilation - compatible with 🧨 diffusers and ZeroGPU⚡️")
435
+ with gr.Row():
436
+ with gr.Column():
437
+ input_image_component = gr.Image(type="pil", label="Input Image")
438
+ prompt_input = gr.Textbox(label="Prompt", value=default_prompt_i2v)
439
+ duration_seconds_input = gr.Slider(minimum=MIN_DURATION, maximum=MAX_DURATION, step=0.1, value=3.5, label="Duration (seconds)", info=f"Clamped to model's {MIN_FRAMES_MODEL}-{MAX_FRAMES_MODEL} frames at {FIXED_FPS}fps.")
440
+
441
+ with gr.Accordion("Advanced Settings", open=False):
442
+ negative_prompt_input = gr.Textbox(label="Negative Prompt", value=default_negative_prompt, lines=3)
443
+ seed_input = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=42, interactive=True)
444
+ randomize_seed_checkbox = gr.Checkbox(label="Randomize seed", value=True, interactive=True)
445
+ steps_slider = gr.Slider(minimum=1, maximum=30, step=1, value=6, label="Inference Steps")
446
+ guidance_scale_input = gr.Slider(minimum=0.0, maximum=10.0, step=0.5, value=1, label="Guidance Scale - high noise stage")
447
+ guidance_scale_2_input = gr.Slider(minimum=0.0, maximum=10.0, step=0.5, value=1, label="Guidance Scale 2 - low noise stage")
448
+
449
+ generate_button = gr.Button("Generate Video", variant="primary")
450
+ with gr.Column():
451
+ video_output = gr.Video(label="Generated Video", autoplay=True, interactive=False)
452
+
453
+ #upload_image_and_prompt(input_image_component, prompt_input)
454
+ ui_inputs = [
455
+ input_image_component, prompt_input, steps_slider,
456
+ negative_prompt_input, duration_seconds_input,
457
+ guidance_scale_input, guidance_scale_2_input, seed_input, randomize_seed_checkbox
458
+ ]
459
+
460
+ generate_button.click(fn=generate_video_with_upload, inputs=ui_inputs, outputs=[video_output, seed_input])
461
+
462
+ if __name__ == "__main__":
463
+ demo.queue().launch(mcp_server=True)