JS6969 commited on
Commit
fa918de
·
verified ·
1 Parent(s): 50ccb3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -20
app.py CHANGED
@@ -46,6 +46,34 @@ from basicsr.utils.download_util import load_file_from_url
46
  from realesrgan import RealESRGANer
47
  from realesrgan.archs.srvgg_arch import SRVGGNetCompact
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  # Flag so UI can know if realesrgan is importable
50
  HAVE_REALESRGAN = True
51
 
@@ -158,13 +186,22 @@ def clamp_scale_for_model(outscale: int, model_id: str) -> int:
158
 
159
 
160
  def sample_paths(paths: List[Path] | List[str], n: int = 30) -> List[str]:
161
- """Return up to n items sampled evenly across the list, preserving order (as strings)."""
162
  if not paths:
163
  return []
164
- n = max(1, min(n, len(paths)))
165
- idxs = np.linspace(0, len(paths) - 1, num=n, dtype=int).tolist()
166
- idxs = sorted(dict.fromkeys(idxs))
167
- return [str(paths[i]) for i in idxs]
 
 
 
 
 
 
 
 
 
168
 
169
 
170
  def sanitize_prefix(txt: str) -> str:
@@ -281,6 +318,8 @@ def build_ffmpeg_extract(
281
  cmd += ["-frame_pts", "1", out_pattern]
282
  return cmd
283
 
 
 
284
 
285
  def realesrgan(img, model_name, denoise_strength, face_enhance, outscale):
286
  if img is None:
@@ -480,8 +519,7 @@ def step1_extract(
480
  last_html = render_progress(0.0, f"Extracting… {created} created")
481
  ret = proc.wait()
482
 
483
- frames = sorted(raw_dir.glob(f"{prefix}_*.{out_format}"))
484
- if ret != 0 or not frames:
485
  try:
486
  err = proc.stderr.read() if proc.stderr else ""
487
  except Exception:
@@ -516,14 +554,12 @@ def save_uploaded_images(files: List[gr.File] | None, prefix: str = "upload") ->
516
 
517
  def step2_upscale(
518
  frames_list: List[str] | None,
519
- ui_model_name: str,
520
- outscale: int,
521
  tile: int,
522
  precision: str,
523
  prog_html: str,
524
  uploaded_imgs: List[gr.File] | None,
525
- denoise_strength: float = 0.5, # NEW: accepted but currently unused
526
- face_enhance: bool = False, # NEW: accepted but currently unused (needs GFPGAN)
527
  ):
528
 
529
  # decide source: uploaded images take priority, else frames from step 1
@@ -534,7 +570,8 @@ def step2_upscale(
534
  src_paths = frames_list or []
535
 
536
  if not src_paths:
537
- return None, None, "No images provided. Upload files or run Step 1 first.", prog_html
 
538
 
539
  # Map demo model -> internal, clamp scale to supported values
540
  model_id = map_ui_model_to_internal(ui_model_name)
@@ -550,6 +587,8 @@ def step2_upscale(
550
  total = len(src_paths)
551
  done = 0
552
  up_paths: List[Path] = []
 
 
553
  for fp in src_paths:
554
  try:
555
  img = Image.open(fp).convert("RGB")
@@ -561,22 +600,29 @@ def step2_upscale(
561
  except Exception:
562
  pass
563
  done += 1
564
- pct = (done/total)*100 if total else 0
565
- prog_html = render_progress(pct, f"Upscaling {done}/{total}")
 
 
 
 
 
 
 
566
 
567
  if not up_paths:
568
- return None, None, "Upscaling produced no outputs.", prog_html
 
569
 
 
570
  gallery = sample_paths(up_paths, 30)
571
  zip_path = work / "upscaled.zip"
572
  with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
573
  for p in up_paths:
574
  zf.write(p, p.name)
575
 
576
- detail = (f"Upscaled: {len(up_paths)} | Model: {ui_model_name}→{model_id} | "
577
- f"Scale: x{scale} | Tile: {tile} | Precision: {precision}")
578
-
579
- return gallery, str(zip_path), f"Upscaled: {len(up_paths)}", render_progress(100.0, "Upscaling complete")
580
 
581
  # ───────────────── Encode (Step 3) — supports uploaded frames/ZIP & optional audio source
582
 
@@ -752,7 +798,7 @@ def quick_mode(video: gr.File | None, start_time: str, end_time: str, resize_lon
752
  zf.write(p, p.name)
753
  zip_up = work / "upscaled.zip"
754
  with zipfile.ZipFile(zip_up, "w", zipfile.ZIP_DEFLATED) as zf:
755
- for p in sorted(up_dir.glob("*.jpg")):
756
  zf.write(p, p.name)
757
 
758
  return str(out_file), str(zip_frames), str(zip_up), "Quick Mode complete.", render_progress(100.0, "All done")
 
46
  from realesrgan import RealESRGANer
47
  from realesrgan.archs.srvgg_arch import SRVGGNetCompact
48
 
49
+ _num = re.compile(r'(\d+)')
50
+
51
+ def _natural_key(p: Path | str):
52
+ s = str(p)
53
+ return [int(t) if t.isdigit() else t.lower() for t in _num.split(s)]
54
+
55
+ def sample_paths(paths: List[Path] | List[str], n: int = 30) -> List[str]:
56
+ """Evenly sample up to n items across the entire list, in order."""
57
+ if not paths:
58
+ return []
59
+ # Ensure stable numeric ordering first (00001, 00002, ... 01000)
60
+ paths = sorted(paths, key=_natural_key)
61
+ total = len(paths)
62
+ n = max(1, min(n, total))
63
+ if n == total:
64
+ return [str(p) for p in paths]
65
+ # Even spacing (no duplicates), covering start→end
66
+ step = (total - 1) / (n - 1)
67
+ idxs = [round(i * step) for i in range(n)]
68
+ # De-dupe in case of edge rounding on tiny sets
69
+ out = []
70
+ seen = set()
71
+ for i in idxs:
72
+ if i not in seen:
73
+ out.append(str(paths[i]))
74
+ seen.add(i)
75
+ return out
76
+
77
  # Flag so UI can know if realesrgan is importable
78
  HAVE_REALESRGAN = True
79
 
 
186
 
187
 
188
  def sample_paths(paths: List[Path] | List[str], n: int = 30) -> List[str]:
189
+ """Evenly sample up to n items across the entire list (deterministic), in natural numeric order."""
190
  if not paths:
191
  return []
192
+ paths = sorted(paths, key=_natural_key) # ensure numeric order first
193
+ total = len(paths)
194
+ n = max(1, min(n, total))
195
+ if n == total:
196
+ return [str(p) for p in paths]
197
+ step = (total - 1) / (n - 1) # cover both ends
198
+ idxs = [round(i * step) for i in range(n)]
199
+ out, seen = [], set()
200
+ for i in idxs:
201
+ if i not in seen:
202
+ out.append(str(paths[int(i)]))
203
+ seen.add(int(i))
204
+ return out
205
 
206
 
207
  def sanitize_prefix(txt: str) -> str:
 
318
  cmd += ["-frame_pts", "1", out_pattern]
319
  return cmd
320
 
321
+ frames = sorted(raw_dir.glob(f"{prefix}_*.{out_format}"), key=_natural_key)
322
+ gallery = sample_paths(frames, 30)
323
 
324
  def realesrgan(img, model_name, denoise_strength, face_enhance, outscale):
325
  if img is None:
 
519
  last_html = render_progress(0.0, f"Extracting… {created} created")
520
  ret = proc.wait()
521
 
522
+ frames = sorted(raw_dir.glob(f"{prefix}_*.{out_format}"), key=_natural_key)
 
523
  try:
524
  err = proc.stderr.read() if proc.stderr else ""
525
  except Exception:
 
554
 
555
  def step2_upscale(
556
  frames_list: List[str] | None,
557
+ model_name: str,
558
+ scale: int,
559
  tile: int,
560
  precision: str,
561
  prog_html: str,
562
  uploaded_imgs: List[gr.File] | None,
 
 
563
  ):
564
 
565
  # decide source: uploaded images take priority, else frames from step 1
 
570
  src_paths = frames_list or []
571
 
572
  if not src_paths:
573
+ yield None, None, "No images provided. Upload files or run Step 1 first.", prog_html
574
+ return
575
 
576
  # Map demo model -> internal, clamp scale to supported values
577
  model_id = map_ui_model_to_internal(ui_model_name)
 
587
  total = len(src_paths)
588
  done = 0
589
  up_paths: List[Path] = []
590
+
591
+ last_pct = -1
592
  for fp in src_paths:
593
  try:
594
  img = Image.open(fp).convert("RGB")
 
600
  except Exception:
601
  pass
602
  done += 1
603
+ if total:
604
+ pct = int(round((done / total) * 100))
605
+ remaining = max(0, total - done)
606
+ if pct != last_pct:
607
+ label = f"Upscaling… {pct}% · {remaining}/{total} remaining"
608
+ prog_html = render_progress(pct, label)
609
+ # stream progress (gallery/zip stay None until the end)
610
+ yield None, None, label, prog_html
611
+ last_pct = pct
612
 
613
  if not up_paths:
614
+ yield None, None, "Upscaling produced no outputs.", prog_html
615
+ return
616
 
617
+ # Final outputs
618
  gallery = sample_paths(up_paths, 30)
619
  zip_path = work / "upscaled.zip"
620
  with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
621
  for p in up_paths:
622
  zf.write(p, p.name)
623
 
624
+ final_label = f"Upscaled: {len(up_paths)}"
625
+ yield gallery, str(zip_path), final_label, render_progress(100.0, "Upscaling complete")
 
 
626
 
627
  # ───────────────── Encode (Step 3) — supports uploaded frames/ZIP & optional audio source
628
 
 
798
  zf.write(p, p.name)
799
  zip_up = work / "upscaled.zip"
800
  with zipfile.ZipFile(zip_up, "w", zipfile.ZIP_DEFLATED) as zf:
801
+ for p in sorted(up_dir.glob("*.jpg"), key=_natural_key):
802
  zf.write(p, p.name)
803
 
804
  return str(out_file), str(zip_frames), str(zip_up), "Quick Mode complete.", render_progress(100.0, "All done")