diff options
| author | Luke Hoersten <[email protected]> | 2026-06-14 10:45:30 -0500 |
|---|---|---|
| committer | Luke Hoersten <[email protected]> | 2026-06-14 10:45:30 -0500 |
| commit | 334455c8ab793e2303e5e3669fa6deba179412be (patch) | |
| tree | 02b4511047e311705a182577c836183fa02f7a5f /README.md | |
| parent | 0a147e5942a9788cb0802f680d2c57a3da87efab (diff) | |
M9-precursor: v1 Scrypted Script (snapshot-rate end-to-end)
scrypted/scrypted-viewport.ts — single-file TypeScript script for
Scrypted's Scripts plugin. Binds N viewports to N Scrypted cameras and
implements the full Scrypted side of the protocol:
Outbound (Scrypted -> device):
- POST /config on script load + every 5 min (re-syncs after device
reboot or DHCP renumber).
- POST /state {wake} when a bound camera fires an event or when the
device's own POST /state {wake} arrives (operator tap).
- POST /frame at FRAME_INTERVAL_MS (1 fps default) via
camera.takePicture({picture:{width,height}}).
- POST /state {sleep} when the Scrypted-side per-stream timer
expires.
Inbound (device -> Scrypted POST <base>/state):
- {state:wake} -> startStream() (cancels pending sleep timer + any
prior interval, then begins pushing frames).
- {state:sleep} -> stopStream(sendSleep=false) (no echo back).
- Unknown viewport -> 404. Bad body -> 400.
Race rules from the spec are honored:
- Every callback cancels prior pending state for that viewport
before applying the new state (cancelPendingSleep semantics).
- startStream / stopStream are idempotent — re-entering is safe.
- On /frame returning 409, stream stops immediately without
echoing /state {sleep} back (the device already slept).
Configuration is a single BINDINGS array at the top of the file —
edit name/host/cameraId/orientation per viewport and save in the
Scrypted UI. No package install. Tuning constants
(IDLE_TIMEOUT_MS, FRAME_INTERVAL_MS, REREGISTER_INTERVAL_MS, etc.)
are right above the class.
scrypted/README.md walks through Scripts-plugin install, the BINDINGS
schema, what each constant controls, an event-by-event description of
the script's behavior, the v1 limitations (snapshot-rate, manual IP,
camera must respect picture dims), and an end-to-end smoke test.
Top-level README's Scrypted Integration section now links the script
file and the install README directly.
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -335,7 +335,7 @@ Both use a small embedded bitmap font. No LVGL, no general text engine. The Scrypted side is **code, not configuration** — Scrypted has no built-in concept of a network framebuffer. The code is small and lives inside Scrypted: -- **v1**: a Scrypted Script (in the Scripts plugin) — listens for camera events, calls `takePicture()`, POSTs the JPEG to `/frame`. Exposes a `POST /state` handler at the plugin's endpoint root (e.g. `http://scrypted.local:11080/endpoint/scrypted-viewport/state`) via the EndpointManager. ~50 lines of TypeScript, no package install. +- **v1** (in this repo at [`scrypted/scrypted-viewport.ts`](scrypted/scrypted-viewport.ts), install instructions in [`scrypted/README.md`](scrypted/README.md)): a Scrypted Script (in the Scripts plugin) — listens for camera events, calls `takePicture()`, POSTs the JPEG to `/frame`. Exposes a `POST /state` handler at the plugin's endpoint root (e.g. `http://scrypted.local:11080/endpoint/scrypted-viewport/state`) via the EndpointManager. ~250 lines of TypeScript, no package install. - **Next milestone after v1 (`/stream`)**: add `POST /stream` with `multipart/x-mixed-replace` chunked body for live frame rates. Scrypted side becomes a small custom plugin using FFmpeg via `MediaManager` to pipe MJPEG. `/frame` stays for snapshots and debug. Either way, no Scrypted core changes and no external service. |
