Skip to content

Commit 57554cc

Browse files
committed
Plan on-demand Storebaelt live webcam mode
1 parent 860cfa4 commit 57554cc

2 files changed

Lines changed: 275 additions & 0 deletions

File tree

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# Storebaelt On-Demand Live Webcam Enhancement Plan
2+
3+
**Date:** 2026-06-03
4+
**Scope:** Demand-driven live/HLS enhancement for the Storebaelt webcam publisher and Explorer UI.
5+
**Related background:** `Storebaelt_Webcam_Poster_Integration_Status_and_UX_Options_2026-06-03.md`
6+
7+
## Goal
8+
9+
Improve the Storebaelt webcam user experience without permanently running heavier live-video ingestion.
10+
11+
The baseline publisher should remain cheap and reliable: it continues publishing poster-image freshness/status observations at the normal cadence. A live/HLS mode should activate only when a client explicitly requests it, remain active only while that client renews a short lease, and shut itself off automatically when no users are watching.
12+
13+
## Design Principle
14+
15+
Use a **lease with TTL**.
16+
17+
A client does not permanently enable live processing. Instead, it requests a short-lived live session for one camera. While the client is actively displaying the webcam, it renews the lease. If renewals stop, the live worker expires the lease and stops HLS work for that camera.
18+
19+
Example lease state:
20+
21+
```text
22+
cameraId -> liveUntil
23+
```
24+
25+
Runtime behavior:
26+
27+
- `now < liveUntil`: live capture is active for that camera.
28+
- `now >= liveUntil`: live capture is stopped for that camera.
29+
- new lease request: extend `liveUntil`.
30+
31+
## Recommended Architecture
32+
33+
### Existing service
34+
35+
`storebaelt-webcams-publisher.service`
36+
37+
Responsibilities:
38+
39+
- poll poster JPEG endpoints every 5 minutes
40+
- compute image hashes
41+
- publish poster/status/freshness observations
42+
- remain the durable, low-cost baseline publisher
43+
44+
### New companion service
45+
46+
`storebaelt-webcams-live.service`
47+
48+
Responsibilities:
49+
50+
- expose a small live-session control surface
51+
- maintain in-memory leases per camera
52+
- activate HLS discovery/frame capture only for leased cameras
53+
- publish live status/frame-reference observations while active
54+
- stop per-camera work when leases expire
55+
56+
The live service can run continuously with near-zero work while idle, or later be made socket-activated if operational simplicity permits.
57+
58+
## Activation Interface Options
59+
60+
### Option A: Small publisher-side HTTP API
61+
62+
Initial pragmatic interface:
63+
64+
```http
65+
POST /live/storebaelt/{cameraId}/lease
66+
Content-Type: application/json
67+
68+
{ "ttlSeconds": 60, "mode": "latestFrame" }
69+
```
70+
71+
Response:
72+
73+
```json
74+
{
75+
"cameraId": "storebaelt-tower",
76+
"liveUntil": "2026-06-03T21:10:00Z",
77+
"active": true,
78+
"mode": "latestFrame",
79+
"status": "starting"
80+
}
81+
```
82+
83+
Additional endpoints:
84+
85+
- `GET /live/storebaelt/{cameraId}/status`
86+
- `DELETE /live/storebaelt/{cameraId}/lease` as an optional explicit stop signal
87+
88+
This is the fastest and clearest first implementation.
89+
90+
### Option B: CSAPI control stream
91+
92+
Longer-term, model live activation as a CSAPI control stream such as `requestLiveWebcam`.
93+
94+
Command fields:
95+
96+
- `cameraId`
97+
- `ttlSeconds`
98+
- `mode`: `latestFrame`, `frameEveryNSeconds`, or `playlistMetadata`
99+
- optional `quality`
100+
101+
This is more standards-aligned, but it depends on Explorer and server control-stream maturity. It should be treated as a follow-on migration path after the small HTTP control surface proves the workflow.
102+
103+
### Option C: Direct client HLS playback after discovery
104+
105+
The live service discovers/validates the HLS URL and returns it to Explorer, but the browser plays the stream directly.
106+
107+
This can provide the most live-feeling experience, but it depends on CORS, token behavior, and player compatibility. It is useful to evaluate, but should not be the only plan.
108+
109+
## Live Output Options
110+
111+
### Preferred first output: live status plus frame-reference observations
112+
113+
While a lease is active, the live service should publish a lightweight observation containing:
114+
115+
- `cameraId`
116+
- `liveActive`
117+
- `liveMode`
118+
- `leaseUntil`
119+
- `hlsPlaylistUrl` when safely shareable
120+
- `frameUrl` or `latestFrameUrl` when available
121+
- `frameTime`
122+
- `frameSha256` if a frame is fetched/generated
123+
- `sourceLatencySeconds` when derivable
124+
- `status`: `starting`, `live`, `stale`, `error`, or `idle`
125+
- `errorMessage` only when needed and safe to expose
126+
127+
This keeps Explorer aligned with the existing observation-driven UI model.
128+
129+
### Alternative output: transient frame cache
130+
131+
If generated frame images are needed, the live service can write latest frames to a short-lived local/cache path and publish a URL to that frame.
132+
133+
This avoids storing image bytes in CSAPI observations, but requires an image-serving path and cache cleanup policy.
134+
135+
## Explorer UX Plan
136+
137+
Add webcam-specific controls to the deployed-system card:
138+
139+
1. Always show poster status:
140+
- latest poster image
141+
- last checked time
142+
- image changed time
143+
- unchanged duration
144+
- stale badge when threshold is exceeded
145+
146+
2. Add a `Start Live` control:
147+
- visible for Storebaelt webcam deployments
148+
- starts a 60 second lease for the selected camera
149+
- changes to `Live` or `Starting` status while active
150+
151+
3. Renew the lease while the user is actively viewing:
152+
- renew every 30 seconds for a 60 second TTL
153+
- stop renewing when the card is closed, route changes, or tab visibility is lost for a configured grace period
154+
155+
4. Show live fallback links:
156+
- embedded player URL
157+
- public Storebaelt webcam page
158+
159+
5. Fail gracefully:
160+
- if live activation fails, keep poster image visible
161+
- show a compact `Live unavailable` state with the player link
162+
163+
## Publisher Runtime Behavior
164+
165+
The live service should be polite and bounded:
166+
167+
- one worker task per active camera
168+
- max TTL accepted per lease, for example 120 seconds
169+
- default TTL 60 seconds
170+
- minimum renewal interval enforced server-side
171+
- stop HLS fetch/decode immediately after idle timeout
172+
- do not fetch HLS for cameras without active leases
173+
- avoid publishing unchanged live frames unless publishing heartbeat/status is intentional
174+
175+
Recommended default live cadence while active:
176+
177+
- status heartbeat every 5-10 seconds
178+
- frame extraction every 5-15 seconds, depending on observed source behavior and CPU cost
179+
180+
## Data Model Additions
181+
182+
Create a separate live/status datastream per Storebaelt camera, or extend the existing webcam image datastream only if the result schema remains clear.
183+
184+
Preferred: separate output name such as `storebaeltWebcamLiveStatus`.
185+
186+
Candidate result fields:
187+
188+
- `cameraId`
189+
- `cameraTitle`
190+
- `liveActive`
191+
- `liveMode`
192+
- `leaseUntil`
193+
- `status`
194+
- `hlsPlaylistUrl`
195+
- `frameUrl`
196+
- `latestFrameUrl`
197+
- `frameTime`
198+
- `frameSha256`
199+
- `sourceLatencySeconds`
200+
- `playerUrl`
201+
- `pageUrl`
202+
- `errorMessage`
203+
204+
Keep poster-source fields in the existing `storebaeltWebcamImage` output so long-term poster freshness remains easy to understand.
205+
206+
## Implementation Phases
207+
208+
### Phase 1: Poster freshness heartbeat
209+
210+
- Publish heartbeat/status observations every 5 minutes, even when the poster image hash is unchanged.
211+
- Add fields such as `imageChanged`, `firstSeenTime`, `lastChangedTime`, `lastSeenTime`, `unchangedPollCount`, and `stalenessStatus`.
212+
- Update Explorer to separate `last checked` from `image changed`.
213+
214+
### Phase 2: Live source reconnaissance
215+
216+
- Inspect the Mediathand/Video.js player network behavior.
217+
- Identify whether HLS playlist URLs are stable, tokenized, or browser-bound.
218+
- Determine whether browser direct playback is viable.
219+
- Measure bandwidth, latency, and cache behavior.
220+
221+
### Phase 3: Live lease service prototype
222+
223+
- Add `storebaelt_webcams_live_service.py` or equivalent companion module.
224+
- Implement lease API and per-camera lease table.
225+
- Add bounded background worker activation per camera.
226+
- Publish live status observations with no frame extraction first.
227+
228+
### Phase 4: Frame or playlist integration
229+
230+
- Add HLS playlist discovery and validation.
231+
- Choose either direct playlist handoff, latest-frame extraction, or transient frame cache.
232+
- Publish live status/frame-reference observations only while leases are active.
233+
234+
### Phase 5: Explorer live UX
235+
236+
- Add `Start Live` and live status states to Storebaelt webcam cards.
237+
- Renew leases while the card is open.
238+
- Stop renewing when the user leaves the card.
239+
- Render live frame/playlist when available, otherwise fall back to poster image and external player links.
240+
241+
### Phase 6: Operational hardening
242+
243+
- Add systemd unit for the live service.
244+
- Add rate limits and max active leases.
245+
- Add logs/metrics for active lease count, source errors, and frame extraction failures.
246+
- Add cleanup for transient frames if used.
247+
248+
## Risks and Mitigations
249+
250+
| Risk | Mitigation |
251+
| --- | --- |
252+
| HLS URLs are tokenized or unstable | Discover per lease; cache only briefly; retain external player fallback. |
253+
| CORS blocks direct browser playback | Use server-side frame extraction or transient frame cache. |
254+
| Live extraction is CPU/bandwidth heavy | Activate only under lease; cap concurrent cameras and frame cadence. |
255+
| Source terms discourage heavy polling | Keep poster mode as default; use low live cadence; only fetch while user-requested. |
256+
| Latest observation time is confused with frame capture time | Store poll/check time and frame/image change time separately. |
257+
| Explorer leaves leases active after navigation | TTL expiration is authoritative; client stop signal is only an optimization. |
258+
259+
## Acceptance Criteria
260+
261+
- With no active Explorer webcam views, no HLS playlist or segment fetches occur.
262+
- Opening a Storebaelt webcam card and selecting live mode activates only that camera.
263+
- Closing the card or stopping renewals deactivates the camera after the TTL.
264+
- Poster image and freshness status remain available even when live mode fails.
265+
- The UI clearly distinguishes last checked time, image/frame changed time, and live activation state.
266+
- Oracle service logs show bounded, understandable live activation and idle behavior.
267+
268+
## Recommendation
269+
270+
Proceed with Phase 1 first, because it fixes the current stale-image confusion regardless of HLS viability. Then prototype the lease service with live status only before adding frame extraction. This keeps the design honest, observable, and reversible while preserving a path to a much better webcam experience.

docs/research/new-publisher-source-planning/Storebaelt_Webcam_Poster_Integration_Status_and_UX_Options_2026-06-03.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
**Date:** 2026-06-03
44
**Scope:** Storebaelt public traffic/weather webcam publisher behavior, image freshness semantics, and UI/UX optimization options.
55

6+
**Follow-on plan:** `Storebaelt_On_Demand_Live_Webcam_Enhancement_Plan_2026-06-03.md` describes the recommended lease-based design for demand-driven live/HLS mode.
7+
68
## Current Integration Behavior
79

810
The Storebaelt integration is intentionally conservative: it publishes references to the two stable poster JPEG URLs, not frames pulled from the HLS live video stream.
@@ -100,6 +102,8 @@ Tradeoffs:
100102

101103
This should be treated as a second-phase enhancement, not the default first fix.
102104

105+
If implemented, live/HLS ingestion should be demand-driven. The publisher should not continuously pull live video while no client is viewing the resource. The recommended pattern is a short-lived lease with TTL: Explorer requests live mode for a specific camera, renews the lease while the webcam card is open, and lets the live worker deactivate automatically when renewals stop. See `Storebaelt_On_Demand_Live_Webcam_Enhancement_Plan_2026-06-03.md` for the detailed plan.
106+
103107
### 5. Improve Explorer UI for Webcam Deployments
104108

105109
For Storebaelt webcam deployments, the Explorer card should show:
@@ -124,5 +128,6 @@ Recommended implementation order:
124128
4. Update Explorer's deployed-system card to display "last checked" separately from "image changed."
125129
5. Add a stale badge when the same image has persisted longer than a threshold.
126130
6. Research HLS extraction only after the poster-source UX is truthful and useful.
131+
7. For live/HLS mode, follow the lease-based on-demand plan so heavier capture work activates only when a client requests it and shuts down when not in use.
127132

128133
This gives a better user experience without prematurely building a fragile video ingestion pipeline.

0 commit comments

Comments
 (0)