From f618fdac4283598280a9b90707189bc498c82181 Mon Sep 17 00:00:00 2001 From: chk <79915315+ChKendel@users.noreply.github.com> Date: Wed, 3 Jun 2026 21:07:46 +0200 Subject: [PATCH] Claude: Fix --- doc/01_WebcamRoadmap.md | 24 +++++++---- public/viewer.js | 93 +++++++++++++++++++---------------------- server.js | 55 +++++++++++++----------- 3 files changed, 90 insertions(+), 82 deletions(-) diff --git a/doc/01_WebcamRoadmap.md b/doc/01_WebcamRoadmap.md index ea5a983..a61d288 100644 --- a/doc/01_WebcamRoadmap.md +++ b/doc/01_WebcamRoadmap.md @@ -72,13 +72,23 @@ Encoding, ICE-Negotiation, robuster Client mit Auto-Fallback (WebRTC→MSE→MJP - [ ] Prüfen ob Kamera natives H.264 liefert (`v4l2-ctl --list-formats`) → kein Re-Encode ### Phase 4 – Internet-Härtung (offen, vor Produktiv-Schaltung) -- [ ] **TLS**: Reverse Proxy (Caddy/nginx/traefik) mit HTTPS vor Port 8444 - (WebRTC im Browser läuft über Internet zuverlässig nur im secure context) -- [ ] **WebRTC-Candidate**: `stun:8555` testen; falls NAT-Probleme → feste public IP/Domain - in der go2rtc-Config eintragen (`candidates: [robot.example.com:8555]`) -- [ ] **TURN**: nur falls reines STUN + Port-Forward UDP 8555 nicht reicht → coturn -- [ ] **Zugriffsschutz**: Basic-Auth oder Token am Reverse Proxy (1–3 bekannte User) -- [ ] **Firewall**: TCP 8444 + UDP 8555 forwarden; Port 1984 NICHT exponieren +- [ ] **TLS via Caddy** – empfohlen, weil Caddy WebSocket-Proxy nativ und zuverlässig kann. + Aktuell verbindet Browser `/api/ws` direkt zu go2rtc Port 1984. + Caddy bündelt beides hinter einer Domain: + ``` + robot.example.com { + handle /api/ws* { reverse_proxy localhost:1984 } + handle /api/stream* { reverse_proxy localhost:1984 } + handle /video-*.js { reverse_proxy localhost:1984 } + handle { reverse_proxy localhost:8444 } + } + ``` + Danach: viewer.js `go2rtcPort` auf 443 (wss://) setzen, Node GO2RTC_PORT=443. +- [ ] **WebRTC-Candidate**: `stun:8555` testen; bei NAT-Problemen → feste IP/Domain: + `candidates: [robot.example.com:8555]` in go2rtc-Config +- [ ] **TURN**: nur wenn STUN + UDP 8555 nicht reicht (sehr restriktive NATs) +- [ ] **Zugriffsschutz**: Basic-Auth am Caddy (1–3 bekannte User) +- [ ] **Firewall**: TCP 443 (Caddy) + UDP 8555 (WebRTC) forwarden; 1984 + 8444 intern ### Phase 5 – Robustheit (optional) - [ ] Kamera hot-plug: go2rtc-Verhalten bei Device-Verlust prüfen diff --git a/public/viewer.js b/public/viewer.js index ea43023..ddc3e73 100644 --- a/public/viewer.js +++ b/public/viewer.js @@ -1,38 +1,37 @@ 'use strict'; // go2rtc Player-Modi – Fallback-Reihenfolge: WebRTC → MSE → MJPEG -// Schlägt WebRTC fehl, springt der go2rtc-Player automatisch weiter → kein schwarzes Bild. const MODE = 'webrtc,mse,mjpeg'; -// ── Logging-Hilfe (sichtbar in Browser DevTools → Console) ────────────────── -const LOG_PREFIX = '[AppRobotWebcam]'; -function log(cam, msg) { console.log(`${LOG_PREFIX}[${cam}] ${msg}`); } -function warn(cam, msg) { console.warn(`${LOG_PREFIX}[${cam}] ⚠ ${msg}`); } -function logErr(cam, msg, e) { console.error(`${LOG_PREFIX}[${cam}] ✗ ${msg}`, e ?? ''); } +// ── Logging (sichtbar in Browser DevTools → Console → F12) ────────────────── +const P = '[WebcamViewer]'; +const log = (c, m) => console.log(`${P}[${c}] ${m}`); +const warn = (c, m) => console.warn(`${P}[${c}] ⚠ ${m}`); +const err = (c, m, e) => console.error(`${P}[${c}] ✗ ${m}`, e ?? ''); // ── Kamera-View aufbauen ───────────────────────────────────────────────────── -function buildCamera(camId, container) { - const wsUrl = `/api/ws?src=${encodeURIComponent(camId)}`; - log(camId, `View erstellt mode=${MODE} ws=${wsUrl}`); +function buildCamera(camId, go2rtcPort, container) { + // WebSocket direkt zu go2rtc – kein Proxy-Zwischenschritt, garantiert stabil. + // Protokoll: ws:// auf LAN (http). Für Internet mit TLS wird aus ws: wss: (Caddy). + const wsUrl = `ws://${location.hostname}:${go2rtcPort}/api/ws?src=${encodeURIComponent(camId)}`; + log(camId, `View erstellt mode="${MODE}" ws=${wsUrl}`); const box = document.createElement('div'); box.className = 'cam-box'; - // go2rtc Web-Component: verbindet sich via WebSocket zu /api/ws (→ Node-Proxy → go2rtc) const stream = document.createElement('video-stream'); stream.mode = MODE; - // Events vom inneren