Claude: WebRTC Versuch

This commit is contained in:
chk
2026-06-02 23:10:13 +02:00
parent 9b1ae2ae14
commit 11811a2e03
7 changed files with 279 additions and 241 deletions

View File

@@ -2,46 +2,47 @@
const express = require('express');
// Returns an Express router mounted at /api/snapshot
// GET /api/snapshot → JSON listing of cameras
// GET /api/snapshot/cam0 latest JPEG from cam0
// GET /api/snapshot/cam1 → latest JPEG from cam1
function createSnapshotRouter(streams) {
// Proxiert go2rtc-Frame-API als /api/snapshot/:id
// GET /api/snapshot → JSON mit Kamera-Liste (von go2rtc /api/streams)
// GET /api/snapshot/cam0 → aktuelles JPEG-Frame (von go2rtc /api/frame?src=cam0)
function createSnapshotRouter(go2rtcUrl) {
const router = express.Router();
router.get('/', (_req, res) => {
res.json({
cameras: streams.map((s, i) => ({
id: `cam${i}`,
device: s.device,
running: s.isRunning,
clients: s.clientCount,
hasFrame: s.latestFrame !== null,
url: `/api/snapshot/cam${i}`,
})),
});
router.get('/', async (_req, res) => {
try {
const r = await fetch(`${go2rtcUrl}/api/streams`);
if (!r.ok) throw new Error(`go2rtc ${r.status}`);
const streams = await r.json();
res.json({
cameras: Object.keys(streams).map(id => ({
id,
url: `/api/snapshot/${id}`,
})),
});
} catch (err) {
res.status(503).json({ error: `go2rtc nicht erreichbar: ${err.message}` });
}
});
router.get('/:id', (req, res) => {
const idx = parseInt(req.params.id.replace('cam', ''), 10);
if (isNaN(idx) || !streams[idx]) {
return res.status(404).json({ error: 'camera not found' });
router.get('/:id', async (req, res) => {
const { id } = req.params;
try {
const upstream = await fetch(`${go2rtcUrl}/api/frame?src=${encodeURIComponent(id)}`);
if (!upstream.ok) {
return res.status(upstream.status).json({ error: 'kein Frame verfügbar' });
}
const buf = Buffer.from(await upstream.arrayBuffer());
res.set({
'Content-Type': 'image/jpeg',
'Content-Length': buf.length,
'Cache-Control': 'no-store',
'X-Camera-Id': id,
'X-Timestamp': new Date().toISOString(),
});
res.end(buf);
} catch (err) {
res.status(503).json({ error: `go2rtc: ${err.message}` });
}
const frame = streams[idx].latestFrame;
if (!frame) {
return res.status(503).json({ error: 'no frame available yet stream may still be starting' });
}
res.set({
'Content-Type': 'image/jpeg',
'Content-Length': frame.length,
'Cache-Control': 'no-store',
'X-Camera-Id': `cam${idx}`,
'X-Camera-Device': streams[idx].device,
'X-Timestamp': new Date().toISOString(),
});
res.end(frame);
});
return router;