Files
appRobotWebcam/doc/01_WebcamRoadmap.md
2026-06-03 21:26:44 +02:00

141 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AppRobotWebcam Roadmap
## Ziel
Sauberer, fokussierter Webcam-Service als Docker-Container. Kein Robot-Control, kein
ArUco nur zwei Verantwortlichkeiten:
1. **Live-Video** mit minimaler Latenz (WebRTC via go2rtc)
2. **Standbilder** auf Abruf via HTTP REST (`/api/snapshot/cam{n}`)
Das Homing-Projekt holt seine Standbilder über den Snapshot-Endpunkt keine weitere Kopplung.
---
## Architektur (final)
```
USB Kameras
go2rtc (Capture · H.264-Encode · WebRTC) ── intern, Port 1984 + UDP 8555
Node.js / Express ── öffentlich, Port 8444
├── / eigener Viewer (go2rtc <video-stream>-Component)
├── /api/ws WebRTC-Signaling → proxied zu go2rtc
├── /api/snapshot/* Standbilder → proxied zu go2rtc /api/frame.jpeg
└── /health
```
**Warum go2rtc statt eigenem FFmpeg-Stream:**
Erste Version (eigener Node-FFmpeg-MJPEG-Stream über WebSocket) hatte spürbare Latenz.
go2rtc ist ein spezialisierter Streaming-Server: WebRTC mit ~50150 ms, automatisches
Encoding, ICE-Negotiation, robuster Client mit Auto-Fallback (WebRTC→MSE→MJPEG).
**Warum Node davor (statt go2rtc direkt):**
- Ein einziger öffentlicher Port (8444); go2rtc-Admin bleibt unerreichbar
- Stabile Snapshot-Schnittstelle, entkoppelt von go2rtc-Interna
- Eigener, schlanker Viewer
**Stack-Entscheide:**
| Komponente | Wahl | Begründung |
|------------|------|------------|
| Streaming | go2rtc | WebRTC out-of-the-box, niedrige Latenz, internet-tauglich |
| Webserver | Node.js + Express | wartbar, user-präferiert |
| Proxy | http-proxy-middleware | reicht HTTP + WebSocket transparent durch |
| Live-Protokoll | WebRTC (Fallback MSE/MJPEG) | niedrigste Latenz, skaliert über Internet |
| Snapshot-API | HTTP GET → JPEG | einfachste Schnittstelle für Consumer |
| Container | docker-compose, `configs` inline | kein Dockerfile-File, Portainer-tauglich |
---
## Tasks
### Phase 1 Grundgerüst ✅
- [x] Projektstruktur, package.json, docker-compose mit inline-Config
- [x] Erste Version (Node-FFmpeg-MJPEG über WebSocket) verworfen wegen Latenz
### Phase 2 Umstieg auf go2rtc / WebRTC ✅
- [x] go2rtc als Streaming-Backend (Kamera-Capture + WebRTC)
- [x] go2rtc-Config in docker-compose eingebettet (`configs.content`)
- [x] Node als Reverse-Proxy (`/api/ws`, `/api/frame.jpeg`, Player-Scripts)
- [x] Eigener Viewer mit go2rtc `<video-stream>`-Component (Auto-Fallback)
- [x] Stabile Snapshot-API `/api/snapshot/cam{n}`
- [x] Auflösung fest 640×480 → Latenz „akzeptabel" (war vorher das Hauptproblem)
### Phase 3 Latenz final tunen ✅
- [x] Messvergleich WebRTC ⟷ MJPEG: **WebRTC ~130 ms, MJPEG ~200 ms** → WebRTC gewinnt
- [x] Entscheid: bei WebRTC bleiben (niedrigere Latenz + besser für Internet)
- [ ] Optional: Prüfen ob Kamera natives H.264 liefert (`v4l2-ctl --list-formats`) → kein Re-Encode
- [ ] Optional: Keyframe-Intervall / Encoder-Preset tunen wenn <100 ms gefordert
### Phase 4 Internet-Härtung (offen, vor Produktiv-Schaltung)
- [ ] **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 (13 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
- [ ] Resource Limits dokumentieren (`mem_limit`, `cpus`)
- [ ] JSON-Logging
- [ ] Snapshot-Metadaten / optionaler Webhook nach Snapshot
---
## Abgrenzung zu appRobotVideoControls
| Feature | appRobotVideoControls | appRobotWebcam |
|---------|-----------------------|----------------|
| Video-Streaming | eigener FFmpeg-MJPEG/WS | go2rtc / WebRTC |
| Snapshots | komplex (dual-pipe) | HTTP REST, einfach |
| Robot-Control (G-Code) | ✅ | ❌ anderes Projekt |
| ArUco / Homing | ✅ | ❌ anderes Projekt |
| Separates Dockerfile | ✅ (OpenCV-Build) | ❌ (inline in compose) |
---
## Ports
| Dienst | Port | Exponiert? |
|--------|------|-----------|
| Node Viewer + API + Signaling | TCP 8444 | ja (Firewall) |
| WebRTC Media | UDP 8555 | ja (Firewall) |
| go2rtc HTTP/Debug-UI | TCP 1984 | nein (nur intern/LAN) |
---
## Datei-Struktur
```
appRobotWebcam/
├── src/
│ └── snapshotService.js Snapshot-Router (proxied go2rtc /api/frame.jpeg)
├── public/
│ ├── index.html Viewer (lädt go2rtc <video-stream>)
│ └── viewer.js baut Kamera-Views, Auto-Fallback WebRTC→MSE→MJPEG
├── doc/
│ ├── 01_WebcamRoadmap.md (diese Datei)
│ ├── 03_Protocoll_roadmap.md WebRTC⟷MJPEG-Vergleich (nachzuholen)
│ └── 05_OptionalToDo_roadmap.md Control-Integration (Optionen)
├── docker-compose.yaml einzige Deploy-Datei (go2rtc-Config eingebettet)
├── go2rtc.yaml nur Referenz/lokal (Config ist in compose eingebettet)
├── package.json
└── server.js Node-Einstiegspunkt
```