Draft compression
This commit is contained in:
248
doc/streamCompression.md
Normal file
248
doc/streamCompression.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# Stream-Komprimierung (MJPEG → H.264) — Abarbeitungsliste
|
||||
|
||||
> **Status (2026-06-16):** Der H.264-Pfad ist **im Code vollständig vorhanden und
|
||||
> unit-getestet**, aber **noch nie auf dem Host scharf geschaltet oder gemessen**.
|
||||
> Diese Datei ist die ausführbare ToDo-Liste, um ihn in Betrieb zu nehmen — destilliert
|
||||
> aus [14_ReRender_roadmap.md](14_ReRender_roadmap.md) (Hintergrund/Entwurf),
|
||||
> [02_HardwareEncoding.md](02_HardwareEncoding.md), [03_Protocoll_roadmap.md](03_Protocoll_roadmap.md)
|
||||
> und [04_Delay_roadmap.md](04_Delay_roadmap.md).
|
||||
>
|
||||
> **Es ist also kein „von Null bauen".** Die offene Arbeit ist: *scharf schalten → messen →
|
||||
> tunen → ausrollen* — und zwar **auf dem Host gemessen, nicht vorhergesagt**
|
||||
> (Memory-Regel; alle Zahlen unten ohne Messung sind ausdrücklich **Hypothesen**).
|
||||
|
||||
---
|
||||
|
||||
## Ausgangslage in einem Satz
|
||||
|
||||
Der Live-Stream geht heute als **MJPEG** raus (jedes Frame ein vollständiges JPEG). Das ist
|
||||
zwar pro Frame komprimiert, aber ohne Inter-Frame-Kompression → hohe Bitrate, und der Client
|
||||
muss jedes Frame einzeln dekodieren und in ein `<img>` schieben. Bei mehreren Kameras bringt
|
||||
das schwache Laptops an die Grenze. Mehr Kameras kommen → das Problem wächst.
|
||||
|
||||
## Warum H.264 dem Laptop hilft (Motivation + eine Korrektur)
|
||||
|
||||
„Unkomprimiert" trifft es nicht ganz — MJPEG **ist** komprimiert, nur eben **intra-frame**.
|
||||
Der Gewinn von H.264 ist trotzdem real und doppelt:
|
||||
|
||||
1. **Inter-Frame-Kompression** (nur Bildänderungen übertragen) → deutlich weniger Bitrate
|
||||
(Hypothese: ~2–5 MBit/s statt MJPEG-Bitrate; vor dem Umbau messen, siehe ToDo 0).
|
||||
2. **Hardware-Decode im Browser** — H.264 dekodiert der Client in der GPU; MJPEG dekodiert
|
||||
er pro Frame auf der CPU/im Main-Thread und tauscht das `<img>`. Genau **das** ist die
|
||||
Last, die mehrere Streams auf dem Laptop erzeugen. → H.264 entlastet primär den Client.
|
||||
|
||||
> ⚠️ **Realität prüfen, nicht annehmen:** Alle Kameras laufen aktuell auf `liveSize`
|
||||
> **320×240** ([../cameras.json](../cameras.json)). `1920x1080` dort ist die `hiresSize`
|
||||
> (Einzelbild beim HD-Knopf), **kein** Dauerstream. Bei 320×240 ist die MJPEG-Bitrate schon
|
||||
> klein → der Bandbreiten-Gewinn könnte gering sein, der **Client-Decode-Gewinn** aber
|
||||
> trotzdem zählen. Das entscheidet ToDo 0.
|
||||
|
||||
---
|
||||
|
||||
## Was bereits im Code steckt (Datei-Pointer)
|
||||
|
||||
| Baustein | Datei | Zustand |
|
||||
|---|---|---|
|
||||
| Encoder-Wahl (VAAPI/QSV/libx264) + MSE-Codec-String + FFmpeg-Args | [../src/hwencode.js](../src/hwencode.js) | ✅ + Unit-Test [../test/hwencode.test.js](../test/hwencode.test.js) |
|
||||
| fMP4-Box-Parser (Init-Segment + Fragmente) | [../src/fmp4Parser.js](../src/fmp4Parser.js) | ✅ + Unit-Test [../test/fmp4Parser.test.js](../test/fmp4Parser.test.js) |
|
||||
| `encode='h264'`-Zweig: Init-Cache, Fan-out, MJPEG-Nebenausgang (fd 3) für Snapshots | [../src/cameraSwitch.js](../src/cameraSwitch.js) | ✅ |
|
||||
| `video/mp4`-Route (Init-first Fan-out), `encode`/`mseCodec` in `/api/snapshot`+`/api/cameras` | [../src/snapshotService.js](../src/snapshotService.js) | ✅ |
|
||||
| MSE-`<video>`-Player + Feature-Detection + Snapshot-Fallback + Live-Edge-Tuning | [../public/viewer.js](../public/viewer.js) | ✅ |
|
||||
| Per-Kamera-Umschaltung „MJPEG / H.264 (GPU)" in der Config-UI | [../public/config.js](../public/config.js), [../src/configService.js](../src/configService.js) | ✅ |
|
||||
| `/dev/dri`-Passthrough, VA-Treiber-Install beim Start, `LIBVA_DRIVER_NAME=i965`, alle H264-Env | [../docker-compose.yaml](../docker-compose.yaml) | ✅ |
|
||||
| Verdrahtung (`resolveHwenc`, `H264`-Tuning, `mseCodec`) | [../server.js](../server.js) | ✅ |
|
||||
|
||||
**Transport-Entscheidung (steht):** MSE-fMP4, **nicht** WebRTC. WebRTC würde die bewusst
|
||||
entfernte go2rtc-/Signaling-Maschinerie zurückholen. MSE erhält „Node besitzt die Kameras"
|
||||
(Node → ffmpeg → Byte-Stream → Browser). Details: [14_ReRender_roadmap.md](14_ReRender_roadmap.md).
|
||||
|
||||
**Umschalten ist pro Kamera:** `encode` in [../cameras.json](../cameras.json) oder per UI
|
||||
(`config.html`). Default bleibt MJPEG → für den LAN-Fall ändert sich nichts.
|
||||
|
||||
---
|
||||
|
||||
## Eiserne Regeln (gelten weiter — aus [04](04_Delay_roadmap.md)/[09](09_Bug_reports.md))
|
||||
|
||||
1. **Der Live-Stream hat absolute Priorität.** Im Zweifel kein Feature statt wackliger Stream.
|
||||
2. **Auf dem Host messen, nicht vorhersagen.** Jede Bitrate/CPU/Latenz-Zahl ohne Messung ist Hypothese.
|
||||
3. **Eine USB-Kamera = ein Öffner.** Der `CameraSwitch` bleibt einziger Geräte-Öffner; nie ein zweiter FFmpeg parallel.
|
||||
4. **Config-Änderung + Rollback statt riskanter Laufzeit-Mutation.** Encode pro Kamera umschalten ist erlaubt, wenn die *andere* Kamera auf bekanntem gutem Stand bleibt und eine Rollback-Zeile existiert.
|
||||
5. **Smoke-Test mutiert `cameras.json`** ([Memory](../memory/MEMORY.md)) — `POST /api/config` überschreibt die Datei. Nicht gegen die echte Config testen, ohne sie vorher zu sichern.
|
||||
|
||||
---
|
||||
|
||||
## ToDo-Liste
|
||||
|
||||
Legende: ⬜ offen · 🧪 nur auf dem Host verifizierbar (echte Kamera + GPU). Reihenfolge ist
|
||||
bewusst: erst messen ob es sich lohnt, dann eine Kamera scharf schalten, dann tunen, dann ausrollen.
|
||||
|
||||
---
|
||||
|
||||
### Phase 0 — Lohnt es sich, und läuft die Basis?
|
||||
|
||||
#### ⬜ 0.1 🧪 Ist-Bandbreite & Client-Last des heutigen MJPEG-Streams messen
|
||||
**Aktion:** Auf dem Host die Bitrate eines Live-Streams bei realer `liveSize` (320×240) messen,
|
||||
bei 1 und bei n Clients; parallel die CPU-Last des empfangenden Laptops (Browser/OS-Taskmanager)
|
||||
bei 1, 2, 3 … Streams notieren.
|
||||
```bash
|
||||
# Bitrate grob: 10 s Stream ziehen, Bytes messen
|
||||
curl -s -o /dev/null -w '%{size_download} bytes in %{time_total}s\n' \
|
||||
--max-time 10 http://<host>:8444/api/stream/cam0
|
||||
# oder Netz-I/O des Containers:
|
||||
docker stats --no-stream AppRobotWebcam
|
||||
```
|
||||
**Risiken:** Ohne Zahl baut man eventuell viel um für wenig Gewinn (bei 320×240 evtl. marginal).
|
||||
Der Client-Last-Test ist der eigentliche Entscheider (das ist das Nutzer-Problem), nicht die Bitrate allein.
|
||||
**Test/Entscheidung:** Tabelle MJPEG vs. (später) H.264 — Bitrate **und** Laptop-CPU pro Stream.
|
||||
Lohnt sich nur, wenn die Client-CPU mit der Stream-Zahl klar hochläuft. **Gate:** nur weiter, wenn der Gewinn plausibel ist.
|
||||
|
||||
#### ⬜ 0.2 🧪 GPU/VAAPI im Container verifizieren (H.264-Encode überhaupt verfügbar?)
|
||||
**Aktion:** Bestätigen, dass der Container den VA-Treiber laden und H.264 encoden kann.
|
||||
```bash
|
||||
docker exec AppRobotWebcam vainfo # erwartet: VAProfileH264* mit VAEntrypointEncSlice
|
||||
docker exec AppRobotWebcam ls -l /dev/dri/ # renderD128 vorhanden?
|
||||
docker logs AppRobotWebcam 2>&1 | grep -i -E "VA-Treiber|vainfo|H.264-GPU"
|
||||
```
|
||||
**Risiken:**
|
||||
- VA-Treiber-Install beim Start schlägt **still** fehl (kein Netz/Paketquelle) → App läuft, aber H.264 ist tot (Compose loggt nur `WARN`).
|
||||
- `i965` vs `iHD`: UHD 630 ist mit `LIBVA_DRIVER_NAME=i965` verdrahtet ([../docker-compose.yaml](../docker-compose.yaml)). Andere/AMD-Box braucht `radeonsi` + `mesa-va-drivers`.
|
||||
- Auf Synology DSM existiert die `render`-Gruppe nicht (bewusst entfernt); Zugriff läuft über root. Auf der Ziel-Box (Lenovo i5/UHD 630) prüfen, ob das `video`-Group-Mapping + `/dev/dri` für den Node-User reicht.
|
||||
**Test:** `vainfo` listet H264-Encode-Entrypoint → grünes Licht. Sonst Treiber/Env fixen, **bevor** eine Kamera auf h264 geht.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1 — Eine Kamera scharf schalten
|
||||
|
||||
#### ⬜ 1.1 🧪 Genau eine Kamera auf `encode='h264'` und Bild im Browser prüfen
|
||||
**Aktion:** **Eine** Kamera umschalten — am sichersten über die Config-UI (`http://<host>:8444/config.html`
|
||||
→ Spalte Encode → „H.264 (GPU)" → speichern), die anderen auf MJPEG lassen. Alternativ `encode: "h264"`
|
||||
am Eintrag in [../cameras.json](../cameras.json) + Redeploy. Vorher `cameras.json` sichern (Regel 5).
|
||||
Erwartete Wirkung im Code: `reconfigure()` killt den Live-FFmpeg und startet ihn als H.264 neu (Hot-Reload);
|
||||
der Viewer baut für diese Kamera ein `<video>`+MSE statt `<img>`.
|
||||
**Risiken:**
|
||||
- **Schwarzes/leeres `<video>`**: MSE-Codec-String passt nicht zu dem, was FFmpeg liefert (Profil/Level). Stellschraube `H264_MSE_CODEC` / `H264_PROFILE` (siehe 2.2). Der Viewer fällt bei nicht unterstütztem Codec automatisch auf den Snapshot-Modus zurück (kein schwarzes Bild, aber auch kein Video).
|
||||
- **FFmpeg startet nicht** (`encode=h264 ohne hwenc-Konfig` oder VAAPI-Init-Fehler) → Auto-Restart-Schleife. Im Log sichtbar.
|
||||
- **Andere Kamera nicht anfassen** — Live-Priorität (Regel 1/4). Rollback = Encode der Test-Kamera zurück auf MJPEG.
|
||||
**Test:** Viewer zeigt flüssiges Live-Bild für die Test-Kamera; Statuszeile „H.264 · live".
|
||||
Codec im Log prüfen:
|
||||
```bash
|
||||
docker logs AppRobotWebcam 2>&1 | grep -i -E "live gestartet|h264_vaapi|encode=h264"
|
||||
```
|
||||
|
||||
#### ⬜ 1.2 🧪 Server-Last messen: encodet wirklich die GPU — und was kostet der MJPEG-Decode?
|
||||
**Aktion:** `docker stats` für die Test-Kamera im H.264-Modus vs. MJPEG-Modus vergleichen.
|
||||
**Wichtig (aus [14](14_ReRender_roadmap.md)):** Im h264-Modus muss FFmpeg das USB-**MJPEG erst dekodieren**
|
||||
(CPU), bevor die GPU H.264 encodet (`format=nv12,hwupload`). Im copybsf-Modus gibt es **gar keinen Decode**.
|
||||
H.264 kann also die Server-CPU **erhöhen**, obwohl die GPU encodet — das ist zu messen, nicht zu raten.
|
||||
```bash
|
||||
docker stats --no-stream AppRobotWebcam
|
||||
# optional, falls verfügbar, GPU-Auslastung:
|
||||
docker exec AppRobotWebcam sh -c 'command -v intel_gpu_top && intel_gpu_top -s 1000 || echo "kein intel_gpu_top"'
|
||||
```
|
||||
**Risiken:** „GPU-Encode = wenig CPU" ist eine **Hypothese**; der zusätzliche MJPEG-Decode kann sie kippen.
|
||||
Bei höheren `liveSize` steigt die Decode-Last überproportional.
|
||||
**Test:** CPU-Delta MJPEG↔H.264 dokumentieren; im FFmpeg-Log `h264_vaapi` bestätigen (nicht `libx264`).
|
||||
Fällt der Encoder heimlich auf `libx264` zurück → CPU explodiert → Treiber/`HWENC` prüfen.
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 — Latenz & Qualität tunen
|
||||
|
||||
#### ⬜ 2.1 🧪 Latenz H.264/MSE vs. MJPEG messen
|
||||
**Aktion:** Stoppuhr-Foto-Methode aus [03_Protocoll_roadmap.md](03_Protocoll_roadmap.md): Handy-Stoppuhr (ms)
|
||||
vor die Kamera, MJPEG- und H.264-Kamera nebeneinander, ein Foto von Monitor + Stoppuhr → Differenz ablesen.
|
||||
Referenz heute: MJPEG ~139 ms (Kamera→Browser).
|
||||
**Risiken:** MSE puffert (Init-Segment + Fragment-Dauer + Browser-Jitter-Buffer). Erwartung: H.264 hat **mehr**
|
||||
Latenz als der MJPEG-Schalter. Der Viewer hält die Latenz klein, indem er an die „Live-Kante" springt
|
||||
(`H264_MAX_LAG_S` in [../public/viewer.js](../public/viewer.js)) — aggressiver = niedrigere Latenz, mehr Ruckler-Risiko.
|
||||
**Test:** Gemessene ms in eine Tabelle MJPEG vs. H.264. Entscheiden, ob die Mehrlatenz für die
|
||||
Roboter-Überwachung vertretbar ist (bei reiner Überwachung meist ja).
|
||||
|
||||
#### ⬜ 2.2 🧪 Bitrate / GOP / Profil / Fragmentlänge nachjustieren
|
||||
**Aktion:** Über Env in [../docker-compose.yaml](../docker-compose.yaml) tunen (Defaults in [../server.js](../server.js)):
|
||||
|
||||
| Env | Default | Wirkung |
|
||||
|---|---|---|
|
||||
| `H264_BITRATE` | `3M` | Zielbitrate ↓ = weniger Bandbreite, mehr Artefakte |
|
||||
| `H264_GOP` | ~2×fps | Keyframe-Abstand; kleiner = schnellerer Einstieg/Reconnect, mehr Bitrate |
|
||||
| `H264_PROFILE` | `main` | `constrained_baseline`/`main`/`high` — muss zum Treiber **und** zum MSE-Codec passen |
|
||||
| `H264_FRAG_MS` | `200` | fMP4-Fragmentlänge; kleiner = niedrigere Latenz, mehr Overhead |
|
||||
| `H264_MSE_CODEC` | aus Profil/Level abgeleitet | nur setzen, wenn der Browser den abgeleiteten String ablehnt (z. B. `avc1.640020`) |
|
||||
|
||||
**Risiken:** Profil/Level (Server) und MSE-Codec-String (Browser) müssen zusammenpassen, sonst schwarzes
|
||||
Video / `addSourceBuffer`-Fehler → Snapshot-Fallback. Zu kleine GOP/Fragmente erhöhen Bitrate/CPU wieder.
|
||||
**Test:** Nach jeder Änderung Bild + Latenz + Bitrate gegenprüfen (ToDo 0.1/2.1 wiederholen). Eine Stellschraube pro Durchgang.
|
||||
|
||||
---
|
||||
|
||||
### Phase 3 — Snapshot & HD-Grab im H.264-Modus verifizieren
|
||||
|
||||
#### ⬜ 3.1 🧪 `/api/snapshot/:id` liefert weiter JPEG, während die Kamera H.264 streamt
|
||||
**Aktion:** Während die Test-Kamera live H.264 läuft, `GET /api/snapshot/<id>` abrufen.
|
||||
Hintergrund: Der h264-FFmpeg hat einen **MJPEG-Nebenausgang** (fd 3, gedrosselt auf `H264_JPEG_FPS=2`),
|
||||
der `latest` für Snapshots füllt ([../src/cameraSwitch.js](../src/cameraSwitch.js), [../src/hwencode.js](../src/hwencode.js)).
|
||||
**Wichtig fürs Homing-Projekt:** dessen Snapshot-Abruf muss unverändert weiterlaufen.
|
||||
**Risiken:** Snapshot ist nur ~2 fps frisch (Nebenausgang gedrosselt) — für ein Standbild ok, für „live"-Polling
|
||||
nicht. Der `split=2`-Filter kostet etwas zusätzlichen CPU (zweiter, billiger MJPEG-Encode).
|
||||
**Test:** `curl -o snap.jpg http://<host>:8444/api/snapshot/<id>` → valides JPEG in `liveSize`. Homing-Abruf gegenprüfen.
|
||||
|
||||
#### ⬜ 3.2 🧪 HD-Grab (`/hires`) im H.264-Modus: Blackout + sauberer Reconnect
|
||||
**Aktion:** HD-Knopf bzw. `GET /api/snapshot/<id>/hires` auf der H.264-Kamera auslösen.
|
||||
Ablauf im Code: `grabHires` killt den live-H.264-FFmpeg (`close` = FD frei) → greift HD-JPEG (`hiresEncode`
|
||||
fällt für h264 automatisch auf `copybsf` → reines Kamera-JPEG, keine H.264-Artefakte) → startet H.264 neu.
|
||||
Der Neustart erzeugt ein **neues Init-Segment** → die Route beendet bestehende MSE-Verbindungen (`onReinit`),
|
||||
der Browser verbindet automatisch neu.
|
||||
**Risiken:** Sichtbarer Blackout + MSE-Reconnect (~2–3 s) für Zuschauer dieser einen Kamera — wie der
|
||||
bekannte HD-Blackout, nur mit zusätzlichem Player-Neuaufbau. Reconnect-Logik (`onReinit` + Viewer-Retry)
|
||||
muss greifen, sonst bleibt das `<video>` stehen.
|
||||
**Test:** HD-Bild wird heruntergeladen (volle `hiresSize`, scharf, keine H.264-Artefakte); das `<video>`
|
||||
läuft nach dem Grab von selbst weiter. Andere Kameras unbeeinflusst.
|
||||
|
||||
---
|
||||
|
||||
### Phase 4 — Mehr Kameras / Rollout
|
||||
|
||||
#### ⬜ 4.1 🧪 Mehrere Kameras gleichzeitig auf H.264 — GPU- und USB-Kapazität
|
||||
**Aktion:** Schrittweise eine zweite, dann dritte Kamera auf H.264 schalten, jeweils CPU/GPU/Bild messen.
|
||||
**Risiken:** „Schwache OnBoard-Graphik" (UHD 630): Quick Sync schafft i. d. R. mehrere parallele H.264-Encodes,
|
||||
aber die **CPU-MJPEG-Decodes summieren sich** (jede h264-Kamera dekodiert ihr USB-MJPEG auf der CPU).
|
||||
USB-Bandbreite ist eine separate Grenze (siehe [07_multipleCam_roadmap.md](07_multipleCam_roadmap.md), `lsusb -t`).
|
||||
**Test:** Mit jeder zugeschalteten H.264-Kamera CPU/GPU + Bild prüfen. Die Zahl finden, ab der es kippt → dokumentieren.
|
||||
|
||||
#### ⬜ 4.2 🧪 Der eigentliche Beweis: Client-Last sinkt
|
||||
**Aktion:** Auf dem Ziel-Laptop denselben Mehr-Kamera-View einmal in MJPEG, einmal in H.264 öffnen und die
|
||||
Browser-/OS-CPU vergleichen (das war der Auslöser des ganzen Umbaus).
|
||||
**Risiken:** Wenn die Client-CPU **nicht** sinkt, lohnt der Server-Mehraufwand (Phase 1.2/4.1) nicht — dann
|
||||
neu abwägen (z. B. nur Bitrate senken statt H.264). Ältere Browser ohne MSE → Snapshot-Fallback (deutlich schlechter).
|
||||
**Test:** Laptop-CPU-Tabelle MJPEG vs. H.264 bei n Kameras. Erfolg = klar niedrigere Client-Last bei akzeptabler Latenz/Qualität.
|
||||
|
||||
#### ⬜ 4.3 Rollout-Strategie + Rollback festhalten
|
||||
**Aktion:** Festlegen, welche Kameras dauerhaft H.264 fahren (z. B. die mit Dauer-Zuschauern), welche MJPEG
|
||||
bleiben (LAN/niedrige Latenz). Default in [../cameras.json](../cameras.json) entsprechend setzen.
|
||||
**Risiken:** Inkonsistenz zwischen UI-Umschaltung (persistiert in `cameras.json`) und Env-Defaults; Verwechslung
|
||||
`encode` (Live) ↔ `hiresEncode` (Grab bleibt JPEG).
|
||||
**Test:** Nach Redeploy `GET /api/cameras` prüfen (`encode`/`mseCodec` pro Kamera korrekt). Rollback = `encode`
|
||||
zurück auf `copybsf` (UI oder Datei) — der MJPEG-Pfad ist unverändert und immer verfügbar.
|
||||
|
||||
---
|
||||
|
||||
### Phase 5 — Optional / später
|
||||
|
||||
- ⬜ **AMD-Box gegenprüfen**, falls sie Zielhardware wird: `GPU=amd`, `LIBVA_DRIVER_NAME=radeonsi`, `mesa-va-drivers` in der Compose-`command`-Zeile ergänzen, `vainfo` gegenprüfen.
|
||||
- ⬜ **MSE-Watchdog**: eingefrorenes `<video>` ohne Fehler-Event erkennen und neu verbinden (Analogon zum offenen MJPEG-Freeze-Watchdog in [09_Bug_reports.md](09_Bug_reports.md)).
|
||||
- ⬜ **Bitrate-Re-Messung nach Tuning** → endgültige Bandbreiten-Zahl für die Doku (ersetzt die Hypothesen oben).
|
||||
- ⬜ **`H264_JPEG_FPS` anheben**, falls das Homing-Projekt frischere Snapshots braucht (kostet etwas CPU).
|
||||
|
||||
---
|
||||
|
||||
## Schnell-Rollback (jederzeit)
|
||||
|
||||
1. **Eine Kamera:** Encode in `config.html` zurück auf „MJPEG" (oder `encode` aus dem `cameras.json`-Eintrag entfernen) → Hot-Reload, MJPEG-`<img>`-Pfad sofort zurück.
|
||||
2. **Komplett:** `cameras.json` aus der Sicherung zurückspielen + Redeploy. Der MJPEG-Schalter ist der unveränderte, bekannte gute Stand.
|
||||
3. **GPU/Treiber kaputt:** H.264 startet nicht → App läuft trotzdem auf MJPEG weiter (Compose-`command` bricht bei Treiberfehler nicht ab). Kein Live-Ausfall.
|
||||
|
||||
## Offene Entscheidungen (vor Phase 1 klären, falls relevant)
|
||||
|
||||
1. **Lohnt es sich** bei der realen `liveSize`? → Gate in ToDo 0.1/4.2 (Client-Last ist der Maßstab).
|
||||
2. **Zielhardware** wirklich die Lenovo-i5/UHD-630-Box (i965)? Falls AMD → Phase 5.
|
||||
3. **Welche `liveSize`** für H.264-Kameras? Höher als 320×240 wird mit H.264 erst sinnvoll/erschwinglich — gemeinsam mit 2.2 entscheiden.
|
||||
Reference in New Issue
Block a user