Spaces:
Running
Running
debugging
Browse files- backend/server.py +16 -5
- frontend/vehicles.html +22 -0
backend/server.py
CHANGED
|
@@ -39,7 +39,7 @@ async def lifespan(app: FastAPI):
|
|
| 39 |
# Warm up: run a dummy inference so OpenVINO compiles its graph now,
|
| 40 |
# not on the first real user request
|
| 41 |
try:
|
| 42 |
-
dummy = np.zeros((
|
| 43 |
model(dummy, verbose=False)
|
| 44 |
print("[BACKEND] Model warm-up complete.")
|
| 45 |
except Exception as e:
|
|
@@ -148,9 +148,12 @@ async def ws_run(ws: WebSocket):
|
|
| 148 |
report_format = data.get("report_format", "png")
|
| 149 |
|
| 150 |
path = videos.get(video_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
loop = asyncio.get_running_loop()
|
| 153 |
-
|
| 154 |
queue = asyncio.Queue()
|
| 155 |
|
| 156 |
def on_frame(update):
|
|
@@ -172,7 +175,7 @@ async def ws_run(ws: WebSocket):
|
|
| 172 |
|
| 173 |
await asyncio.sleep(0.05)
|
| 174 |
|
| 175 |
-
result = task.result()
|
| 176 |
result["report_format"] = report_format
|
| 177 |
run_results[video_id] = result
|
| 178 |
await ws.send_text(json.dumps({
|
|
@@ -183,8 +186,16 @@ async def ws_run(ws: WebSocket):
|
|
| 183 |
"speed_vs_realtime": result["speed_vs_realtime"],
|
| 184 |
}))
|
| 185 |
await ws.close()
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
|
| 189 |
|
| 190 |
app.mount("/", StaticFiles(directory=str(FRONTEND)), name="frontend")
|
|
|
|
| 39 |
# Warm up: run a dummy inference so OpenVINO compiles its graph now,
|
| 40 |
# not on the first real user request
|
| 41 |
try:
|
| 42 |
+
dummy = np.zeros((640, 640, 3), dtype=np.uint8) # HWC — what YOLO predict() expects
|
| 43 |
model(dummy, verbose=False)
|
| 44 |
print("[BACKEND] Model warm-up complete.")
|
| 45 |
except Exception as e:
|
|
|
|
| 148 |
report_format = data.get("report_format", "png")
|
| 149 |
|
| 150 |
path = videos.get(video_id)
|
| 151 |
+
if not path:
|
| 152 |
+
await ws.send_text(json.dumps({"error": f"Unknown video_id: {video_id}"}))
|
| 153 |
+
await ws.close()
|
| 154 |
+
return
|
| 155 |
|
| 156 |
loop = asyncio.get_running_loop()
|
|
|
|
| 157 |
queue = asyncio.Queue()
|
| 158 |
|
| 159 |
def on_frame(update):
|
|
|
|
| 175 |
|
| 176 |
await asyncio.sleep(0.05)
|
| 177 |
|
| 178 |
+
result = task.result() # re-raises any exception from the engine
|
| 179 |
result["report_format"] = report_format
|
| 180 |
run_results[video_id] = result
|
| 181 |
await ws.send_text(json.dumps({
|
|
|
|
| 186 |
"speed_vs_realtime": result["speed_vs_realtime"],
|
| 187 |
}))
|
| 188 |
await ws.close()
|
| 189 |
+
|
| 190 |
+
except Exception as e:
|
| 191 |
+
import traceback
|
| 192 |
+
err_msg = traceback.format_exc()
|
| 193 |
+
print(f"[BACKEND] Engine error for {video_id}:\n{err_msg}")
|
| 194 |
+
try:
|
| 195 |
+
await ws.send_text(json.dumps({"error": str(e), "detail": err_msg}))
|
| 196 |
+
await ws.close()
|
| 197 |
+
except Exception:
|
| 198 |
+
pass
|
| 199 |
|
| 200 |
|
| 201 |
app.mount("/", StaticFiles(directory=str(FRONTEND)), name="frontend")
|
frontend/vehicles.html
CHANGED
|
@@ -1352,6 +1352,28 @@
|
|
| 1352 |
ws.onmessage = e => {
|
| 1353 |
const d = JSON.parse(e.data);
|
| 1354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1355 |
if (d.done) {
|
| 1356 |
processingDone = true;
|
| 1357 |
document.getElementById('proc-label').innerText = 'Complete';
|
|
|
|
| 1352 |
ws.onmessage = e => {
|
| 1353 |
const d = JSON.parse(e.data);
|
| 1354 |
|
| 1355 |
+
// Backend engine error — surface it clearly
|
| 1356 |
+
if (d.error) {
|
| 1357 |
+
processingDone = true;
|
| 1358 |
+
document.getElementById('proc-label').innerText = 'Engine Error';
|
| 1359 |
+
const badge = document.getElementById('results-status-badge');
|
| 1360 |
+
if (badge) {
|
| 1361 |
+
badge.innerText = 'Failed';
|
| 1362 |
+
badge.className = 'px-2.5 py-1 bg-red-900/40 text-red-300 text-[10px] font-bold rounded-full uppercase tracking-tighter';
|
| 1363 |
+
}
|
| 1364 |
+
console.error('[UrbanFlow] Engine error:', d.detail || d.error);
|
| 1365 |
+
document.getElementById('run-results-content').innerHTML = `
|
| 1366 |
+
<div class="flex flex-col items-center justify-center p-8 border-2 border-dashed border-red-900/40 rounded-2xl col-span-3 text-slate-400">
|
| 1367 |
+
<i class="fa-solid fa-triangle-exclamation text-2xl mb-3 text-red-400"></i>
|
| 1368 |
+
<span class="text-xs font-semibold mb-1">Inference pipeline failed.</span>
|
| 1369 |
+
<span class="text-[10px] text-slate-500 mb-4 text-center max-w-xs">${d.error}</span>
|
| 1370 |
+
<button onclick="startNewAnalysis()" class="text-[10px] font-bold uppercase tracking-widest px-4 py-2 rounded-full" style="background:#111;border:1px solid #2a2a2a;color:#c89a6c">
|
| 1371 |
+
← Start New Analysis
|
| 1372 |
+
</button>
|
| 1373 |
+
</div>`;
|
| 1374 |
+
return;
|
| 1375 |
+
}
|
| 1376 |
+
|
| 1377 |
if (d.done) {
|
| 1378 |
processingDone = true;
|
| 1379 |
document.getElementById('proc-label').innerText = 'Complete';
|