weijielyu commited on
Commit
f423985
·
1 Parent(s): 918c308
Files changed (1) hide show
  1. app.py +47 -55
app.py CHANGED
@@ -331,74 +331,54 @@ class FaceLiftPipeline:
331
  print(f"Error details:\n{error_details}")
332
  raise gr.Error(f"Generation failed: {str(e)}")
333
 
334
- # Create viewer HTML that references external viewer.js
335
  def create_splat_viewer_html(ply_url: str, viewer_js_url: str, viewer_id: str) -> str:
336
- """Create HTML with splat viewer that loads a PLY file via external script."""
337
 
338
- return f"""
339
- <iframe id="viewer-frame-{viewer_id}" style="width:100%; height:600px; border:1px solid #333; border-radius:8px;" srcdoc='
340
- <!DOCTYPE html>
 
 
 
 
 
 
341
  <html>
342
  <head>
343
  <meta charset="utf-8">
 
 
344
  <style>
345
  body {{ margin: 0; overflow: hidden; background: #000; }}
346
  #canvas {{ width: 100vw; height: 100vh; display: block; }}
347
  #spinner {{
348
- position: absolute;
349
- top: 50%;
350
- left: 50%;
351
  transform: translate(-50%, -50%);
352
- color: white;
353
- font-family: Arial;
354
- z-index: 10;
355
- text-align: center;
356
- background: rgba(0,0,0,0.8);
357
- padding: 20px;
358
- border-radius: 8px;
359
- }}
360
- #progress {{
361
- background: #4CAF50;
362
- height: 4px;
363
- width: 0%;
364
- transition: width 0.3s;
365
  }}
 
366
  #message {{
367
- position: absolute;
368
- top: 50%;
369
- left: 50%;
370
  transform: translate(-50%, -50%);
371
- color: #ff4444;
372
- font-family: Arial;
373
- font-size: 14px;
374
- background: rgba(0,0,0,0.9);
375
- padding: 20px;
376
- border-radius: 8px;
377
- display: none;
378
- z-index: 11;
379
  }}
380
  #fps, #camid {{
381
- position: absolute;
382
- right: 10px;
383
- color: white;
384
- font-family: monospace;
385
- font-size: 11px;
386
- background: rgba(0,0,0,0.7);
387
- padding: 6px 10px;
388
- border-radius: 4px;
389
- display: none;
390
  }}
391
  #fps {{ top: 10px; }}
392
  #camid {{ top: 40px; }}
393
  #controls-info {{
394
- position: absolute;
395
- bottom: 10px;
396
- left: 10px;
397
- color: white;
398
- font-family: Arial;
399
- font-size: 11px;
400
- background: rgba(0,0,0,0.7);
401
- padding: 8px 12px;
402
  border-radius: 4px;
403
  }}
404
  </style>
@@ -418,14 +398,15 @@ def create_splat_viewer_html(ply_url: str, viewer_js_url: str, viewer_id: str) -
418
  <strong>Controls:</strong> Drag: Rotate | Scroll: Zoom | Right-drag: Pan
419
  </div>
420
 
421
- <script src="{viewer_js_url}"></script>
 
 
 
422
  <script>
423
  // Auto-load PLY after viewer initializes
424
  const plyUrl = "{ply_url}";
425
- const viewerJsUrl = "{viewer_js_url}";
426
  console.log("=== Splat Viewer Init ===");
427
  console.log("PLY URL:", plyUrl);
428
- console.log("Viewer JS URL:", viewerJsUrl);
429
 
430
  let attempts = 0;
431
  const checkAndLoad = setInterval(function() {{
@@ -459,14 +440,25 @@ def create_splat_viewer_html(ply_url: str, viewer_js_url: str, viewer_id: str) -
459
  clearInterval(checkAndLoad);
460
  document.getElementById("spinner").style.display = "none";
461
  const msg = document.getElementById("message");
462
- msg.textContent = "Viewer failed to initialize. Check console for viewer.js errors.";
463
  msg.style.display = "block";
464
  }}
465
  }}, 100);
466
  </script>
467
  </body>
468
- </html>
469
- '></iframe>
 
 
 
 
 
 
 
 
 
 
 
470
  """
471
 
472
  def main():
 
331
  print(f"Error details:\n{error_details}")
332
  raise gr.Error(f"Generation failed: {str(e)}")
333
 
334
+ # Create viewer HTML file that can be served by Gradio
335
  def create_splat_viewer_html(ply_url: str, viewer_js_url: str, viewer_id: str) -> str:
336
+ """Create a standalone HTML file with embedded viewer for the PLY file."""
337
 
338
+ # Read viewer.js content
339
+ viewer_js_path = Path(__file__).parent / "viewer.js"
340
+ viewer_js_content = viewer_js_path.read_text() if viewer_js_path.exists() else "console.error('viewer.js not found');"
341
+
342
+ # Create HTML file in outputs directory
343
+ output_dir = Path(ply_url.replace("/file=", "").rsplit("/", 1)[0])
344
+ viewer_html_path = output_dir / f"viewer_{viewer_id}.html"
345
+
346
+ html_content = f"""<!DOCTYPE html>
347
  <html>
348
  <head>
349
  <meta charset="utf-8">
350
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
351
+ <title>3D Gaussian Splat Viewer</title>
352
  <style>
353
  body {{ margin: 0; overflow: hidden; background: #000; }}
354
  #canvas {{ width: 100vw; height: 100vh; display: block; }}
355
  #spinner {{
356
+ position: absolute; top: 50%; left: 50%;
 
 
357
  transform: translate(-50%, -50%);
358
+ color: white; font-family: Arial; z-index: 10;
359
+ text-align: center; background: rgba(0,0,0,0.8);
360
+ padding: 20px; border-radius: 8px;
 
 
 
 
 
 
 
 
 
 
361
  }}
362
+ #progress {{ background: #4CAF50; height: 4px; width: 0%; transition: width 0.3s; }}
363
  #message {{
364
+ position: absolute; top: 50%; left: 50%;
 
 
365
  transform: translate(-50%, -50%);
366
+ color: #ff4444; font-family: Arial; font-size: 14px;
367
+ background: rgba(0,0,0,0.9); padding: 20px;
368
+ border-radius: 8px; display: none; z-index: 11;
 
 
 
 
 
369
  }}
370
  #fps, #camid {{
371
+ position: absolute; right: 10px;
372
+ color: white; font-family: monospace; font-size: 11px;
373
+ background: rgba(0,0,0,0.7); padding: 6px 10px;
374
+ border-radius: 4px; display: none;
 
 
 
 
 
375
  }}
376
  #fps {{ top: 10px; }}
377
  #camid {{ top: 40px; }}
378
  #controls-info {{
379
+ position: absolute; bottom: 10px; left: 10px;
380
+ color: white; font-family: Arial; font-size: 11px;
381
+ background: rgba(0,0,0,0.7); padding: 8px 12px;
 
 
 
 
 
382
  border-radius: 4px;
383
  }}
384
  </style>
 
398
  <strong>Controls:</strong> Drag: Rotate | Scroll: Zoom | Right-drag: Pan
399
  </div>
400
 
401
+ <script>
402
+ {viewer_js_content}
403
+ </script>
404
+
405
  <script>
406
  // Auto-load PLY after viewer initializes
407
  const plyUrl = "{ply_url}";
 
408
  console.log("=== Splat Viewer Init ===");
409
  console.log("PLY URL:", plyUrl);
 
410
 
411
  let attempts = 0;
412
  const checkAndLoad = setInterval(function() {{
 
440
  clearInterval(checkAndLoad);
441
  document.getElementById("spinner").style.display = "none";
442
  const msg = document.getElementById("message");
443
+ msg.textContent = "Viewer failed to initialize.";
444
  msg.style.display = "block";
445
  }}
446
  }}, 100);
447
  </script>
448
  </body>
449
+ </html>"""
450
+
451
+ # Write HTML file
452
+ viewer_html_path.write_text(html_content)
453
+
454
+ # Return iframe that loads this HTML file
455
+ viewer_html_url = f"/file={viewer_html_path}"
456
+
457
+ return f"""
458
+ <iframe id="viewer-frame-{viewer_id}" src="{viewer_html_url}" style="width:100%; height:600px; border:1px solid #333; border-radius:8px;" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
459
+ <p style="font-size:11px; color:#666; margin-top:5px;">
460
+ <a href="{viewer_html_url}" target="_blank" style="color:#4CAF50;">Open in new tab</a> for better performance
461
+ </p>
462
  """
463
 
464
  def main():