JS6969 commited on
Commit
ddffa5d
·
verified ·
1 Parent(s): 27a2e60

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -40
app.py CHANGED
@@ -570,25 +570,25 @@ def step2_upscale(
570
  precision: str,
571
  prog_html: str,
572
  uploaded_imgs: List[gr.File] | None,
573
- denoise_strength: float = 0.5, # <- NEW param (to match UI)
574
- face_enhance: bool = False, # <- NEW param (to match UI)
 
 
575
  ):
576
- """Upscale frames with live progress updates.
577
- Streams updates like: Upscaling… 20% · 80/100 remaining
578
- Yields: (gallery|None, zip_path|None, details|str, progress_html|str)
579
  """
580
  if not HAVE_REALESRGAN:
581
- msg = ("Real-ESRGAN not available. Ensure requirements.txt includes (each on its own line):\n"
582
- "--prefer-binary\n"
583
- "numpy==1.26.4\nscipy==1.11.4\nscikit-image==0.22.0\nopencv-python-headless==4.10.0.84\n"
584
- "torch==2.2.2\nrealesrgan==0.3.0\nbasicsr==1.4.2\npillow\ngradio==5.44.1")
585
  yield None, None, msg, prog_html
586
  return
587
 
588
- # Choose source: uploaded images take priority, else frames from Step 1
589
  if uploaded_imgs and len(uploaded_imgs) > 0:
590
- img_paths, _ = save_uploaded_images(uploaded_imgs, prefix="up")
591
- src_paths = [str(p) for p in img_paths]
592
  else:
593
  src_paths = frames_list or []
594
 
@@ -596,10 +596,34 @@ def step2_upscale(
596
  yield None, None, "No images provided. Upload files or run Step 1 first.", prog_html
597
  return
598
 
599
- # Map UI -> internal model id and clamp outscale
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  model_id = MODEL_MAP.get(ui_model_name, "x4plus")
601
- scale = _clamp_scale_for_model(int(outscale or 4), model_id)
602
 
 
 
 
 
603
  device = "cuda" if os.environ.get("CUDA_VISIBLE_DEVICES") else "cpu"
604
  half = (precision == "half") and (device == "cuda")
605
  upsampler = get_realesrganer(model_id, scale, tile, half, device=device)
@@ -611,36 +635,37 @@ def step2_upscale(
611
  total = len(src_paths)
612
  done = 0
613
  up_paths: List[Path] = []
614
- last_pct = -1
615
 
616
- for fp in src_paths:
617
- try:
618
- img = Image.open(fp).convert("RGB")
619
- # (denoise_strength & face_enhance are accepted but not wired in this minimal build)
620
- output, _ = upsampler.enhance(np.array(img), outscale=scale)
621
- out_img = Image.fromarray(output)
622
- out_file = out_dir / (Path(fp).stem + ".jpg")
623
- out_img.save(out_file, quality=95)
624
- up_paths.append(out_file)
625
- except Exception:
626
- pass
627
 
628
- done += 1
629
- if total:
630
- pct = int(round((done / total) * 100))
631
- remaining = max(0, total - done)
632
- if pct != last_pct:
633
- label = f"Upscaling… {pct}% · {remaining}/{total} remaining"
634
- prog_html = render_progress(pct, label)
635
- # Stream a progress update (gallery/zip are None until the end)
636
- yield None, None, label, prog_html
637
- last_pct = pct
 
 
 
 
 
 
 
 
 
 
 
638
 
639
  if not up_paths:
640
  yield None, None, "Upscaling produced no outputs.", prog_html
641
  return
642
 
643
- # Final outputs
644
  up_paths = sorted(up_paths, key=_natural_key)
645
  gallery = sample_paths(up_paths, 30)
646
  zip_path = work / "upscaled.zip"
@@ -649,9 +674,10 @@ def step2_upscale(
649
  zf.write(p, p.name)
650
 
651
  final_label = (f"Upscaled: {len(up_paths)} | Model: {ui_model_name}→{model_id} | "
652
- f"Scale: x{scale} | Tile: {tile} | Precision: {precision}")
653
  yield gallery, str(zip_path), final_label, render_progress(100.0, "Upscaling complete")
654
 
 
655
  # ───────────────── Encode (Step 3) — supports uploaded frames/ZIP & optional audio source
656
 
657
  def prepare_frames_from_upload(files: List[gr.File] | None, prefix: str = "enc") -> Tuple[Optional[str], Optional[str]]:
@@ -957,7 +983,10 @@ def build_ui():
957
  with gr.Row():
958
  tile = gr.Number(value=0, label="Tile size (0 = auto)")
959
  precision = gr.Dropdown(["auto", "half", "full"], value="auto", label="Precision (GPU=half, CPU=full)")
960
-
 
 
 
961
  with gr.Row():
962
  btn_upscale = gr.Button("Step 2: Upscale", variant="primary")
963
 
@@ -968,7 +997,7 @@ def build_ui():
968
 
969
  btn_upscale.click(
970
  step2_upscale,
971
- inputs=[frames_state, ui_model_name, outscale, tile, precision, prog2, imgs_override, denoise_strength, face_enhance],
972
  outputs=[gallery_up, zip_up, details2, prog2],
973
  )
974
 
 
570
  precision: str,
571
  prog_html: str,
572
  uploaded_imgs: List[gr.File] | None,
573
+ denoise_strength: float = 0.5,
574
+ face_enhance: bool = False,
575
+ batch_size: int = 16, # << NEW
576
+ max_images: int = 0, # << NEW (0 = all)
577
  ):
578
+ """Upscale frames **in batches** with live progress updates.
579
+ Streams: "Upscaling… 20% · 80/100 remaining (batch 2/10)"
 
580
  """
581
  if not HAVE_REALESRGAN:
582
+ msg = ("Real-ESRGAN not available. Check requirements.txt includes: --prefer-binary, "
583
+ "numpy==1.26.4, scipy==1.11.4, scikit-image==0.22.0, opencv-python-headless, "
584
+ "torch==2.2.2, realesrgan==0.3.0, basicsr==1.4.2, pillow, gradio.")
 
585
  yield None, None, msg, prog_html
586
  return
587
 
588
+ # Source: uploaded > frames from Step 1
589
  if uploaded_imgs and len(uploaded_imgs) > 0:
590
+ # Use direct file paths; no extra staging copy
591
+ src_paths = [str(Path(f.name)) for f in uploaded_imgs]
592
  else:
593
  src_paths = frames_list or []
594
 
 
596
  yield None, None, "No images provided. Upload files or run Step 1 first.", prog_html
597
  return
598
 
599
+ # Optional cap
600
+ try:
601
+ max_images = int(max_images or 0)
602
+ except Exception:
603
+ max_images = 0
604
+ if max_images > 0:
605
+ src_paths = src_paths[:max_images]
606
+
607
+ # Batch size
608
+ try:
609
+ batch_size = max(1, int(batch_size or 1))
610
+ except Exception:
611
+ batch_size = 16
612
+
613
+ # Map UI model -> internal id; clamp scale to model
614
+ MODEL_MAP = {
615
+ "RealESRGAN_x4plus": "x4plus",
616
+ "RealESRNet_x4plus": "x4plus", # fallback
617
+ "RealESRGAN_x4plus_anime_6B": "x4plus-anime",
618
+ "RealESRGAN_x2plus": "x2plus",
619
+ "realesr-general-x4v3": "x4plus", # fallback
620
+ }
621
  model_id = MODEL_MAP.get(ui_model_name, "x4plus")
 
622
 
623
+ def _clamp_scale_for_model(s: int, mid: str) -> int:
624
+ return 2 if mid == "x2plus" else 4
625
+
626
+ scale = _clamp_scale_for_model(int(outscale or 4), model_id)
627
  device = "cuda" if os.environ.get("CUDA_VISIBLE_DEVICES") else "cpu"
628
  half = (precision == "half") and (device == "cuda")
629
  upsampler = get_realesrganer(model_id, scale, tile, half, device=device)
 
635
  total = len(src_paths)
636
  done = 0
637
  up_paths: List[Path] = []
 
638
 
639
+ # Process in batches
640
+ for i in range(0, total, batch_size):
641
+ batch = src_paths[i:i+batch_size]
 
 
 
 
 
 
 
 
642
 
643
+ for fp in batch:
644
+ try:
645
+ with Image.open(fp) as im:
646
+ img = im.convert("RGB")
647
+ output, _ = upsampler.enhance(np.array(img), outscale=scale)
648
+ out_img = Image.fromarray(output)
649
+ out_file = out_dir / (Path(fp).stem + ".jpg")
650
+ out_img.save(out_file, quality=95)
651
+ up_paths.append(out_file)
652
+ except Exception:
653
+ # continue on errors
654
+ pass
655
+ finally:
656
+ done += 1
657
+
658
+ # Emit progress after each batch
659
+ pct = int(round((done / total) * 100)) if total else 0
660
+ remaining = max(0, total - done)
661
+ label = f"Upscaling… {pct}% · {remaining}/{total} remaining (batch {i//batch_size+1}/{(total+batch_size-1)//batch_size})"
662
+ prog_html = render_progress(pct, label)
663
+ yield None, None, label, prog_html
664
 
665
  if not up_paths:
666
  yield None, None, "Upscaling produced no outputs.", prog_html
667
  return
668
 
 
669
  up_paths = sorted(up_paths, key=_natural_key)
670
  gallery = sample_paths(up_paths, 30)
671
  zip_path = work / "upscaled.zip"
 
674
  zf.write(p, p.name)
675
 
676
  final_label = (f"Upscaled: {len(up_paths)} | Model: {ui_model_name}→{model_id} | "
677
+ f"Scale: x{scale} | Tile: {tile} | Precision: {precision} | Batch: {batch_size}")
678
  yield gallery, str(zip_path), final_label, render_progress(100.0, "Upscaling complete")
679
 
680
+
681
  # ───────────────── Encode (Step 3) — supports uploaded frames/ZIP & optional audio source
682
 
683
  def prepare_frames_from_upload(files: List[gr.File] | None, prefix: str = "enc") -> Tuple[Optional[str], Optional[str]]:
 
983
  with gr.Row():
984
  tile = gr.Number(value=0, label="Tile size (0 = auto)")
985
  precision = gr.Dropdown(["auto", "half", "full"], value="auto", label="Precision (GPU=half, CPU=full)")
986
+ with gr.Row():
987
+ batch_size = gr.Number(value=16, precision=0, label="Batch size (images per batch)")
988
+ max_images = gr.Number(value=0, precision=0, label="Max images to process (0 = all)")
989
+
990
  with gr.Row():
991
  btn_upscale = gr.Button("Step 2: Upscale", variant="primary")
992
 
 
997
 
998
  btn_upscale.click(
999
  step2_upscale,
1000
+ inputs=[frames_state, ui_model_name, outscale, tile, precision, prog2, imgs_override, denoise_strength, face_enhance, batch_size, max_images],
1001
  outputs=[gallery_up, zip_up, details2, prog2],
1002
  )
1003