akhaliq HF Staff commited on
Commit
769d659
1 Parent(s): 85f764f

Fix Invalid URL crash in runPipeline and surface file sizes

Browse files

new URL(artifactUrl) threw because the artifact URL is a relative path
("/gradio_api/file=..."). Drop the URL parse; instead return the file
size from each @app .api() endpoint alongside the URL, so the UI can
show real byte counts in the Scene tree and Telemetry grid.

Files changed (1) hide show
  1. app.py +18 -12
app.py CHANGED
@@ -88,7 +88,7 @@ def reconstruct(image_path: FileData) -> dict:
88
  seconds=round(time.perf_counter() - started, 3),
89
  bytes=artifact.stat().st_size,
90
  )
91
- return {"url": _file_url(artifact)}
92
 
93
 
94
  @app.api(name="export_ply", queue=True, concurrency_limit=2)
@@ -107,7 +107,7 @@ def export_ply(artifact_url: str) -> dict:
107
  seconds=round(time.perf_counter() - started, 3),
108
  bytes=scene_ply.stat().st_size,
109
  )
110
- return {"url": _file_url(scene_ply)}
111
 
112
 
113
  @app.api(name="export_viewer", queue=True, concurrency_limit=2)
@@ -126,7 +126,7 @@ def export_viewer(scene_ply_url: str) -> dict:
126
  sog_bytes=exported.scene_sog.stat().st_size,
127
  viewer_html_bytes=exported.viewer_html.stat().st_size,
128
  )
129
- return {"url": _file_url(exported.viewer_html)}
130
 
131
 
132
  @app.api(name="export_html", queue=True, concurrency_limit=2)
@@ -144,7 +144,7 @@ def export_html(viewer_html_url: str) -> dict:
144
  seconds=round(time.perf_counter() - started, 3),
145
  bytes=standalone.stat().st_size,
146
  )
147
- return {"url": _file_url(standalone)}
148
 
149
 
150
  @app.api(name="viewer_html", queue=False)
@@ -1293,11 +1293,12 @@ INDEX_HTML = r"""<!doctype html>
1293
  client.predict("/reconstruct", { image_path: handle_file(pendingFile) })
1294
  );
1295
  const artifactUrl = reconWrap.result.data[0].url;
 
1296
  stageTimings.gpu = reconWrap.ms;
1297
  setStage("reconstruct", "done", fmtSec(reconWrap.ms / 1000));
1298
  document.getElementById("telGpu").textContent = fmtSec(reconWrap.ms / 1000);
1299
- document.getElementById("telArtifact").textContent = fmtBytes(parseInt(new URL(artifactUrl).searchParams.get("size") || "0", 10)) || "ready";
1300
- logLine("reconstruct", "ok", `${fmtSec(reconWrap.ms / 1000)} 路 artifact ready`);
1301
 
1302
  // Stage 2: PLY export
1303
  setViewerState("loading", { title: "Preparing PLY", detail: "Filtering Gaussians", progress: 45, stageLabel: "STAGE 2 / 4 路 CPU" });
@@ -1307,9 +1308,11 @@ INDEX_HTML = r"""<!doctype html>
1307
  client.predict("/export_ply", { artifact_url: artifactUrl })
1308
  );
1309
  const plyUrl = plyWrap.result.data[0].url;
1310
- setStage("ply", "done", fmtSec(plyWrap.ms / 1000));
 
1311
  setDownload(dlPly, plyUrl, "Download PLY");
1312
- logLine("ply", "ok", `${fmtSec(plyWrap.ms / 1000)} 路 ${plyUrl.split("/").pop()}`);
 
1313
 
1314
  // Stage 3: Viewer
1315
  setViewerState("loading", { title: "Encoding viewer", detail: "Building WebGL scene", progress: 70, stageLabel: "STAGE 3 / 4 路 ENCODE" });
@@ -1319,14 +1322,16 @@ INDEX_HTML = r"""<!doctype html>
1319
  client.predict("/export_viewer", { scene_ply_url: plyUrl })
1320
  );
1321
  const viewerUrl = viewWrap.result.data[0].url + "?v=" + Date.now();
1322
- setStage("viewer", "done", fmtSec(viewWrap.ms / 1000));
 
 
1323
  viewerFrame.src = viewerUrl;
1324
  viewerFrame.onload = () => {
1325
  viewerFrame.classList.add("ready");
1326
  setViewerState("ready");
1327
  viewportMeta.textContent = "ready";
1328
  };
1329
- logLine("viewer", "ok", `${fmtSec(viewWrap.ms / 1000)} 路 WebGL scene ready`);
1330
 
1331
  // Stage 4: HTML
1332
  setViewerState("loading", { title: "Bundling HTML", detail: "Embedding assets for download", progress: 92, stageLabel: "STAGE 4 / 4 路 BUNDLE" });
@@ -1336,12 +1341,13 @@ INDEX_HTML = r"""<!doctype html>
1336
  client.predict("/export_html", { viewer_html_url: viewerUrl.replace(/[?#].*/, "") })
1337
  );
1338
  const htmlUrl = htmlWrap.result.data[0].url;
1339
- setStage("html", "done", fmtSec(htmlWrap.ms / 1000));
 
1340
  setDownload(dlHtml, htmlUrl, "Download HTML");
1341
 
1342
  const totalSec = (performance.now() - pipelineStart) / 1000;
1343
  document.getElementById("telTotal").textContent = fmtSec(totalSec);
1344
- logLine("html", "ok", `${fmtSec(htmlWrap.ms / 1000)} 路 standalone ready`);
1345
 
1346
  setViewerState("ready");
1347
  setStatus("idle", { gpu: "idle", queue: 0, stage: "4 / 4" });
 
88
  seconds=round(time.perf_counter() - started, 3),
89
  bytes=artifact.stat().st_size,
90
  )
91
+ return {"url": _file_url(artifact), "size": artifact.stat().st_size}
92
 
93
 
94
  @app.api(name="export_ply", queue=True, concurrency_limit=2)
 
107
  seconds=round(time.perf_counter() - started, 3),
108
  bytes=scene_ply.stat().st_size,
109
  )
110
+ return {"url": _file_url(scene_ply), "size": scene_ply.stat().st_size}
111
 
112
 
113
  @app.api(name="export_viewer", queue=True, concurrency_limit=2)
 
126
  sog_bytes=exported.scene_sog.stat().st_size,
127
  viewer_html_bytes=exported.viewer_html.stat().st_size,
128
  )
129
+ return {"url": _file_url(exported.viewer_html), "size": exported.viewer_html.stat().st_size}
130
 
131
 
132
  @app.api(name="export_html", queue=True, concurrency_limit=2)
 
144
  seconds=round(time.perf_counter() - started, 3),
145
  bytes=standalone.stat().st_size,
146
  )
147
+ return {"url": _file_url(standalone), "size": standalone.stat().st_size}
148
 
149
 
150
  @app.api(name="viewer_html", queue=False)
 
1293
  client.predict("/reconstruct", { image_path: handle_file(pendingFile) })
1294
  );
1295
  const artifactUrl = reconWrap.result.data[0].url;
1296
+ const artifactSize = reconWrap.result.data[0].size;
1297
  stageTimings.gpu = reconWrap.ms;
1298
  setStage("reconstruct", "done", fmtSec(reconWrap.ms / 1000));
1299
  document.getElementById("telGpu").textContent = fmtSec(reconWrap.ms / 1000);
1300
+ document.getElementById("telArtifact").textContent = fmtBytes(artifactSize);
1301
+ logLine("reconstruct", "ok", `${fmtSec(reconWrap.ms / 1000)} 路 ${fmtBytes(artifactSize)}`);
1302
 
1303
  // Stage 2: PLY export
1304
  setViewerState("loading", { title: "Preparing PLY", detail: "Filtering Gaussians", progress: 45, stageLabel: "STAGE 2 / 4 路 CPU" });
 
1308
  client.predict("/export_ply", { artifact_url: artifactUrl })
1309
  );
1310
  const plyUrl = plyWrap.result.data[0].url;
1311
+ const plySize = plyWrap.result.data[0].size;
1312
+ setStage("ply", "done", fmtBytes(plySize));
1313
  setDownload(dlPly, plyUrl, "Download PLY");
1314
+ document.getElementById("telPly").textContent = fmtBytes(plySize);
1315
+ logLine("ply", "ok", `${fmtSec(plyWrap.ms / 1000)} 路 ${fmtBytes(plySize)}`);
1316
 
1317
  // Stage 3: Viewer
1318
  setViewerState("loading", { title: "Encoding viewer", detail: "Building WebGL scene", progress: 70, stageLabel: "STAGE 3 / 4 路 ENCODE" });
 
1322
  client.predict("/export_viewer", { scene_ply_url: plyUrl })
1323
  );
1324
  const viewerUrl = viewWrap.result.data[0].url + "?v=" + Date.now();
1325
+ const viewerSize = viewWrap.result.data[0].size;
1326
+ setStage("viewer", "done", fmtBytes(viewerSize));
1327
+ document.getElementById("telViewer").textContent = fmtBytes(viewerSize);
1328
  viewerFrame.src = viewerUrl;
1329
  viewerFrame.onload = () => {
1330
  viewerFrame.classList.add("ready");
1331
  setViewerState("ready");
1332
  viewportMeta.textContent = "ready";
1333
  };
1334
+ logLine("viewer", "ok", `${fmtSec(viewWrap.ms / 1000)} 路 ${fmtBytes(viewerSize)}`);
1335
 
1336
  // Stage 4: HTML
1337
  setViewerState("loading", { title: "Bundling HTML", detail: "Embedding assets for download", progress: 92, stageLabel: "STAGE 4 / 4 路 BUNDLE" });
 
1341
  client.predict("/export_html", { viewer_html_url: viewerUrl.replace(/[?#].*/, "") })
1342
  );
1343
  const htmlUrl = htmlWrap.result.data[0].url;
1344
+ const htmlSize = htmlWrap.result.data[0].size;
1345
+ setStage("html", "done", fmtBytes(htmlSize));
1346
  setDownload(dlHtml, htmlUrl, "Download HTML");
1347
 
1348
  const totalSec = (performance.now() - pipelineStart) / 1000;
1349
  document.getElementById("telTotal").textContent = fmtSec(totalSec);
1350
+ logLine("html", "ok", `${fmtSec(htmlWrap.ms / 1000)} 路 ${fmtBytes(htmlSize)}`);
1351
 
1352
  setViewerState("ready");
1353
  setStatus("idle", { gpu: "idle", queue: 0, stage: "4 / 4" });