Lemonator commited on
Commit
3ee8e25
Β·
verified Β·
1 Parent(s): 5751ffd

Update app_lora.py

Browse files
Files changed (1) hide show
  1. app_lora.py +83 -198
app_lora.py CHANGED
@@ -22,7 +22,9 @@ MODEL_ID = "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers"
22
  LORA_REPO_ID = "vrgamedevgirl84/Wan14BT2VFusioniX"
23
  LORA_FILENAME = "FusionX_LoRa/Wan2.1_I2V_14B_FusionX_LoRA.safetensors"
24
 
25
- # Initialize models with proper dtype handling
 
 
26
  image_encoder = CLIPVisionModel.from_pretrained(MODEL_ID, subfolder="image_encoder", torch_dtype=torch.float16)
27
  vae = AutoencoderKLWan.from_pretrained(MODEL_ID, subfolder="vae", torch_dtype=torch.float16)
28
  pipe = WanImageToVideoPipeline.from_pretrained(
@@ -30,10 +32,12 @@ pipe = WanImageToVideoPipeline.from_pretrained(
30
  )
31
  pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=8.0)
32
 
33
- # Enable memory efficient attention and CPU offloading for large videos
34
  pipe.enable_model_cpu_offload()
35
- pipe.enable_vae_slicing()
36
- pipe.enable_vae_tiling()
 
 
37
 
38
  try:
39
  causvid_path = hf_hub_download(repo_id=LORA_REPO_ID, filename=LORA_FILENAME)
@@ -48,261 +52,142 @@ except Exception as e:
48
  print("❌ Error during LoRA loading:")
49
  traceback.print_exc()
50
 
 
51
  MOD_VALUE = 32
52
  DEFAULT_H_SLIDER_VALUE = 640
53
  DEFAULT_W_SLIDER_VALUE = 1024
54
- NEW_FORMULA_MAX_AREA = 640.0 * 1024.0
55
 
56
  SLIDER_MIN_H, SLIDER_MAX_H = 128, 1024
57
  SLIDER_MIN_W, SLIDER_MAX_W = 128, 1024
58
  MAX_SEED = np.iinfo(np.int32).max
59
 
60
  FIXED_FPS = 24
61
- MIN_FRAMES_MODEL = 8 # Minimum 8 frames (~0.33s)
62
- MAX_FRAMES_MODEL = 240 # Maximum 240 frames (10 seconds at 24fps)
63
 
64
  default_prompt_i2v = "make this image come alive, cinematic motion, smooth animation"
65
  default_negative_prompt = "Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards, watermark, text, signature"
66
 
67
 
68
- def _calculate_new_dimensions_wan(pil_image, mod_val, calculation_max_area,
69
- min_slider_h, max_slider_h,
70
- min_slider_w, max_slider_w,
71
- default_h, default_w):
72
- orig_w, orig_h = pil_image.size
73
- if orig_w <= 0 or orig_h <= 0:
74
- return default_h, default_w
75
-
76
- aspect_ratio = orig_h / orig_w
77
-
78
- calc_h = round(np.sqrt(calculation_max_area * aspect_ratio))
79
- calc_w = round(np.sqrt(calculation_max_area / aspect_ratio))
80
 
81
- calc_h = max(mod_val, (calc_h // mod_val) * mod_val)
82
- calc_w = max(mod_val, (calc_w // mod_val) * mod_val)
83
-
84
- new_h = int(np.clip(calc_h, min_slider_h, (max_slider_h // mod_val) * mod_val))
85
- new_w = int(np.clip(calc_w, min_slider_w, (max_slider_w // mod_val) * mod_val))
86
-
87
- return new_h, new_w
88
-
89
- def handle_image_upload_for_dims_wan(uploaded_pil_image, current_h_val, current_w_val):
90
- if uploaded_pil_image is None:
91
- return gr.update(value=DEFAULT_H_SLIDER_VALUE), gr.update(value=DEFAULT_W_SLIDER_VALUE)
92
- try:
93
- new_h, new_w = _calculate_new_dimensions_wan(
94
- uploaded_pil_image, MOD_VALUE, NEW_FORMULA_MAX_AREA,
95
- SLIDER_MIN_H, SLIDER_MAX_H, SLIDER_MIN_W, SLIDER_MAX_W,
96
- DEFAULT_H_SLIDER_VALUE, DEFAULT_W_SLIDER_VALUE
97
- )
98
- return gr.update(value=new_h), gr.update(value=new_w)
99
- except Exception as e:
100
- gr.Warning("Error attempting to calculate new dimensions")
101
- return gr.update(value=DEFAULT_H_SLIDER_VALUE), gr.update(value=DEFAULT_W_SLIDER_VALUE)
102
-
103
- def get_duration(input_image, prompt, height, width,
104
- negative_prompt, duration_seconds,
105
- guidance_scale, steps,
106
- seed, randomize_seed,
107
- progress):
108
- # Adjust timeout based on video length and complexity
109
- if duration_seconds > 7:
110
- return 180 # 3 minutes for very long videos
111
- elif duration_seconds > 5:
112
- return 120 # 2 minutes for long videos
113
- elif duration_seconds > 3:
114
- return 90 # 1.5 minutes for medium videos
115
- else:
116
- return 60 # 1 minute for short videos
117
-
118
- def export_video_with_ffmpeg(frames, output_path, fps=24):
119
- """Export video using imageio if available, otherwise fall back to OpenCV"""
120
- try:
121
- import imageio
122
- # Use imageio for better quality
123
- writer = imageio.get_writer(output_path, fps=fps, codec='libx264',
124
- pixelformat='yuv420p', quality=8)
125
- for frame in frames:
126
- writer.append_data(np.array(frame))
127
- writer.close()
128
- return True
129
- except ImportError:
130
- # Fall back to OpenCV
131
- export_to_video(frames, output_path, fps=fps)
132
- return False
133
-
134
- @spaces.GPU(duration=get_duration)
135
- def generate_video(input_image, prompt, height, width,
136
  negative_prompt=default_negative_prompt, duration_seconds=2,
137
  guidance_scale=1, steps=4,
138
- seed=42, randomize_seed=False,
139
  progress=gr.Progress(track_tqdm=True)):
140
-
 
 
141
  if input_image is None:
142
  raise gr.Error("Please upload an input image.")
143
 
144
  target_h = max(MOD_VALUE, (int(height) // MOD_VALUE) * MOD_VALUE)
145
  target_w = max(MOD_VALUE, (int(width) // MOD_VALUE) * MOD_VALUE)
146
-
147
- # Calculate frames with proper alignment
148
  raw_frames = int(round(duration_seconds * FIXED_FPS))
149
- # Ensure num_frames-1 is divisible by 4 as required by the model
150
  num_frames = ((raw_frames - 1) // 4) * 4 + 1
151
  num_frames = np.clip(num_frames, MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
152
-
153
- # Additional check for very long videos
154
- if num_frames > 120:
155
- # For videos longer than 5 seconds, reduce resolution to manage memory
156
- max_dim = max(target_h, target_w)
157
- if max_dim > 768:
158
- scale_factor = 768 / max_dim
159
- target_h = max(MOD_VALUE, (int(target_h * scale_factor) // MOD_VALUE) * MOD_VALUE)
160
- target_w = max(MOD_VALUE, (int(target_w * scale_factor) // MOD_VALUE) * MOD_VALUE)
161
- gr.Info(f"Reduced resolution to {target_w}x{target_h} for long video generation")
162
-
163
- print(f"Generating {num_frames} frames (requested {raw_frames}) at {target_w}x{target_h}")
164
-
165
- current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
166
 
 
 
 
 
 
 
 
167
  resized_image = input_image.resize((target_w, target_h), Image.Resampling.LANCZOS)
168
 
169
- # Clear GPU cache before generation
170
  if torch.cuda.is_available():
171
  torch.cuda.empty_cache()
172
 
173
  try:
174
- with torch.inference_mode():
175
- # Generate video with autocast for memory efficiency
176
- with torch.autocast("cuda", dtype=torch.float16):
177
- output_frames_list = pipe(
178
- image=resized_image,
179
- prompt=prompt,
180
- negative_prompt=negative_prompt,
181
- height=target_h,
182
- width=target_w,
183
- num_frames=num_frames,
184
- guidance_scale=float(guidance_scale),
185
- num_inference_steps=int(steps),
186
- generator=torch.Generator(device="cuda").manual_seed(current_seed),
187
- return_dict=True
188
- ).frames[0]
189
  except torch.cuda.OutOfMemoryError:
190
- torch.cuda.empty_cache()
191
  raise gr.Error("Out of GPU memory. Try reducing the duration or resolution.")
192
  except Exception as e:
193
- torch.cuda.empty_cache()
194
  raise gr.Error(f"Generation failed: {str(e)}")
195
-
196
- # Clear cache after generation
197
- if torch.cuda.is_available():
198
- torch.cuda.empty_cache()
199
 
200
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
201
  video_path = tmpfile.name
202
-
203
- # Export using imageio if available, otherwise OpenCV
204
- used_imageio = export_video_with_ffmpeg(output_frames_list, video_path, fps=FIXED_FPS)
205
-
206
- # Only try FFmpeg optimization if we have a valid video file
207
- if os.path.exists(video_path) and os.path.getsize(video_path) > 0:
208
- try:
209
- # Check if ffmpeg is available
210
- subprocess.run(['ffmpeg', '-version'], capture_output=True, check=True)
211
-
212
- optimized_path = video_path + "_opt.mp4"
213
- cmd = [
214
- 'ffmpeg',
215
- '-y', # Overwrite without asking
216
- '-i', video_path, # Input file
217
- '-c:v', 'libx264', # Codec
218
- '-pix_fmt', 'yuv420p', # Pixel format
219
- '-profile:v', 'main', # Compatibility profile
220
- '-level', '4.0', # Support for higher resolutions
221
- '-movflags', '+faststart', # Streaming optimized
222
- '-crf', '23', # Quality level
223
- '-preset', 'medium', # Balance between speed and compression
224
- '-maxrate', '10M', # Max bitrate for large videos
225
- '-bufsize', '20M', # Buffer size
226
- optimized_path
227
- ]
228
-
229
- result = subprocess.run(cmd, capture_output=True, text=True)
230
-
231
- if result.returncode == 0 and os.path.exists(optimized_path) and os.path.getsize(optimized_path) > 0:
232
- os.unlink(video_path) # Remove original
233
- video_path = optimized_path
234
- else:
235
- print(f"FFmpeg optimization failed: {result.stderr}")
236
-
237
- except (subprocess.CalledProcessError, FileNotFoundError):
238
- print("FFmpeg not available or optimization failed, using original export")
239
 
240
  return video_path, current_seed
241
 
242
- # Gradio Interface
243
  with gr.Blocks() as demo:
244
  gr.Markdown("# Fast 4 steps Wan 2.1 I2V (14B) FusionX-LoRA")
245
- gr.Markdown("Generate videos up to 10 seconds long! Longer videos may use reduced resolution for stability.")
246
 
247
  with gr.Row():
248
  with gr.Column():
249
- input_image_component = gr.Image(type="pil", label="Input Image (auto-resized to target H/W)")
250
  prompt_input = gr.Textbox(label="Prompt", value=default_prompt_i2v)
251
- duration_seconds_input = gr.Slider(
252
- minimum=round(MIN_FRAMES_MODEL/FIXED_FPS, 1), # 0.3s (8 frames)
253
- maximum=round(MAX_FRAMES_MODEL/FIXED_FPS, 1), # 10.0s (240 frames)
254
- step=0.1,
255
- value=2, # Default 2 seconds
256
- label="Duration (seconds)",
257
- info=f"Video length: {MIN_FRAMES_MODEL/FIXED_FPS:.1f}-{MAX_FRAMES_MODEL/FIXED_FPS:.1f}s. Longer videos may take more time and use more memory."
258
- )
259
  with gr.Accordion("Advanced Settings", open=False):
260
  negative_prompt_input = gr.Textbox(label="Negative Prompt", value=default_negative_prompt, lines=3)
261
  seed_input = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=42, interactive=True)
262
  randomize_seed_checkbox = gr.Checkbox(label="Randomize seed", value=True, interactive=True)
263
  with gr.Row():
264
- height_input = gr.Slider(minimum=SLIDER_MIN_H, maximum=SLIDER_MAX_H, step=MOD_VALUE, value=DEFAULT_H_SLIDER_VALUE, label=f"Output Height (multiple of {MOD_VALUE})")
265
- width_input = gr.Slider(minimum=SLIDER_MIN_W, maximum=SLIDER_MAX_W, step=MOD_VALUE, value=DEFAULT_W_SLIDER_VALUE, label=f"Output Width (multiple of {MOD_VALUE})")
266
- steps_slider = gr.Slider(minimum=1, maximum=30, step=1, value=4, label="Inference Steps")
267
  guidance_scale_input = gr.Slider(minimum=0.0, maximum=20.0, step=0.5, value=1.0, label="Guidance Scale", visible=False)
268
-
269
  generate_button = gr.Button("Generate Video", variant="primary")
270
  with gr.Column():
271
  video_output = gr.Video(label="Generated Video", autoplay=True, interactive=False)
272
- gr.Markdown("### Tips for best results:")
273
- gr.Markdown("- For videos longer than 5 seconds, consider using lower resolutions (512-768px)")
274
- gr.Markdown("- Clear, simple prompts often work better than complex descriptions")
275
- gr.Markdown("- The model works best with 4-8 inference steps")
276
-
277
- input_image_component.upload(
278
- fn=handle_image_upload_for_dims_wan,
279
- inputs=[input_image_component, height_input, width_input],
280
- outputs=[height_input, width_input]
281
- )
282
-
283
- input_image_component.clear(
284
- fn=handle_image_upload_for_dims_wan,
285
- inputs=[input_image_component, height_input, width_input],
286
- outputs=[height_input, width_input]
287
- )
288
 
289
- ui_inputs = [
290
- input_image_component, prompt_input, height_input, width_input,
291
- negative_prompt_input, duration_seconds_input,
292
- guidance_scale_input, steps_slider, seed_input, randomize_seed_checkbox
293
- ]
294
  generate_button.click(fn=generate_video, inputs=ui_inputs, outputs=[video_output, seed_input])
295
 
296
- gr.Examples(
297
- examples=[
298
- ["peng.png", "a penguin playfully dancing in the snow, Antarctica", 896, 512],
299
- ["forg.jpg", "the frog jumps around", 448, 832],
300
- ],
301
- inputs=[input_image_component, prompt_input, height_input, width_input],
302
- outputs=[video_output, seed_input],
303
- fn=generate_video,
304
- cache_examples="lazy"
305
- )
 
306
 
307
  if __name__ == "__main__":
308
  demo.queue(max_size=3).launch()
 
22
  LORA_REPO_ID = "vrgamedevgirl84/Wan14BT2VFusioniX"
23
  LORA_FILENAME = "FusionX_LoRa/Wan2.1_I2V_14B_FusionX_LoRA.safetensors"
24
 
25
+ # --- Model Loading at Startup ---
26
+ # This is the correct pattern for your environment. The model is loaded once
27
+ # when the Space starts, leading to a longer build but a fast experience for users.
28
  image_encoder = CLIPVisionModel.from_pretrained(MODEL_ID, subfolder="image_encoder", torch_dtype=torch.float16)
29
  vae = AutoencoderKLWan.from_pretrained(MODEL_ID, subfolder="vae", torch_dtype=torch.float16)
30
  pipe = WanImageToVideoPipeline.from_pretrained(
 
32
  )
33
  pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=8.0)
34
 
35
+ # Enable memory efficient attention and CPU offloading
36
  pipe.enable_model_cpu_offload()
37
+
38
+ # THE FIX: These two lines caused the original error and have been removed.
39
+ # pipe.enable_vae_slicing()
40
+ # pipe.enable_vae_tiling()
41
 
42
  try:
43
  causvid_path = hf_hub_download(repo_id=LORA_REPO_ID, filename=LORA_FILENAME)
 
52
  print("❌ Error during LoRA loading:")
53
  traceback.print_exc()
54
 
55
+ # --- Constants and Helper Functions ---
56
  MOD_VALUE = 32
57
  DEFAULT_H_SLIDER_VALUE = 640
58
  DEFAULT_W_SLIDER_VALUE = 1024
59
+ NEW_FORMULA_MAX_AREA = 640.0 * 1024.0
60
 
61
  SLIDER_MIN_H, SLIDER_MAX_H = 128, 1024
62
  SLIDER_MIN_W, SLIDER_MAX_W = 128, 1024
63
  MAX_SEED = np.iinfo(np.int32).max
64
 
65
  FIXED_FPS = 24
66
+ MIN_FRAMES_MODEL = 8
67
+ MAX_FRAMES_MODEL = 240
68
 
69
  default_prompt_i2v = "make this image come alive, cinematic motion, smooth animation"
70
  default_negative_prompt = "Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards, watermark, text, signature"
71
 
72
 
73
+ def get_duration(duration_seconds):
74
+ if duration_seconds > 7: return 180
75
+ if duration_seconds > 5: return 120
76
+ if duration_seconds > 3: return 90
77
+ return 60
 
 
 
 
 
 
 
78
 
79
+ # --- The Main Generation Function ---
80
+ # The @spaces.GPU decorator is correctly placed here.
81
+ @spaces.GPU(duration=60)
82
+ def generate_video(input_image, prompt, height, width,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  negative_prompt=default_negative_prompt, duration_seconds=2,
84
  guidance_scale=1, steps=4,
85
+ seed=42, randomize_seed=False,
86
  progress=gr.Progress(track_tqdm=True)):
87
+
88
+ spaces.set_timeout(get_duration(duration_seconds))
89
+
90
  if input_image is None:
91
  raise gr.Error("Please upload an input image.")
92
 
93
  target_h = max(MOD_VALUE, (int(height) // MOD_VALUE) * MOD_VALUE)
94
  target_w = max(MOD_VALUE, (int(width) // MOD_VALUE) * MOD_VALUE)
95
+
 
96
  raw_frames = int(round(duration_seconds * FIXED_FPS))
 
97
  num_frames = ((raw_frames - 1) // 4) * 4 + 1
98
  num_frames = np.clip(num_frames, MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
+ if num_frames > 120 and max(target_h, target_w) > 768:
101
+ scale_factor = 768 / max(target_h, target_w)
102
+ target_h = max(MOD_VALUE, int(target_h * scale_factor) // MOD_VALUE * MOD_VALUE)
103
+ target_w = max(MOD_VALUE, int(target_w * scale_factor) // MOD_VALUE * MOD_VALUE)
104
+ gr.Info(f"Reduced resolution to {target_w}x{target_h} for long video generation")
105
+
106
+ current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
107
  resized_image = input_image.resize((target_w, target_h), Image.Resampling.LANCZOS)
108
 
 
109
  if torch.cuda.is_available():
110
  torch.cuda.empty_cache()
111
 
112
  try:
113
+ with torch.inference_mode(), torch.autocast("cuda", dtype=torch.float16):
114
+ output_frames_list = pipe(
115
+ image=resized_image, prompt=prompt, negative_prompt=negative_prompt,
116
+ height=target_h, width=target_w, num_frames=num_frames,
117
+ guidance_scale=float(guidance_scale), num_inference_steps=int(steps),
118
+ generator=torch.Generator(device="cuda").manual_seed(current_seed),
119
+ return_dict=True
120
+ ).frames[0]
 
 
 
 
 
 
 
121
  except torch.cuda.OutOfMemoryError:
 
122
  raise gr.Error("Out of GPU memory. Try reducing the duration or resolution.")
123
  except Exception as e:
 
124
  raise gr.Error(f"Generation failed: {str(e)}")
125
+ finally:
126
+ if torch.cuda.is_available():
127
+ torch.cuda.empty_cache()
 
128
 
129
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
130
  video_path = tmpfile.name
131
+ import imageio
132
+ writer = imageio.get_writer(video_path, fps=FIXED_FPS, codec='libx264',
133
+ pixelformat='yuv420p', quality=8)
134
+ for frame in output_frames_list:
135
+ writer.append_data(np.array(frame))
136
+ writer.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  return video_path, current_seed
139
 
140
+ # --- Gradio UI ---
141
  with gr.Blocks() as demo:
142
  gr.Markdown("# Fast 4 steps Wan 2.1 I2V (14B) FusionX-LoRA")
 
143
 
144
  with gr.Row():
145
  with gr.Column():
146
+ input_image_component = gr.Image(type="pil", label="Input Image")
147
  prompt_input = gr.Textbox(label="Prompt", value=default_prompt_i2v)
148
+ duration_seconds_input = gr.Slider(minimum=0.3, maximum=10.0, step=0.1, value=2, label="Duration (seconds)")
 
 
 
 
 
 
 
149
  with gr.Accordion("Advanced Settings", open=False):
150
  negative_prompt_input = gr.Textbox(label="Negative Prompt", value=default_negative_prompt, lines=3)
151
  seed_input = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=42, interactive=True)
152
  randomize_seed_checkbox = gr.Checkbox(label="Randomize seed", value=True, interactive=True)
153
  with gr.Row():
154
+ height_input = gr.Slider(minimum=SLIDER_MIN_H, maximum=SLIDER_MAX_H, step=MOD_VALUE, value=DEFAULT_H_SLIDER_VALUE, label="Height")
155
+ width_input = gr.Slider(minimum=SLIDER_MIN_W, maximum=SLIDER_MAX_W, step=MOD_VALUE, value=DEFAULT_W_SLIDER_VALUE, label="Width")
156
+ steps_slider = gr.Slider(minimum=1, maximum=30, step=1, value=4, label="Inference Steps")
157
  guidance_scale_input = gr.Slider(minimum=0.0, maximum=20.0, step=0.5, value=1.0, label="Guidance Scale", visible=False)
 
158
  generate_button = gr.Button("Generate Video", variant="primary")
159
  with gr.Column():
160
  video_output = gr.Video(label="Generated Video", autoplay=True, interactive=False)
161
+ gr.Markdown("### Tips:\n- For videos > 5s, consider lower resolutions.\n- 4-8 steps is often optimal.")
162
+
163
+ def handle_image_upload(img):
164
+ if img is None: return gr.update(value=DEFAULT_H_SLIDER_VALUE), gr.update(value=DEFAULT_W_SLIDER_VALUE)
165
+ try:
166
+ w, h = img.size
167
+ aspect = h / w
168
+ calc_h = round(np.sqrt(NEW_FORMULA_MAX_AREA * aspect))
169
+ calc_w = round(np.sqrt(NEW_FORMULA_MAX_AREA / aspect))
170
+ new_h = int(np.clip((calc_h // MOD_VALUE) * MOD_VALUE, SLIDER_MIN_H, SLIDER_MAX_H))
171
+ new_w = int(np.clip((calc_w // MOD_VALUE) * MOD_VALUE, SLIDER_MIN_W, SLIDER_MAX_W))
172
+ return gr.update(value=new_h), gr.update(value=new_w)
173
+ except: return gr.update(value=DEFAULT_H_SLIDER_VALUE), gr.update(value=DEFAULT_W_SLIDER_VALUE)
174
+
175
+ input_image_component.upload(handle_image_upload, inputs=input_image_component, outputs=[height_input, width_input])
 
176
 
177
+ ui_inputs = [input_image_component, prompt_input, height_input, width_input, negative_prompt_input, duration_seconds_input, guidance_scale_input, steps_slider, seed_input, randomize_seed_checkbox]
 
 
 
 
178
  generate_button.click(fn=generate_video, inputs=ui_inputs, outputs=[video_output, seed_input])
179
 
180
+ # The gr.Examples requires the files to be in your repo. Commenting out to prevent errors.
181
+ # gr.Examples(
182
+ # examples=[
183
+ # ["peng.png", "a penguin playfully dancing in the snow, Antarctica", 896, 512],
184
+ # ["forg.jpg", "the frog jumps around", 448, 832],
185
+ # ],
186
+ # inputs=[input_image_component, prompt_input, height_input, width_input],
187
+ # outputs=[video_output, seed_input],
188
+ # fn=generate_video,
189
+ # cache_examples="lazy"
190
+ # )
191
 
192
  if __name__ == "__main__":
193
  demo.queue(max_size=3).launch()