LowRes
This commit is contained in:
@@ -8,7 +8,8 @@
|
|||||||
"stream": true,
|
"stream": true,
|
||||||
"hires": true,
|
"hires": true,
|
||||||
"note": "usb-046d_0825_3BB3FE20-video-index0",
|
"note": "usb-046d_0825_3BB3FE20-video-index0",
|
||||||
"hiresSize": "1280x960"
|
"hiresSize": "1280x960",
|
||||||
|
"liveSize": "320x240"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cam1",
|
"id": "cam1",
|
||||||
@@ -18,7 +19,8 @@
|
|||||||
"stream": true,
|
"stream": true,
|
||||||
"hires": true,
|
"hires": true,
|
||||||
"note": "usb-046d_081b_342D4F40-video-index0",
|
"note": "usb-046d_081b_342D4F40-video-index0",
|
||||||
"hiresSize": "1280x960"
|
"hiresSize": "1280x960",
|
||||||
|
"liveSize": "320x240"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cam2",
|
"id": "cam2",
|
||||||
@@ -28,7 +30,8 @@
|
|||||||
"stream": true,
|
"stream": true,
|
||||||
"hires": true,
|
"hires": true,
|
||||||
"note": "usb-046d_HD_Pro_Webcam_C920_9C5591DF-video-index0",
|
"note": "usb-046d_HD_Pro_Webcam_C920_9C5591DF-video-index0",
|
||||||
"hiresSize": "1920x1080"
|
"hiresSize": "1920x1080",
|
||||||
|
"liveSize": "320x240"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
117
doc/12_cameraConfig_roadmap.md
Normal file
117
doc/12_cameraConfig_roadmap.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
## Roadmap – Dynamische Kamera-Konfiguration (config.html)
|
||||||
|
|
||||||
|
**Ziel:** Live-Auflösung pro Kamera zur Laufzeit umschalten, ohne Datei-Editor oder Container-Restart.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kontext
|
||||||
|
|
||||||
|
Alle drei Kameras (C270, C920, C922) unterstützen dieselben MJPEG-nativen Auflösungen:
|
||||||
|
|
||||||
|
| Auflösung | Pixel | Faktor ggü. 640×480 |
|
||||||
|
|-----------|-------|----------------------|
|
||||||
|
| 160×120 | 19'200 | −96% |
|
||||||
|
| 320×240 | 76'800 | −83% |
|
||||||
|
| 640×360 | 230'400 | −53% (16:9) |
|
||||||
|
| 640×480 | 307'200 | Referenz (aktuell) |
|
||||||
|
| 800×600 | 480'000 | +56% |
|
||||||
|
| 1280×720 | 921'600 | +200% |
|
||||||
|
|
||||||
|
Nur MJPEG-native Auflösungen verwenden – sonst fällt V4L2 auf YUYV (unkomprimiert) zurück
|
||||||
|
und FFmpeg muss software-encoden (~50% CPU pro Kamera).
|
||||||
|
|
||||||
|
**Priorität:** Latenz > CPU > Bildqualität. Bandbreite ist der Engpass beim Internet-Zugriff.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geplante UI: `/config.html`
|
||||||
|
|
||||||
|
Separate Admin-Seite (kein Viewer-Umbau nötig). Pro Kamera eine Zeile:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ Kamera-Konfiguration │
|
||||||
|
├──────────┬────────────┬──────────┬──────────────────┤
|
||||||
|
│ cam0 │ Kamera 0 │ [320×240 ▼] │ Live: 320×240│
|
||||||
|
│ cam1 │ Kamera 1 │ [640×360 ▼] │ Live: 640×360│
|
||||||
|
│ cam2 │ Kamera 2 │ [Aus ▼] │ Live: aus │
|
||||||
|
├──────────┴────────────┴──────────┴──────────────────┤
|
||||||
|
│ [Speichern & Neu starten] │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**ComboBox-Optionen pro Kamera:**
|
||||||
|
- `Aus` → Stream deaktivieren (`stream: false`)
|
||||||
|
- `160×120`
|
||||||
|
- `320×240`
|
||||||
|
- `640×360`
|
||||||
|
- `640×480` (aktuell Default)
|
||||||
|
- `800×600`
|
||||||
|
- `1280×720`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementierung
|
||||||
|
|
||||||
|
### Phase 1 – API-Endpunkt (server.js / neues Modul)
|
||||||
|
|
||||||
|
**GET `/api/config`** → liefert aktuelle Konfiguration aller Kameras:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cameras": [
|
||||||
|
{ "id": "cam0", "liveSize": "320x240", "stream": true },
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**POST `/api/config`** → nimmt neue Konfiguration entgegen:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cameras": [
|
||||||
|
{ "id": "cam0", "liveSize": "640x360", "stream": true },
|
||||||
|
{ "id": "cam1", "liveSize": "320x240", "stream": true },
|
||||||
|
{ "id": "cam2", "stream": false }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ablauf im Handler:
|
||||||
|
1. Validierung (nur erlaubte Auflösungen akzeptieren)
|
||||||
|
2. `cameras.json` aktualisieren
|
||||||
|
3. Pro geänderter Kamera: Live-FFmpeg stoppen (`_killCurrentAndWait`) + mit neuen Params neu starten (`_spawnLive`) – kein Container-Restart nötig
|
||||||
|
|
||||||
|
### Phase 2 – `config.html` (statische Seite in `/public`)
|
||||||
|
|
||||||
|
- Liest beim Laden `GET /api/config`
|
||||||
|
- Zeigt pro Kamera ein `<select>` mit den erlaubten Auflösungen
|
||||||
|
- `[Speichern]` → `POST /api/config` → Erfolgsmeldung
|
||||||
|
- Keine Authentifizierung (ist im internen Netz, wie der Viewer)
|
||||||
|
|
||||||
|
### Phase 3 – Hot-Reload in CameraSwitch
|
||||||
|
|
||||||
|
Neue Methode `reconfigure({ liveSize, stream })` in `CameraSwitch`:
|
||||||
|
- Wenn `stream: false` → `_killCurrentAndWait()`, kein Neustart
|
||||||
|
- Wenn `liveSize` geändert → `_killCurrentAndWait()` + `this.liveSize = newSize` + `_spawnLive()`
|
||||||
|
- Wenn nichts geändert → no-op
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Abgrenzung (nicht im Scope dieser Roadmap)
|
||||||
|
|
||||||
|
- MJPEG Re-Encode-Qualität (`-q:v`) → separates Thema, eigene Env-Variable
|
||||||
|
- `liveFps` per Kamera → triviale Erweiterung, analog zu `liveSize`
|
||||||
|
- Authentifizierung auf `/config.html` → wenn Internet-Zugang geplant
|
||||||
|
- `hiresSize` per Kamera (HD-Grab) → bereits in cameras.json, kein UI nötig
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Manueller Test (sofort möglich, ohne diese Roadmap)
|
||||||
|
|
||||||
|
`cameras.json` direkt bearbeiten und Container neu starten:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "id": "cam0", ..., "liveSize": "320x240" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Details: siehe unten im Gesprächsprotokoll / `09_Bug_reports.md`.
|
||||||
Reference in New Issue
Block a user