1
0
Fork 0
mirror of https://github.com/maziggy/bambuddy.git synced 2026-05-09 08:25:54 +02:00

[PR #617] [CLOSED] Add camera grid streaming with multiplexed MJPEG, print controls, and UX improvements #1090

Closed
opened 2026-05-07 00:15:57 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/maziggy/bambuddy/pull/617
Author: @aneopsy
Created: 3/5/2026
Status: Closed

Base: 0.2.3b1Head: printers-camera-grid


📝 Commits (10+)

  • c6b8983 feat(camera): shared stream hub, canvas grid viewer, multiplexed streaming, and bandwidth optimization
  • 8cb98a9 feat(camera): add pause, resume, and stop controls to camera cardsEnhances camera grid with print controls
  • 12aa11e feat(camera-grid): worker decoding, IntersectionObserver, reconnect, quality switching, and UX improvements
  • 0b652b3 feat(camera-grid): HMS error notifications, ETA tooltip, control loading states, and backend hardening
  • a937260 feat(camera-grid): i18n, auth, process cleanup, input validation, and ref leak fixes
  • b9299a1 feat(camera-grid): fix producer race condition, add auth headers, and i18n fixes
  • 51f7da2 feat(camera-grid): fix sort bug, reconnect UI, frame validation, and stream cleanup
  • 9c78902 feat(camera-grid): encapsulate hub access, input validation, auth, and timer leak fixes
  • 94539ee fix(printers): AMS tray ID consistency, timer leak, localStorage safety, and modal ordering
  • 01efd08 fix(security): harden camera endpoints - RTSP sanitization, credential leak, Query bounds, SSRF

📊 Changes

60 files changed (+9340 additions, -2029 deletions)

View changed files

📝 backend/app/api/routes/auth.py (+21 -1)
📝 backend/app/api/routes/camera.py (+1842 -282)
📝 backend/app/api/routes/printers.py (+6 -0)
📝 backend/app/api/routes/settings.py (+31 -2)
📝 backend/app/api/routes/websocket.py (+40 -2)
📝 backend/app/core/database.py (+1 -1)
📝 backend/app/main.py (+45 -16)
📝 backend/app/schemas/printer.py (+27 -3)
📝 backend/app/schemas/settings.py (+10 -0)
📝 backend/app/services/camera.py (+319 -27)
📝 backend/app/services/external_camera.py (+252 -171)
📝 backend/app/services/timelapse_processor.py (+19 -11)
📝 backend/tests/integration/test_auth_api.py (+65 -1)
📝 backend/tests/integration/test_camera_api.py (+154 -26)
📝 backend/tests/integration/test_settings_api.py (+98 -0)
📝 backend/tests/unit/services/mock_ftp_server.py (+8 -1)
backend/tests/unit/services/test_camera_service.py (+498 -0)
📝 backend/tests/unit/services/test_external_camera.py (+19 -24)
backend/tests/unit/services/test_sanitize_camera_url.py (+146 -0)
backend/tests/unit/test_camera_grid.py (+1001 -0)

...and 40 more files

📄 Description

Description

Adds a real-time camera grid view to the Printers page — a single multiplexed MJPEG stream serves frames for all visible printers, decoded in a Web Worker and rendered on canvas. Includes inline print controls (pause/resume/stop), HMS error notifications, quality switching, and comprehensive backend stream management with shared producers and automatic cleanup.

Frontend:

image image

Backend optimisation - CPU usage for camera stream:

Before:
image

After:
image

Type of Change

  • New feature (non-breaking change that adds functionality)

Changes Made

Backend (backend/app/api/routes/camera.py)

  • Shared stream hub (_StreamHub) — single producer per camera, multiple consumers
  • Multiplexed /camera/grid-stream endpoint with binary-framed multi-printer MJPEG
  • Print control endpoints (pause, resume, stop) on camera cards
  • Periodic cleanup of stale frame buffers and orphaned ffmpeg processes
  • RTSP semaphore to limit concurrent ffmpeg spawns
  • Race condition fix in _ensure_producer for concurrent client requests

Frontend (frontend/src/pages/PrintersPage.tsx)

  • CameraGrid component with canvas-based rendering and dynamic layout
  • Web Worker (cameraGridDecoder.worker.ts) for off-main-thread frame decoding
  • IntersectionObserver to pause/resume streams for off-screen cards
  • Reconnect logic with exponential backoff
  • Quality/scale/FPS switching controls
  • Inline pause, resume, stop print controls on camera cards
  • HMS error notification badges with modal details
  • ETA tooltip on progress display

i18n

  • Added camera grid translation keys to all 7 locale files
  • Italian nozzle info keys

Testing

  • I have tested this on my local machine
  • Backend: 1794/1795 tests pass (1 flaky unrelated FTP test)
  • Frontend: 1038/1038 tests pass
  • Ruff lint/format clean
  • TypeScript + ESLint clean

Checklist

  • My code follows the project's coding style
  • I have commented my code where necessary
  • My changes generate no new warnings
  • I have tested my changes thoroughly

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/maziggy/bambuddy/pull/617 **Author:** [@aneopsy](https://github.com/aneopsy) **Created:** 3/5/2026 **Status:** ❌ Closed **Base:** `0.2.3b1` ← **Head:** `printers-camera-grid` --- ### 📝 Commits (10+) - [`c6b8983`](https://github.com/maziggy/bambuddy/commit/c6b89834f221b1eb4451e53b5cf9c2fabbfaa0f4) feat(camera): shared stream hub, canvas grid viewer, multiplexed streaming, and bandwidth optimization - [`8cb98a9`](https://github.com/maziggy/bambuddy/commit/8cb98a9080905045da10ad89ab3270e4f434fc61) feat(camera): add pause, resume, and stop controls to camera cardsEnhances camera grid with print controls - [`12aa11e`](https://github.com/maziggy/bambuddy/commit/12aa11e47f781948a98373c17afca022a450cbc1) feat(camera-grid): worker decoding, IntersectionObserver, reconnect, quality switching, and UX improvements - [`0b652b3`](https://github.com/maziggy/bambuddy/commit/0b652b3dbce13c825145b61c61f725674b796680) feat(camera-grid): HMS error notifications, ETA tooltip, control loading states, and backend hardening - [`a937260`](https://github.com/maziggy/bambuddy/commit/a9372604be5aebbcde7720aa5b38f76b84e1ee9f) feat(camera-grid): i18n, auth, process cleanup, input validation, and ref leak fixes - [`b9299a1`](https://github.com/maziggy/bambuddy/commit/b9299a1d1ae280a33137eb4dcef2ed5d011aa6b2) feat(camera-grid): fix producer race condition, add auth headers, and i18n fixes - [`51f7da2`](https://github.com/maziggy/bambuddy/commit/51f7da245494d3594db61f197cefba895fa37802) feat(camera-grid): fix sort bug, reconnect UI, frame validation, and stream cleanup - [`9c78902`](https://github.com/maziggy/bambuddy/commit/9c78902fb2447e475dc61a3f3e5a1281c79abc74) feat(camera-grid): encapsulate hub access, input validation, auth, and timer leak fixes - [`94539ee`](https://github.com/maziggy/bambuddy/commit/94539ee39a27b80c5993be7fdaf57d268924a97b) fix(printers): AMS tray ID consistency, timer leak, localStorage safety, and modal ordering - [`01efd08`](https://github.com/maziggy/bambuddy/commit/01efd08995e44b75a0a1de46fbf826ef5feaef16) fix(security): harden camera endpoints - RTSP sanitization, credential leak, Query bounds, SSRF ### 📊 Changes **60 files changed** (+9340 additions, -2029 deletions) <details> <summary>View changed files</summary> 📝 `backend/app/api/routes/auth.py` (+21 -1) 📝 `backend/app/api/routes/camera.py` (+1842 -282) 📝 `backend/app/api/routes/printers.py` (+6 -0) 📝 `backend/app/api/routes/settings.py` (+31 -2) 📝 `backend/app/api/routes/websocket.py` (+40 -2) 📝 `backend/app/core/database.py` (+1 -1) 📝 `backend/app/main.py` (+45 -16) 📝 `backend/app/schemas/printer.py` (+27 -3) 📝 `backend/app/schemas/settings.py` (+10 -0) 📝 `backend/app/services/camera.py` (+319 -27) 📝 `backend/app/services/external_camera.py` (+252 -171) 📝 `backend/app/services/timelapse_processor.py` (+19 -11) 📝 `backend/tests/integration/test_auth_api.py` (+65 -1) 📝 `backend/tests/integration/test_camera_api.py` (+154 -26) 📝 `backend/tests/integration/test_settings_api.py` (+98 -0) 📝 `backend/tests/unit/services/mock_ftp_server.py` (+8 -1) ➕ `backend/tests/unit/services/test_camera_service.py` (+498 -0) 📝 `backend/tests/unit/services/test_external_camera.py` (+19 -24) ➕ `backend/tests/unit/services/test_sanitize_camera_url.py` (+146 -0) ➕ `backend/tests/unit/test_camera_grid.py` (+1001 -0) _...and 40 more files_ </details> ### 📄 Description ## Description Adds a real-time camera grid view to the Printers page — a single multiplexed MJPEG stream serves frames for all visible printers, decoded in a Web Worker and rendered on canvas. Includes inline print controls (pause/resume/stop), HMS error notifications, quality switching, and comprehensive backend stream management with shared producers and automatic cleanup. Frontend: <img width="3318" height="1898" alt="image" src="https://github.com/user-attachments/assets/7dd716ec-afac-4c21-8fc1-dbdd71f26d10" /> <img width="814" height="470" alt="image" src="https://github.com/user-attachments/assets/e35fc2b7-3d2d-43f0-856e-777638e7ada1" /> Backend optimisation - CPU usage for camera stream: Before: <img width="1264" height="73" alt="image" src="https://github.com/user-attachments/assets/85a46ff3-48d2-4f09-ac2f-acc34618ad95" /> After: <img width="1222" height="70" alt="image" src="https://github.com/user-attachments/assets/6015f35b-c3ab-446f-95b3-02746ec2808c" /> ## Type of Change - [x] New feature (non-breaking change that adds functionality) ## Changes Made **Backend (`backend/app/api/routes/camera.py`)** - Shared stream hub (`_StreamHub`) — single producer per camera, multiple consumers - Multiplexed `/camera/grid-stream` endpoint with binary-framed multi-printer MJPEG - Print control endpoints (pause, resume, stop) on camera cards - Periodic cleanup of stale frame buffers and orphaned ffmpeg processes - RTSP semaphore to limit concurrent ffmpeg spawns - Race condition fix in `_ensure_producer` for concurrent client requests **Frontend (`frontend/src/pages/PrintersPage.tsx`)** - `CameraGrid` component with canvas-based rendering and dynamic layout - Web Worker (`cameraGridDecoder.worker.ts`) for off-main-thread frame decoding - `IntersectionObserver` to pause/resume streams for off-screen cards - Reconnect logic with exponential backoff - Quality/scale/FPS switching controls - Inline pause, resume, stop print controls on camera cards - HMS error notification badges with modal details - ETA tooltip on progress display **i18n** - Added camera grid translation keys to all 7 locale files - Italian nozzle info keys ## Testing - [x] I have tested this on my local machine - [x] Backend: 1794/1795 tests pass (1 flaky unrelated FTP test) - [x] Frontend: 1038/1038 tests pass - [x] Ruff lint/format clean - [x] TypeScript + ESLint clean ## Checklist - [x] My code follows the project's coding style - [x] I have commented my code where necessary - [x] My changes generate no new warnings - [x] I have tested my changes thoroughly --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-07 00:15:57 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/bambuddy-maziggy-1#1090
No description provided.