Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0 0.3895610272884369 0.6932320594787598 0.1280086189508438 0.1627638041973114
0 0.16703420877456665 0.5642731785774231 0.09341136366128922 0.15167592465877533
0 0.9560484290122986 0.9221291542053223 0.08790302276611328 0.15574170649051666
0 0.13916879892349243 0.811154842376709 0.07705847173929214 0.1463843435049057
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0 0.29829591512680054 0.6446008682250977 0.12156656384468079 0.15267311036586761
0 0.49192899465560913 0.745903730392456 0.1493932455778122 0.18510030210018158
0 0.7323252558708191 0.8575846552848816 0.1644657701253891 0.20728585124015808
0 0.43945321440696716 0.26821741461753845 0.08059863746166229 0.10975001007318497
0 0.14751005172729492 0.5243874788284302 0.07802576571702957 0.1305433213710785
0 0.9607410430908203 0.9214945435523987 0.07851791381835938 0.15701085329055786
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
207 changes: 207 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type": "module",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
Expand All @@ -15,7 +16,9 @@
"cors": "^2.8.5",
"dotenv": "^17.2.3",
"express": "^5.2.1",
"multer": "^2.0.2",
"prisma": "^6.19.0",
"uuid": "^13.0.0",
"ws": "^8.18.3"
}
}
53 changes: 33 additions & 20 deletions backend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { PrismaClient } from "@prisma/client";
import clientRoutes from "./routes/client.js";
import projectRoutes from "./routes/projects.js";
import cameraRoutes from "./routes/cameras.js";
import streamRoutes from "./routes/streams.js";
import annotationRoutes from "./routes/annotation.js";
import path from "path";
import { fileURLToPath } from "url";

// EXPRESS + PRISMA SETUP
const prisma = new PrismaClient();
Expand All @@ -17,6 +21,18 @@ app.use(express.json());
app.use("/clients", clientRoutes);
app.use("/projects", projectRoutes);
app.use("/cameras", cameraRoutes);
app.use("/streams", streamRoutes);
app.use("/api/annotation", annotationRoutes);

// SERVE STATIC FILES
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const BACKEND_ROOT = path.join(__dirname, "../");

// Serve uploads so frontend can view them
app.use("/uploads", express.static(path.join(BACKEND_ROOT, "uploads")));
// Serve results
app.use("/results", express.static(path.join(BACKEND_ROOT, "current_annotation_output")));

app.get("/", (req, res) => {
res.json({ message: "Backend running" });
Expand All @@ -39,31 +55,28 @@ wss.on("connection", (ws) => {
console.log("Client connected to WebSocket");

ws.on("message", (msg) => {
const text = msg.toString();

// Check if message is valid base64 JPEG (Python frame)
const isPythonFrame =
text.length > 1000 && // base64 frame is large
(text.startsWith("/") || text.startsWith("iVB") || text.startsWith("/9j"));

if (!isPythonFrame) {
console.log("Ignoring non-frame message");
return;
}

console.log("Broadcasting frame:", text.length);

// Broadcast only Python frames to all React clients
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(text);
try {
const parsed = JSON.parse(msg);

// If it has streamId, it's a frame from Python
if (parsed.streamId && parsed.image) {
// Broadcast to all clients (Let frontend filter by streamId)
// Optimization: Could filter by client subscription if we implemented that
const broadcastMsg = JSON.stringify(parsed);
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(broadcastMsg);
}
});
}
});
} catch (e) {
console.log("Received non-JSON message or invalid format");
}
});
});


// =================================
// START EXPRESS API SERVER
// =================================
app.listen(3000, () => console.log("Server running on port 3000"));
app.listen(5000, () => console.log("Server running on port 5000"));
Loading
Loading