go2rtc and several IP cameras still emit a warm-up / black frame on every
fresh MJPEG connection — even with the v0.2.4b2 warm-up-skip fix it
slipped through intermittently for @nkm8's setup. His own bisect named
the clean solution: go2rtc exposes /api/frame.jpeg as a dedicated
single-frame endpoint that never returns the encoder's stale keyframe.
Adds an optional external_camera_snapshot_url column on printers. When
set, every single-frame capture path (snapshot endpoint, [SNAPSHOT]
notification thumbnails, [PHOTO-BG] finish photo, layer timelapse,
Obico ML, plate-detect / calibrate-plate) routes through _capture_snapshot
on the override URL via plain HTTP GET, bypassing the warm-up dance.
Live view stays on the configured stream URL — only single-frame
captures use the override. Override is camera-type-agnostic. SSRF guard
applies (existing _sanitize_camera_url allowlist). Empty string treated
as unset.
Settings UI: new "Snapshot URL (optional)" input + Test button under
External Cameras, hidden for camera_type=snapshot since the live URL is
already a single-frame source. en + de fully translated; 6 other locales
seeded with English copy.
5 backend tests pin the routing contract; 3 frontend tests pin the
input + debounced PATCH. Documented in
bambuddy-wiki/docs/features/camera.md with the go2rtc example.
Add support for external network cameras (MJPEG, RTSP, HTTP snapshot)
that replace a printer's built-in camera when configured.
Features:
- Live streaming on printers page (replaces built-in camera)
- Finish photo capture from external camera on print complete
- Layer-based timelapse: captures frame on each layer change,
stitches to MP4 video on print completion
Backend changes:
- Add external_camera_url, external_camera_type, external_camera_enabled
fields to Printer model with database migration
- New external_camera.py service: MJPEG/RTSP/snapshot frame capture,
connection testing, MJPEG stream generation
- New layer_timelapse.py service: TimelapseSession management,
layer-by-layer frame capture, ffmpeg video stitching
- Add on_layer_change callback to MQTT client and printer manager
- Update camera routes with external camera streaming and tracking
- Update print lifecycle hooks for timelapse start/stitch/cancel
- Add external camera fields to backup/restore
- Rate limiting for external camera streams (prevents browser freeze)
Frontend changes:
- Add external camera configuration UI in Settings > Camera
- Per-printer enable toggle, URL input, type selector, test button
- Toast notification on save
Closes#143