VISHAL18for4 commited on
Commit
544b2bd
Β·
verified Β·
1 Parent(s): 88bbbe2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -36
app.py CHANGED
@@ -417,6 +417,37 @@ function swDownload() {
417
  """
418
 
419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  # ────────────────────────────────────────────────────────────────
421
  # UI β€” css in gr.Blocks() (correct for all Gradio versions)
422
  # ────────────────────────────────────────────────────────────────
@@ -474,12 +505,9 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
474
  # 3D viewer β€” always visible, waits for content
475
  gr.HTML(VIEWER_SHELL)
476
 
477
- # Hidden File component β€” Gradio serves this over its normal
478
- # file route and gives the frontend a real URL for it (via the
479
- # .change(js=...) wiring below), so the browser can fetch() the
480
- # raw bytes directly instead of us shipping a giant base64
481
- # string through the page.
482
- ply_file = gr.File(visible=False, elem_id="sw-ply-file", label="ply")
483
 
484
  # ── Tab 2: Two angles + animation ───────────────────
485
  with gr.TabItem("🎬 Two Angles β†’ Animation"):
@@ -541,17 +569,18 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
541
  def handle_single(img):
542
  print(f"[handle_single] click received, img={img}", flush=True)
543
  if img is None:
544
- return "⚠ Please upload a photo first.", gr.update(value=None, visible=False)
545
  try:
546
  ply, status = run_sharp(img)
547
  except Exception as e:
548
  print(f"[handle_single] GPU call raised: {e}", flush=True)
549
  return (f"⚠ GPU rejected the request: {str(e)}\n(If this mentions quota/duration, you've hit your daily free ZeroGPU limit β€” wait for it to reset, or sign in with a HF account for a bigger quota.)",
550
- gr.update(value=None, visible=False))
551
  print(f"[handle_single] run_sharp returned ply={ply!r} status={status!r}", flush=True)
552
  if ply:
553
- return status, gr.update(value=ply, visible=False)
554
- return status, gr.update(value=None, visible=False)
 
555
 
556
  def handle_dual(a, b, do_anim):
557
  if a is None or b is None:
@@ -590,34 +619,9 @@ with gr.Blocks(css=CSS, title="SplatWeb") as demo:
590
 
591
  return msg, html_out
592
 
593
- btn1.click(fn=handle_single, inputs=[img1], outputs=[st1, ply_file])
594
  btn2.click(fn=handle_dual, inputs=[imgA, imgB, anim_toggle], outputs=[st2, anim_file])
595
 
596
- # This is the load-bearing wire: whenever ply_file's value changes
597
- # (including programmatically, from handle_single's return), Gradio
598
- # hands this JS function the component's real FileData β€” the same
599
- # {path, url, size, ...} object it uses internally β€” no DOM-scraping,
600
- # no guessing routes. fn=None means this runs client-side only, no
601
- # extra server round-trip.
602
- ply_file.change(
603
- fn=None, inputs=[ply_file], outputs=[],
604
- js="""
605
- (file) => {
606
- const log = (m) => { if (window.swLog) window.swLog(m); else console.log('[SplatWeb]', m); };
607
- log('ply_file component changed: ' + JSON.stringify(file));
608
- if (file && file.url) {
609
- const mb = file.size ? (file.size / 1024 / 1024).toFixed(2) : '';
610
- if (window.swLoadUrl) { window.swLoadUrl(file.url, mb); }
611
- else { log('ERROR: viewer script not ready yet β€” reload the page and try again'); }
612
- } else if (file) {
613
- log('ERROR: file has no .url field (got: ' + Object.keys(file).join(',') + ') β€” Gradio version mismatch?');
614
- } else {
615
- log('cleared / no file');
616
- }
617
- }
618
- """
619
- )
620
-
621
  gr.HTML("""
622
  <div style="text-align:center;padding:1.5rem 1rem;
623
  border-top:1px solid rgba(80,130,255,0.07);margin-top:1.5rem;">
 
417
  """
418
 
419
 
420
+ # Gradio serves any file under its allowed paths (which includes the
421
+ # system temp dir β€” where our .ply files live) at this documented route:
422
+ # /gradio_api/file=<path>
423
+ # See: https://gradio.app/guides/file-access
424
+ # Building this URL ourselves in Python is deterministic β€” unlike reading
425
+ # it back off a File component's FileData, whose `.url` field can still be
426
+ # null at the moment a change event fires (it gets filled in later by the
427
+ # frontend's own render pass), which is what left the viewer stuck idle.
428
+ def make_load_trigger(ply_path: str, size_mb) -> str:
429
+ import urllib.parse
430
+ url = "/gradio_api/file=" + urllib.parse.quote(ply_path, safe="/")
431
+ url_js = url.replace("\\", "\\\\").replace("'", "\\'")
432
+ return f"""
433
+ <script>
434
+ (function() {{
435
+ var tries = 0;
436
+ (function tryLoad() {{
437
+ tries++;
438
+ if (typeof window.swLoadUrl === 'function') {{
439
+ window.swLoadUrl('{url_js}', '{size_mb}');
440
+ }} else if (tries < 50) {{
441
+ setTimeout(tryLoad, 100);
442
+ }} else if (window.swLog) {{
443
+ window.swLog('ERROR: viewer script never became ready β€” try reloading the page');
444
+ }}
445
+ }})();
446
+ }})();
447
+ </script>
448
+ """
449
+
450
+
451
  # ────────────────────────────────────────────────────────────────
452
  # UI β€” css in gr.Blocks() (correct for all Gradio versions)
453
  # ────────────────────────────────────────────────────────────────
 
505
  # 3D viewer β€” always visible, waits for content
506
  gr.HTML(VIEWER_SHELL)
507
 
508
+ # Hidden trigger β€” a tiny script (just a URL string, never the
509
+ # file bytes) telling the viewer where to fetch the model from.
510
+ trigger1 = gr.HTML(value="", visible=False)
 
 
 
511
 
512
  # ── Tab 2: Two angles + animation ───────────────────
513
  with gr.TabItem("🎬 Two Angles β†’ Animation"):
 
569
  def handle_single(img):
570
  print(f"[handle_single] click received, img={img}", flush=True)
571
  if img is None:
572
+ return "⚠ Please upload a photo first.", gr.update(value="", visible=False)
573
  try:
574
  ply, status = run_sharp(img)
575
  except Exception as e:
576
  print(f"[handle_single] GPU call raised: {e}", flush=True)
577
  return (f"⚠ GPU rejected the request: {str(e)}\n(If this mentions quota/duration, you've hit your daily free ZeroGPU limit β€” wait for it to reset, or sign in with a HF account for a bigger quota.)",
578
+ gr.update(value="", visible=False))
579
  print(f"[handle_single] run_sharp returned ply={ply!r} status={status!r}", flush=True)
580
  if ply:
581
+ size_mb = round(os.path.getsize(ply) / 1024 / 1024, 2)
582
+ return status, gr.update(value=make_load_trigger(ply, size_mb), visible=True)
583
+ return status, gr.update(value="", visible=False)
584
 
585
  def handle_dual(a, b, do_anim):
586
  if a is None or b is None:
 
619
 
620
  return msg, html_out
621
 
622
+ btn1.click(fn=handle_single, inputs=[img1], outputs=[st1, trigger1])
623
  btn2.click(fn=handle_dual, inputs=[imgA, imgB, anim_toggle], outputs=[st2, anim_file])
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  gr.HTML("""
626
  <div style="text-align:center;padding:1.5rem 1rem;
627
  border-top:1px solid rgba(80,130,255,0.07);margin-top:1.5rem;">