ginipick commited on
Commit
6312ef8
·
verified ·
1 Parent(s): 1d1db23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -30
app.py CHANGED
@@ -51,6 +51,13 @@ def initialize_video_pipeline():
51
  # Install PyTorch 2.8 (if needed)
52
  os.system('pip install --upgrade --pre --extra-index-url https://download.pytorch.org/whl/nightly/cu126 "torch<2.9" spaces')
53
 
 
 
 
 
 
 
 
54
  video_pipe = WanImageToVideoPipeline.from_pretrained(VIDEO_MODEL_ID,
55
  transformer=WanTransformer3DModel.from_pretrained('cbensimon/Wan2.2-I2V-A14B-bf16-Diffusers',
56
  subfolder='transformer',
@@ -70,6 +77,16 @@ def initialize_video_pipeline():
70
  gc.collect()
71
  torch.cuda.synchronize()
72
  torch.cuda.empty_cache()
 
 
 
 
 
 
 
 
 
 
73
 
74
  print("Video pipeline initialized successfully!")
75
  except Exception as e:
@@ -225,7 +242,10 @@ def resize_image_landscape(image: Image.Image) -> Image.Image:
225
 
226
  return image.resize((LANDSCAPE_WIDTH, LANDSCAPE_HEIGHT), Image.LANCZOS)
227
 
228
- @spaces.GPU(duration=120)
 
 
 
229
  def generate_video(
230
  input_image,
231
  prompt,
@@ -248,29 +268,55 @@ def generate_video(
248
  if video_pipe is None:
249
  raise gr.Error("Video pipeline not initialized. Please check GPU availability.")
250
 
251
- num_frames = np.clip(int(round(duration_seconds * FIXED_FPS)), MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
252
- current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
253
- resized_image = resize_image_for_video(input_image)
254
-
255
- output_frames_list = video_pipe(
256
- image=resized_image,
257
- prompt=prompt,
258
- negative_prompt=negative_prompt,
259
- height=resized_image.height,
260
- width=resized_image.width,
261
- num_frames=num_frames,
262
- guidance_scale=float(guidance_scale),
263
- guidance_scale_2=float(guidance_scale_2),
264
- num_inference_steps=int(steps),
265
- generator=torch.Generator(device="cuda").manual_seed(current_seed),
266
- ).frames[0]
267
-
268
- with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
269
- video_path = tmpfile.name
270
-
271
- export_to_video(output_frames_list, video_path, fps=FIXED_FPS)
272
-
273
- return video_path, current_seed, "🎬 Video generated successfully!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
  # ===========================
276
  # Enhanced CSS
@@ -383,7 +429,7 @@ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
383
 
384
  with gr.Column(elem_classes="header-container"):
385
  gr.HTML("""
386
- <h1 class="logo-text">🍌 Nano Banana + Video</h1>
387
  <p class="subtitle">AI-Powered Image Style Transfer with Video Generation</p>
388
  <div style="display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px;">
389
  <a href="https://huggingface.co/spaces/openfree/Nano-Banana-Upscale" target="_blank">
@@ -570,12 +616,15 @@ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
570
  guidance_1, guidance_2, video_seed, randomize_seed
571
  ]
572
 
573
- def generate_video_wrapper(*args):
574
  try:
575
- video_path, seed, status = generate_video(*args)
576
- return video_path, seed, status
 
 
 
577
  except Exception as e:
578
- return None, args[7], f"Error: {str(e)}"
579
 
580
  generate_video_btn.click(
581
  fn=generate_video_wrapper,
@@ -583,7 +632,18 @@ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
583
  outputs=[video_output, video_seed, video_status]
584
  )
585
 
586
-
 
 
 
 
 
 
 
 
 
 
 
587
 
588
  # Launch
589
  if __name__ == "__main__":
 
51
  # Install PyTorch 2.8 (if needed)
52
  os.system('pip install --upgrade --pre --extra-index-url https://download.pytorch.org/whl/nightly/cu126 "torch<2.9" spaces')
53
 
54
+ # Import optimization module
55
+ try:
56
+ from optimization import optimize_pipeline_
57
+ except ImportError:
58
+ print("Warning: optimization module not found, skipping optimization")
59
+ optimize_pipeline_ = None
60
+
61
  video_pipe = WanImageToVideoPipeline.from_pretrained(VIDEO_MODEL_ID,
62
  transformer=WanTransformer3DModel.from_pretrained('cbensimon/Wan2.2-I2V-A14B-bf16-Diffusers',
63
  subfolder='transformer',
 
77
  gc.collect()
78
  torch.cuda.synchronize()
79
  torch.cuda.empty_cache()
80
+
81
+ # Optimize pipeline if module available
82
+ if optimize_pipeline_ is not None:
83
+ optimize_pipeline_(video_pipe,
84
+ image=Image.new('RGB', (LANDSCAPE_WIDTH, LANDSCAPE_HEIGHT)),
85
+ prompt='prompt',
86
+ height=LANDSCAPE_HEIGHT,
87
+ width=LANDSCAPE_WIDTH,
88
+ num_frames=MAX_FRAMES_MODEL,
89
+ )
90
 
91
  print("Video pipeline initialized successfully!")
92
  except Exception as e:
 
242
 
243
  return image.resize((LANDSCAPE_WIDTH, LANDSCAPE_HEIGHT), Image.LANCZOS)
244
 
245
+ def get_duration(steps):
246
+ return int(steps) * 15
247
+
248
+ @spaces.GPU(duration=get_duration)
249
  def generate_video(
250
  input_image,
251
  prompt,
 
268
  if video_pipe is None:
269
  raise gr.Error("Video pipeline not initialized. Please check GPU availability.")
270
 
271
+ try:
272
+ # Ensure frames are divisible by 4
273
+ num_frames = int(round(duration_seconds * FIXED_FPS))
274
+ num_frames = np.clip(num_frames, MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
275
+ # Round to nearest number divisible by 4
276
+ num_frames = ((num_frames - 1) // 4) * 4 + 1
277
+
278
+ current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
279
+ resized_image = resize_image_for_video(input_image)
280
+
281
+ # Clear cache before generation
282
+ torch.cuda.empty_cache()
283
+ gc.collect()
284
+
285
+ # Generate video with memory management
286
+ with torch.inference_mode():
287
+ output_frames_list = video_pipe(
288
+ image=resized_image,
289
+ prompt=prompt,
290
+ negative_prompt=negative_prompt,
291
+ height=resized_image.height,
292
+ width=resized_image.width,
293
+ num_frames=num_frames,
294
+ guidance_scale=float(guidance_scale),
295
+ guidance_scale_2=float(guidance_scale_2),
296
+ num_inference_steps=int(steps),
297
+ generator=torch.Generator(device="cuda").manual_seed(current_seed),
298
+ ).frames[0]
299
+
300
+ # Clear cache after generation
301
+ torch.cuda.empty_cache()
302
+ gc.collect()
303
+
304
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile:
305
+ video_path = tmpfile.name
306
+
307
+ export_to_video(output_frames_list, video_path, fps=FIXED_FPS)
308
+
309
+ return video_path, current_seed, "🎬 Video generated successfully!"
310
+
311
+ except RuntimeError as e:
312
+ if "out of memory" in str(e).lower() or "CUDA" in str(e):
313
+ torch.cuda.empty_cache()
314
+ gc.collect()
315
+ raise gr.Error("GPU memory error. Try reducing the duration or number of steps.")
316
+ else:
317
+ raise gr.Error(f"Video generation error: {str(e)}")
318
+ except Exception as e:
319
+ raise gr.Error(f"Unexpected error: {str(e)}")
320
 
321
  # ===========================
322
  # Enhanced CSS
 
429
 
430
  with gr.Column(elem_classes="header-container"):
431
  gr.HTML("""
432
+ <h1 class="logo-text">🍌 Open Nano Banana + Video</h1>
433
  <p class="subtitle">AI-Powered Image Style Transfer with Video Generation</p>
434
  <div style="display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px;">
435
  <a href="https://huggingface.co/spaces/openfree/Nano-Banana-Upscale" target="_blank">
 
616
  guidance_1, guidance_2, video_seed, randomize_seed
617
  ]
618
 
619
+ def generate_video_wrapper(img, prompt, steps, neg_prompt, duration, g1, g2, seed, rand_seed):
620
  try:
621
+ # Pass steps as first argument for GPU duration
622
+ video_path, new_seed, status = generate_video(
623
+ img, prompt, steps, neg_prompt, duration, g1, g2, seed, rand_seed
624
+ )
625
+ return video_path, new_seed, status
626
  except Exception as e:
627
+ return None, seed, f"Error: {str(e)}"
628
 
629
  generate_video_btn.click(
630
  fn=generate_video_wrapper,
 
632
  outputs=[video_output, video_seed, video_status]
633
  )
634
 
635
+ # Examples for image generation
636
+ gr.Examples(
637
+ examples=[
638
+ ["Create a dreamy watercolor style with soft pastels", "examples/photo1.jpg", None],
639
+ ["Transform into cyberpunk neon aesthetic", "examples/photo2.jpg", "examples/style.jpg"],
640
+ ["Make it look like Studio Ghibli animation", "examples/landscape.jpg", None],
641
+ ],
642
+ inputs=[style_prompt, image1, image2],
643
+ outputs=[output_image, img_status],
644
+ fn=process_images,
645
+ cache_examples=False
646
+ )
647
 
648
  # Launch
649
  if __name__ == "__main__":