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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -19
app.py CHANGED
@@ -532,6 +532,94 @@ def step1_extract(
532
 
533
  # ───────────────── Upscale (Step 2) — supports uploaded images OR frames from Step 1
534
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
  def save_uploaded_images(files: List[gr.File] | None, prefix: str = "upload") -> Tuple[List[Path], Path]:
536
  tmp = Path(tempfile.mkdtemp(prefix="imgup_"))
537
  in_dir = tmp / "input"; in_dir.mkdir(parents=True, exist_ok=True)
@@ -874,7 +962,12 @@ def build_ui():
874
  frames_dir_state = gr.State("") # str
875
  prefix_state = gr.State("") # str
876
  fps_state = gr.State(30.0) # float
877
-
 
 
 
 
 
878
  with gr.Tabs():
879
  # STEP 1
880
  with gr.Tab("Step 1 · Extract Frames"):
@@ -970,37 +1063,44 @@ def build_ui():
970
  value="RealESRGAN_x4plus",
971
  show_label=True
972
  )
973
- denoise_strength = gr.Slider(
974
- label="Denoise Strength (only for realesr-general-x4v3)",
975
- minimum=0, maximum=1, step=0.1, value=0.5
976
- )
977
- outscale = gr.Slider(
978
- label="Resolution upscale",
979
- minimum=1, maximum=6, step=1, value=4, show_label=True
980
- )
981
- face_enhance = gr.Checkbox(label="Face Enhancement (GFPGAN)", value=False)
982
 
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
 
993
  prog2 = gr.HTML(render_progress(0.0, "Idle"))
994
  gallery_up = gr.Gallery(label="Upscaled preview (30 sampled)", columns=6, height=480)
995
  zip_up = gr.File(label="Download upscaled ZIP")
996
  details2 = gr.Markdown("")
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
 
 
1004
  # STEP 3 — Re-encode
1005
  with gr.Tab("Step 3 · Re-encode Video"):
1006
  gr.Markdown("Use frames from Step 1 **or** upload a frames ZIP / images. Optionally provide a video for audio track.")
 
532
 
533
  # ───────────────── Upscale (Step 2) — supports uploaded images OR frames from Step 1
534
 
535
+ # Manual-batch Step 2 helpers (resumable, click-to-advance)
536
+ def _ensure_dir(p: Path) -> Path:
537
+ p.mkdir(parents=True, exist_ok=True)
538
+ return p
539
+
540
+ def _save_zip_of_dir(dir_path: Path, zip_path: Path) -> str:
541
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
542
+ for p in sorted(dir_path.glob("*.*"), key=_natural_key):
543
+ if p.suffix.lower() in [".jpg", ".jpeg", ".png"]:
544
+ zf.write(p, p.name)
545
+ return str(zip_path)
546
+
547
+ def _list_image_paths_from_upload(files: List[gr.File] | None) -> List[str]:
548
+ if not files: return []
549
+ return [str(Path(f.name)) for f in files if Path(f.name).suffix.lower() in [".jpg",".jpeg",".png"]]
550
+
551
+ def _build_gallery_from_dir(dir_path: Path, n: int = 30) -> List[str]:
552
+ paths = sorted(list(dir_path.glob("*.jpg")) + list(dir_path.glob("*.png")), key=_natural_key)
553
+ return sample_paths(paths, n)
554
+
555
+ def step2_prepare_sources(frames_list, uploaded_imgs, max_images):
556
+ src = _list_image_paths_from_upload(uploaded_imgs) or (frames_list or [])
557
+ if not src:
558
+ return [], "", 0, 0, "No images found. Upload files or run Step 1 first.", render_progress(0.0, "Idle")
559
+ try:
560
+ max_images = int(max_images or 0)
561
+ except Exception:
562
+ max_images = 0
563
+ if max_images > 0:
564
+ src = src[:max_images]
565
+ work = Path(tempfile.mkdtemp(prefix="up_manual_"))
566
+ out_dir = _ensure_dir(work / "upscaled")
567
+ total = len(src)
568
+ done_idx = 0
569
+ msg = f"Sources loaded: {total} image(s). Click 'Process Next Batch' to start."
570
+ prog = render_progress(0.0, "Ready")
571
+ return src, str(out_dir), done_idx, total, msg, prog
572
+
573
+ def step2_process_next_batch(
574
+ up_src_paths, up_out_dir, up_done_idx, up_total,
575
+ ui_model_name, outscale, tile, precision, denoise_strength, face_enhance, batch_size,
576
+ ):
577
+ if not up_src_paths or not up_out_dir:
578
+ return None, None, "Load sources first.", render_progress(0.0, "Idle"), up_done_idx, up_out_dir
579
+ model_id = map_ui_model_to_internal(ui_model_name)
580
+ scale = clamp_scale_for_model(int(outscale or 4), model_id)
581
+ device = "cuda" if os.environ.get("CUDA_VISIBLE_DEVICES") else "cpu"
582
+ half = (precision == "half") and (device == "cuda")
583
+ tile = int(tile or 256)
584
+ batch_size = max(1, int(batch_size or 8))
585
+ upsampler = get_realesrganer(model_id, scale, tile, half, device=device)
586
+
587
+ start = int(up_done_idx or 0)
588
+ end = min(start + batch_size, int(up_total or 0))
589
+ out_dir = Path(up_out_dir)
590
+
591
+ if start >= up_total:
592
+ gallery = _build_gallery_from_dir(out_dir, 30)
593
+ zip_path = Path(out_dir.parent) / "upscaled.zip"
594
+ zip_file = _save_zip_of_dir(out_dir, zip_path)
595
+ prog = render_progress(100.0, "All images processed")
596
+ details = f"Done. Total upscaled: {len(list(out_dir.glob('*.jpg')))+len(list(out_dir.glob('*.png')))}"
597
+ return gallery, zip_file, details, prog, start, up_out_dir
598
+
599
+ processed_now = 0
600
+ for fp in up_src_paths[start:end]:
601
+ try:
602
+ with Image.open(fp) as im:
603
+ img = im.convert("RGB")
604
+ output, _ = upsampler.enhance(np.array(img), outscale=scale)
605
+ Image.fromarray(output).save(out_dir / (Path(fp).stem + ".jpg"), quality=95)
606
+ except Exception:
607
+ pass
608
+ processed_now += 1
609
+
610
+ next_idx = end
611
+ pct = int(round((next_idx / up_total) * 100)) if up_total else 0
612
+ label = (f"Processed {processed_now} image(s) this batch. "
613
+ f"{next_idx}/{up_total} done (x{scale}, model={ui_model_name}).")
614
+ prog = render_progress(pct, f"Upscaling… {pct}%")
615
+
616
+ gallery = _build_gallery_from_dir(out_dir, 30)
617
+ zip_path = Path(out_dir.parent) / "upscaled.zip"
618
+ zip_file = _save_zip_of_dir(out_dir, zip_path)
619
+ return gallery, zip_file, label, prog, next_idx, up_out_dir
620
+
621
+
622
+
623
  def save_uploaded_images(files: List[gr.File] | None, prefix: str = "upload") -> Tuple[List[Path], Path]:
624
  tmp = Path(tempfile.mkdtemp(prefix="imgup_"))
625
  in_dir = tmp / "input"; in_dir.mkdir(parents=True, exist_ok=True)
 
962
  frames_dir_state = gr.State("") # str
963
  prefix_state = gr.State("") # str
964
  fps_state = gr.State(30.0) # float
965
+ # Shared Step 2 states (manual batching)
966
+ up_src_paths_state = gr.State([]) # list[str] absolute paths to process
967
+ up_out_dir_state = gr.State("") # str: output dir path
968
+ up_done_idx_state = gr.State(0) # int: next index to start from
969
+ up_total_state = gr.State(0) # int: total images
970
+
971
  with gr.Tabs():
972
  # STEP 1
973
  with gr.Tab("Step 1 · Extract Frames"):
 
1063
  value="RealESRGAN_x4plus",
1064
  show_label=True
1065
  )
1066
+ denoise_strength = gr.Slider(0, 1, value=0.5, step=0.1, label="Denoise (only general-x4v3)")
1067
+ outscale = gr.Slider(1, 6, value=4, step=1, label="Resolution upscale")
1068
+ face_enhance = gr.Checkbox(value=False, label="Face Enhancement (GFPGAN)")
 
 
 
 
 
 
1069
 
1070
  with gr.Row():
1071
+ tile = gr.Number(value=256, label="Tile size (try 128 if OOM; 0=auto)")
1072
  precision = gr.Dropdown(["auto", "half", "full"], value="auto", label="Precision (GPU=half, CPU=full)")
1073
  with gr.Row():
1074
+ batch_size = gr.Number(value=12, precision=0, label="Batch size per click")
1075
  max_images = gr.Number(value=0, precision=0, label="Max images to process (0 = all)")
1076
+
1077
  with gr.Row():
1078
+ btn_prepare = gr.Button("Step 2: Load / Reset Sources", variant="secondary")
1079
+ btn_next = gr.Button("Process Next Batch", variant="primary")
1080
 
1081
  prog2 = gr.HTML(render_progress(0.0, "Idle"))
1082
  gallery_up = gr.Gallery(label="Upscaled preview (30 sampled)", columns=6, height=480)
1083
  zip_up = gr.File(label="Download upscaled ZIP")
1084
  details2 = gr.Markdown("")
1085
+
1086
+ # 1) load/reset sources
1087
+ btn_prepare.click(
1088
+ step2_prepare_sources,
1089
+ inputs=[frames_state, imgs_override, max_images],
1090
+ outputs=[up_src_paths_state, up_out_dir_state, up_done_idx_state, up_total_state, details2, prog2]
1091
+ )
1092
+
1093
+ # 2) process one batch per click
1094
+ btn_next.click(
1095
+ step2_process_next_batch,
1096
+ inputs=[
1097
+ up_src_paths_state, up_out_dir_state, up_done_idx_state, up_total_state,
1098
+ ui_model_name, outscale, tile, precision, denoise_strength, face_enhance, batch_size
1099
+ ],
1100
+ outputs=[gallery_up, zip_up, details2, prog2, up_done_idx_state, up_out_dir_state]
1101
  )
1102
 
1103
+
1104
  # STEP 3 — Re-encode
1105
  with gr.Tab("Step 3 · Re-encode Video"):
1106
  gr.Markdown("Use frames from Step 1 **or** upload a frames ZIP / images. Optionally provide a video for audio track.")