multimodalart HF Staff commited on
Commit
1e531a7
·
verified ·
1 Parent(s): 18b8c31

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -15
app.py CHANGED
@@ -9,6 +9,7 @@ from huggingface_hub import hf_hub_download
9
  import logging
10
  import numpy as np
11
  from PIL import Image
 
12
 
13
  # --- Global Model Loading & LoRA Handling ---
14
  MODEL_ID = "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers"
@@ -71,6 +72,9 @@ SLIDER_MAX_H = 896
71
  SLIDER_MIN_W = 128
72
  SLIDER_MAX_W = 896
73
 
 
 
 
74
  def _calculate_new_dimensions_wan(pil_image: Image.Image, mod_val: int, calculation_max_area: float,
75
  min_slider_h: int, max_slider_h: int,
76
  min_slider_w: int, max_slider_w: int,
@@ -130,16 +134,17 @@ def handle_image_upload_for_dims_wan(uploaded_pil_image: Image.Image | None, cur
130
  # --- Gradio Interface Function ---
131
  @spaces.GPU
132
  def generate_video(input_image: Image.Image, prompt: str, negative_prompt: str,
133
- height: int, width: int, duration_seconds: float, # Changed from num_frames
134
  guidance_scale: float, steps: int,
135
- progress=gr.Progress(track_tqdm=True)): # Removed fps_for_conditioning_and_export
 
136
  if input_image is None:
137
  raise gr.Error("Please upload an input image.")
138
 
139
  # Constants for frame calculation
140
  FIXED_FPS = 24
141
- MIN_FRAMES_MODEL = 8 # Based on original num_frames_input slider min
142
- MAX_FRAMES_MODEL = 81 # Based on original num_frames_input slider max
143
 
144
  logger.info("Starting video generation...")
145
  logger.info(f" Input Image: Uploaded (Original size: {input_image.size if input_image else 'N/A'})")
@@ -149,24 +154,25 @@ def generate_video(input_image: Image.Image, prompt: str, negative_prompt: str,
149
 
150
  target_height = int(height)
151
  target_width = int(width)
152
- # duration_seconds is already float
153
  guidance_scale_val = float(guidance_scale)
154
  steps_val = int(steps)
155
 
156
- # Calculate number of frames based on duration and fixed FPS
157
  num_frames_for_pipeline = int(round(duration_seconds * FIXED_FPS))
158
- # Clamp num_frames to be within model's supported range
159
  num_frames_for_pipeline = max(MIN_FRAMES_MODEL, min(MAX_FRAMES_MODEL, num_frames_for_pipeline))
160
- # Ensure at least MIN_FRAMES_MODEL if rounding leads to a very small number (or zero)
161
  if num_frames_for_pipeline < MIN_FRAMES_MODEL:
162
  num_frames_for_pipeline = MIN_FRAMES_MODEL
163
 
164
  logger.info(f" Duration: {duration_seconds:.1f}s, Fixed FPS (conditioning & export): {FIXED_FPS}")
165
  logger.info(f" Calculated Num Frames: {num_frames_for_pipeline} (clamped to [{MIN_FRAMES_MODEL}-{MAX_FRAMES_MODEL}])")
166
  logger.info(f" Guidance Scale: {guidance_scale_val}, Steps: {steps_val}")
 
 
 
 
 
 
167
 
168
 
169
- # Ensure dimensions are compatible.
170
  if target_height % MOD_VALUE_H != 0:
171
  logger.warning(f"Height {target_height} is not a multiple of {MOD_VALUE_H}. Adjusting...")
172
  target_height = (target_height // MOD_VALUE_H) * MOD_VALUE_H
@@ -188,16 +194,16 @@ def generate_video(input_image: Image.Image, prompt: str, negative_prompt: str,
188
  negative_prompt=negative_prompt,
189
  height=target_height,
190
  width=target_width,
191
- num_frames=num_frames_for_pipeline, # Use calculated and clamped num_frames
192
  guidance_scale=guidance_scale_val,
193
  num_inference_steps=steps_val,
194
- generator=torch.Generator(device="cuda").manual_seed(0)
195
  ).frames[0]
196
 
197
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
198
  video_path = tmpfile.name
199
 
200
- export_to_video(output_frames_list, video_path, fps=FIXED_FPS) # Use fixed FPS for export
201
  logger.info(f"Video successfully generated and saved to {video_path}")
202
  return video_path
203
 
@@ -222,6 +228,21 @@ with gr.Blocks() as demo:
222
  value=default_negative_prompt,
223
  lines=3
224
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  with gr.Row():
226
  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})")
227
  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})")
@@ -253,7 +274,9 @@ with gr.Blocks() as demo:
253
  width_input,
254
  duration_seconds_input,
255
  guidance_scale_input,
256
- steps_slider
 
 
257
  ]
258
 
259
  generate_button.click(
@@ -264,8 +287,9 @@ with gr.Blocks() as demo:
264
 
265
  gr.Examples(
266
  examples=[
267
- ["peng.png", "a penguin playfully dancing in the snow, Antarctica", default_negative_prompt, 896, 512, 2, 1.0, 4],
268
- ["forg.jpg", "the frog jumps around", default_negative_prompt, 448, 832, 2, 1.0, 4],
 
269
  ],
270
  inputs=inputs_for_click_and_examples,
271
  outputs=video_output,
 
9
  import logging
10
  import numpy as np
11
  from PIL import Image
12
+ import random # Added for random seed generation
13
 
14
  # --- Global Model Loading & LoRA Handling ---
15
  MODEL_ID = "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers"
 
72
  SLIDER_MIN_W = 128
73
  SLIDER_MAX_W = 896
74
 
75
+ # --- Constant for Seed ---
76
+ MAX_SEED = np.iinfo(np.int32).max
77
+
78
  def _calculate_new_dimensions_wan(pil_image: Image.Image, mod_val: int, calculation_max_area: float,
79
  min_slider_h: int, max_slider_h: int,
80
  min_slider_w: int, max_slider_w: int,
 
134
  # --- Gradio Interface Function ---
135
  @spaces.GPU
136
  def generate_video(input_image: Image.Image, prompt: str, negative_prompt: str,
137
+ height: int, width: int, duration_seconds: float,
138
  guidance_scale: float, steps: int,
139
+ seed: int, randomize_seed: bool,
140
+ progress=gr.Progress(track_tqdm=True)):
141
  if input_image is None:
142
  raise gr.Error("Please upload an input image.")
143
 
144
  # Constants for frame calculation
145
  FIXED_FPS = 24
146
+ MIN_FRAMES_MODEL = 8
147
+ MAX_FRAMES_MODEL = 81
148
 
149
  logger.info("Starting video generation...")
150
  logger.info(f" Input Image: Uploaded (Original size: {input_image.size if input_image else 'N/A'})")
 
154
 
155
  target_height = int(height)
156
  target_width = int(width)
 
157
  guidance_scale_val = float(guidance_scale)
158
  steps_val = int(steps)
159
 
 
160
  num_frames_for_pipeline = int(round(duration_seconds * FIXED_FPS))
 
161
  num_frames_for_pipeline = max(MIN_FRAMES_MODEL, min(MAX_FRAMES_MODEL, num_frames_for_pipeline))
 
162
  if num_frames_for_pipeline < MIN_FRAMES_MODEL:
163
  num_frames_for_pipeline = MIN_FRAMES_MODEL
164
 
165
  logger.info(f" Duration: {duration_seconds:.1f}s, Fixed FPS (conditioning & export): {FIXED_FPS}")
166
  logger.info(f" Calculated Num Frames: {num_frames_for_pipeline} (clamped to [{MIN_FRAMES_MODEL}-{MAX_FRAMES_MODEL}])")
167
  logger.info(f" Guidance Scale: {guidance_scale_val}, Steps: {steps_val}")
168
+
169
+ # Seed logic
170
+ current_seed = int(seed)
171
+ if randomize_seed:
172
+ current_seed = random.randint(0, MAX_SEED)
173
+ logger.info(f" Initial Seed: {seed}, Randomize: {randomize_seed}, Using Seed: {current_seed}")
174
 
175
 
 
176
  if target_height % MOD_VALUE_H != 0:
177
  logger.warning(f"Height {target_height} is not a multiple of {MOD_VALUE_H}. Adjusting...")
178
  target_height = (target_height // MOD_VALUE_H) * MOD_VALUE_H
 
194
  negative_prompt=negative_prompt,
195
  height=target_height,
196
  width=target_width,
197
+ num_frames=num_frames_for_pipeline,
198
  guidance_scale=guidance_scale_val,
199
  num_inference_steps=steps_val,
200
+ generator=torch.Generator(device="cuda").manual_seed(current_seed) # Use current_seed
201
  ).frames[0]
202
 
203
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
204
  video_path = tmpfile.name
205
 
206
+ export_to_video(output_frames_list, video_path, fps=FIXED_FPS)
207
  logger.info(f"Video successfully generated and saved to {video_path}")
208
  return video_path
209
 
 
228
  value=default_negative_prompt,
229
  lines=3
230
  )
231
+ # --- Added Seed Controls ---
232
+ seed_input = gr.Slider(
233
+ label="Seed",
234
+ minimum=0,
235
+ maximum=MAX_SEED,
236
+ step=1,
237
+ value=42, # Default seed value
238
+ interactive=True
239
+ )
240
+ randomize_seed_checkbox = gr.Checkbox(
241
+ label="Randomize seed",
242
+ value=True, # Default to randomize
243
+ interactive=True
244
+ )
245
+ # --- End of Added Seed Controls ---
246
  with gr.Row():
247
  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})")
248
  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})")
 
274
  width_input,
275
  duration_seconds_input,
276
  guidance_scale_input,
277
+ steps_slider,
278
+ seed_input, # Added seed_input
279
+ randomize_seed_checkbox # Added randomize_seed_checkbox
280
  ]
281
 
282
  generate_button.click(
 
287
 
288
  gr.Examples(
289
  examples=[
290
+ # Added seed (e.g., 42) and randomize_seed (e.g., True) to examples
291
+ ["peng.png", "a penguin playfully dancing in the snow, Antarctica", default_negative_prompt, 896, 512, 2, 1.0, 4, 42, False],
292
+ ["forg.jpg", "the frog jumps around", default_negative_prompt, 448, 832, 2, 1.0, 4, 123, False],
293
  ],
294
  inputs=inputs_for_click_and_examples,
295
  outputs=video_output,