Spaces:
Sleeping
Sleeping
| import json | |
| import base64 | |
| import cv2 | |
| import numpy as np | |
| import asyncio | |
| from fastapi import WebSocket, WebSocketDisconnect | |
| from services.vision import process_frame_synchronous | |
| from services.attendance import mark_attendance | |
| from core.state import active_connections | |
| async def websocket_endpoint(websocket: WebSocket): | |
| """ | |
| Hard-Locked WebSocket Connection with Visual Debugging. | |
| Returns crops and bounding boxes alongside the Truth Report. | |
| """ | |
| await websocket.accept() | |
| active_connections.append(websocket) | |
| try: | |
| while True: | |
| data = await websocket.receive_text() | |
| payload = json.loads(data) | |
| if payload.get("type") == "heartbeat": | |
| await websocket.send_json({"type": "heartbeat_ack"}) | |
| continue | |
| if payload.get("type") == "frame": | |
| encoded_data = payload["image"].split(',')[1] | |
| nparr = np.frombuffer(base64.b64decode(encoded_data), np.uint8) | |
| frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR) | |
| report, stats = await asyncio.to_thread(process_frame_synchronous, frame) | |
| results_summary = [] | |
| # Prepare visual data for frontend | |
| client_faces = [] | |
| for face in report: | |
| name = face["name"] | |
| score = face["score"] | |
| status = face["status"] | |
| # Store data for drawing boxes and showing crops | |
| client_faces.append({ | |
| "name": name, | |
| "score": score, | |
| "status": status, | |
| "box": face["box"], | |
| "crop": face["crop_b64"] | |
| }) | |
| if status == "match": | |
| # Business Logic: Mark Attendance | |
| status_db, time_str = mark_attendance(name) | |
| results_summary.append(f"✅ {name} ({score}%)") | |
| # Push to session attendance list | |
| await websocket.send_json({ | |
| "type": "attendance", | |
| "name": name, | |
| "time": time_str or "Just Now", | |
| "status": "success" | |
| }) | |
| else: | |
| results_summary.append(f"❌ {name} ({score}%)") | |
| # Detailed Terminal Output | |
| debug_msg = f"Faces: {stats['detected']} | " | |
| debug_msg += " | ".join(results_summary) if results_summary else "No faces found." | |
| # Send frame processing result back to browser | |
| await websocket.send_json({ | |
| "type": "ready", | |
| "debug": debug_msg, | |
| "faces": client_faces # ALL visual debug data included here | |
| }) | |
| except WebSocketDisconnect: | |
| if websocket in active_connections: | |
| active_connections.remove(websocket) | |