The overlay can now be rendered either way at runtime:
- baked (default): server decodes the JPEG, draws the overlay, re-encodes,
publishes to the broadcaster and ffmpeg. Works with OctoPrint, VLC, and
any RTSP consumer. Same behavior as before.
- html: server skips decode/draw/encode entirely. The browser draws the
stats as positioned HTML over the raw stream. No video-side overlay,
so /stream/overlay and /snapshot/overlay return 503 and the RTSP
overlay process is stopped while in html mode. The user's RTSP overlay
preference is preserved and restored when switching back to baked.
Pipeline:
- overlayBaked atomic.Bool, default true
- SetOverlayBaked(bool) clears the broadcaster and stops the RTSP overlay
process when switching to html; restarts it when switching to baked if
the master toggle and user preference are both on
- runOverlay() skips the decode/draw/encode when not (enabled AND baked)
- pipelineState gains overlay_baked field, default true on load so
existing installs keep their current behavior
Web:
- /api/overlay GET returns {"enabled", "type"}; POST accepts either or
both fields (omitted fields are left unchanged)
- gateOverlay middleware also 503s when the overlay is in html mode
- /overlay full-screen page in html mode serves /stream/raw and renders
the same HTML overlay markup as the index card
UI:
- Second toggle next to "Overlay feed" — Baked vs HTML
- Overlay card has a stream-frame wrapper so the HTML overlay can
absolute-position on top of the image
- New .html-overlay CSS with state pill, filename, hotend/bed temps,
progress bar, elapsed/ETA — matches the baked overlay's information
but rendered crisp in the browser
- HTML overlay updates from the existing /api/stats poll loop
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>