WebCam als schlanke alternative zum appVideoControl
This commit is contained in:
85
server.js
Normal file
85
server.js
Normal file
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
const { WebSocketServer } = require('ws');
|
||||
const path = require('path');
|
||||
const { detectDevices } = require('./src/deviceDetect');
|
||||
const { VideoStream } = require('./src/videoStream');
|
||||
const { createSnapshotRouter } = require('./src/snapshotService');
|
||||
|
||||
const PORT = parseInt(process.env.PORT ?? '8080', 10);
|
||||
|
||||
function buildStreams() {
|
||||
const devices = detectDevices();
|
||||
console.log(`Detected ${devices.length} camera(s):`, devices);
|
||||
|
||||
return devices.map((device, idx) => new VideoStream(device, {
|
||||
name: `cam${idx}`,
|
||||
width: parseInt(process.env[`CAM${idx}_WIDTH`] ?? '640', 10),
|
||||
height: parseInt(process.env[`CAM${idx}_HEIGHT`] ?? '480', 10),
|
||||
fps: parseInt(process.env[`CAM${idx}_FPS`] ?? '30', 10),
|
||||
quality: parseInt(process.env[`CAM${idx}_QUALITY`] ?? '5', 10),
|
||||
}));
|
||||
}
|
||||
|
||||
function main() {
|
||||
const streams = buildStreams();
|
||||
|
||||
// Start all streams eagerly – first client gets immediate frame
|
||||
streams.forEach(s => s.start());
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
app.use('/api/snapshot', createSnapshotRouter(streams));
|
||||
|
||||
app.get('/health', (_req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
cameras: streams.map((s, i) => ({
|
||||
id: `cam${i}`,
|
||||
device: s.device,
|
||||
running: s.isRunning,
|
||||
clients: s.clientCount,
|
||||
hasFrame: s.latestFrame !== null,
|
||||
})),
|
||||
});
|
||||
});
|
||||
|
||||
const server = http.createServer(app);
|
||||
const wss = new WebSocketServer({ noServer: true });
|
||||
|
||||
server.on('upgrade', (req, socket, head) => {
|
||||
const match = req.url?.match(/^\/ws\/cam(\d+)$/);
|
||||
if (!match) { socket.destroy(); return; }
|
||||
|
||||
const idx = parseInt(match[1], 10);
|
||||
if (!streams[idx]) { socket.destroy(); return; }
|
||||
|
||||
wss.handleUpgrade(req, socket, head, (ws) => {
|
||||
const stream = streams[idx];
|
||||
stream.addClient(ws);
|
||||
ws.on('close', () => stream.removeClient(ws));
|
||||
ws.on('error', () => stream.removeClient(ws));
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`AppRobotWebcam on http://0.0.0.0:${PORT}`);
|
||||
streams.forEach((s, i) => {
|
||||
console.log(` ws://0.0.0.0:${PORT}/ws/cam${i} → ${s.device}`);
|
||||
console.log(` http://0.0.0.0:${PORT}/api/snapshot/cam${i}`);
|
||||
});
|
||||
});
|
||||
|
||||
const shutdown = (signal) => {
|
||||
console.log(`\n${signal} received – shutting down`);
|
||||
streams.forEach(s => s.stop());
|
||||
server.close(() => process.exit(0));
|
||||
};
|
||||
process.on('SIGINT', () => shutdown('SIGINT'));
|
||||
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user