Files
ryan.mcgee 5c7b1482d6 Default overlay to enabled in HTML mode
Fresh installs now show the overlay over the live picture in the web
UI without any server-side overlay processing. Previously the overlay
defaulted to off entirely.

The change is just to loadState()'s default values; both fields are
still read from the state file when present, so existing users who
have explicitly toggled either setting keep their preference. Users
upgrading from before overlay_baked existed get the new HTML default
(was implicitly baked before).

Behavior with the new defaults on a fresh install:
- Master overlay: on
- Overlay type: HTML (baked off)
- runOverlay() drops frames without decoding (no CPU overhead)
- /stream/overlay and /snapshot/overlay return 503 (HTML mode)
- RTSP overlay process does not start
- Web UI shows stats overlaid via CSS on top of the raw stream

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 15:22:44 -05:00

6.7 KiB

OctoCam

Live webcam streaming for a 3D printer with OctoPrint stats burned into the overlay feed. Built with Go + MediaMTX. Runs on Raspberry Pi, Rock64, and any arm64/armv7 SBC.

Pages

URL Description
http://<host>:8080/ Both feeds side by side with stats and RTSP toggles
http://<host>:8080/raw Raw feed — bare full-screen (no UI chrome)
http://<host>:8080/overlay Overlay feed — bare full-screen (no UI chrome)

Streams

URL Description
http://<host>:8080/stream/raw Raw MJPEG HTTP (for direct embedding)
http://<host>:8080/stream/overlay Overlay MJPEG HTTP (for direct embedding)
http://<host>:8080/snapshot/raw Single JPEG snapshot of the raw feed
http://<host>:8080/snapshot/overlay Single JPEG snapshot of the overlay feed
rtsp://<host>:8554/raw Raw RTSP — use as OctoPrint webcam URL or open in VLC
rtsp://<host>:8554/overlay Overlay RTSP — OctoPrint webcam URL with stats

RTSP feeds can be toggled on/off at runtime from the web UI without restarting the service.

The raw HTTP stream and snapshot (/stream/raw, /snapshot/raw, and the mjpg_streamer-compatible /webcam/?action=stream and /webcam/?action=snapshot) are always available, regardless of any runtime toggle. They never carry the overlay. Point OctoPrint's Classic Webcam plugin at these URLs for reliable live feeds and snapshot capture.

The overlay feed is a separate master toggle (rendering, MJPEG, RTSP). It defaults to on in HTML mode, so a fresh install shows the stats over the live picture in the web UI without doing any server-side JPEG decode/draw/encode. The RTSP overlay sub-toggle is preserved across master toggles but the ffmpeg process only runs when the master is on and the overlay type is baked.

Overlay type can be switched at runtime between two modes:

  • HTML (default): the overlay is drawn client-side over the raw stream. No JPEG decode/draw/encode on the server. Web-only — /stream/overlay and /snapshot/overlay return 503 and the RTSP overlay process is stopped.
  • Baked: the overlay is rendered server-side and burned into the JPEG frames. Required for OctoPrint, VLC, or any consumer that expects the stats inside the video stream. Higher CPU cost.

All toggles — master overlay, overlay type, and both RTSP feed states — persist in the state file (/var/lib/octocam/feeds.json by default) and survive reboots.

Architecture

USB webcam ──→ octocam (Go)
                  │  ← OctoPrint API (temps, state, progress)
                  │
                  ├─ /stream/raw        MJPEG HTTP  ──→ browser
                  ├─ /stream/overlay    MJPEG HTTP  ──→ browser
                  ├─ /, /raw, /overlay  web pages
                  │
                  ├─ ffmpeg raw     -c:v copy (passthrough) ──→ MediaMTX /raw
                  └─ ffmpeg overlay H264 ultrafast @ 5fps   ──→ MediaMTX /overlay
                                                │
                                          RTSP :8554  ──→ VLC / OctoPrint

Browser streams are served directly as MJPEG HTTP — no WebRTC, no HLS, no extra encoding. The RTSP feeds via MediaMTX are for external tools and are optional (toggleable).

Quick Install

Build the binary on your dev machine first, then copy the repo to the target board and run the installer.

On your dev machine:

git clone https://git.enclaveis.com/Enclave-Information-Systems/octocam
cd octocam
make build-pi       # arm64 (Pi 4/5, Rock64, etc.)
# or: make build-pi32   # armv7 (32-bit OS)

On the board:

cp .env.example /etc/octocam.env
# Edit /etc/octocam.env — set OCTOPRINT_API_KEY and OCTOCAM_DEVICE
sudo bash deploy/install.sh
sudo systemctl start octocam

Open http://<board-ip>:8080/ in a browser.

Configuration

All settings are environment variables read from /etc/octocam.env (service) or .env (local dev). See .env.example for the full list. The only required variable is OCTOPRINT_API_KEY — get it from OctoPrint → Settings → API.

Key settings:

Variable Default Description
OCTOCAM_DEVICE /dev/video0 V4L2 camera device
OCTOCAM_WIDTH / OCTOCAM_HEIGHT 1280 / 720 Capture resolution
OCTOCAM_FPS 15 Camera framerate
OCTOCAM_OVERLAY_RTSP_FPS 5 RTSP overlay framerate (lower = less CPU)
OCTOCAM_FFMPEG_HW auto Encoder: auto, h264_v4l2m2m, h264_rkmpp, libx264
OCTOCAM_BASE_PATH (empty) URL prefix for hosting at a sub-path, e.g. /octocam
OCTOCAM_STATE_FILE /var/lib/octocam/feeds.json Persists RTSP feed state across reboots
OCTOPRINT_URL http://localhost:5000 OctoPrint base URL
OCTOPRINT_API_KEY Required

RTSP feeds default to off on first run. Enable them from the web UI — the state is saved immediately and survives reboots.

API

Method Path Description
GET /api/stats OctoPrint snapshot (temps, progress, state)
GET /api/feeds RTSP feed states {"raw":{"enabled":true,"running":true},...}
POST /api/feeds/raw Toggle raw RTSP — body {"enabled": false}
POST /api/feeds/overlay Toggle overlay RTSP — body {"enabled": true}
GET /api/overlay Overlay state {"enabled": false, "type": "baked"}
POST /api/overlay Set overlay state — body {"enabled": true} and/or {"type": "html"}
GET /snapshot/raw Single JPEG frame from the raw feed
GET /snapshot/overlay Single JPEG frame from the overlay feed (503 when master overlay off)
GET /healthz Health check — 200 ok or 503 degraded

Overlay

The overlay stream burns four regions onto each frame:

  • Top-left: Printer state pill (green Printing / yellow Paused / red Error) + filename
  • Top-right: H: actual/target °C and B: actual/target °C
  • Bottom: Progress bar + % elapsed H:MM:SS ETA H:MM:SS

When OctoPrint is unreachable the overlay shows a single red "OctoPrint unreachable" badge; the camera stream continues uninterrupted.

Development

# Build for the current machine
make build

# Cross-compile for arm64 boards
make build-pi

# Run locally (needs a USB webcam and MediaMTX running on localhost)
cp .env.example .env
# Edit .env — set OCTOPRINT_API_KEY
OCTOPRINT_API_KEY=xxx ./octocam

Run MediaMTX locally for dev:

# Linux amd64
curl -fsSL https://github.com/bluenviron/mediamtx/releases/latest/download/mediamtx_linux_amd64.tar.gz | tar xz
./mediamtx deploy/mediamtx.yml