Add configurable FPS to test preview and fix composite stream release race

- Add FPS control (1-60, default 20) to test preview modal next to LED count
- Server accepts fps query param, controls frame send interval
- Single Apply icon button (✓) applies both LED count and FPS
- FPS control stays visible for picture sources (LED count hidden)
- Fix composite sub-stream consumer ID collision: use unique instance ID
  to prevent old WebSocket release from killing new connection's streams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 02:04:09 +03:00
parent e912019873
commit 561229a7fe
9 changed files with 78 additions and 28 deletions

View File

@@ -682,6 +682,7 @@ async def test_color_strip_ws(
source_id: str,
token: str = Query(""),
led_count: int = Query(100),
fps: int = Query(20),
):
"""WebSocket for real-time CSS source preview. Auth via ``?token=<api_key>``.
@@ -723,8 +724,12 @@ async def test_color_strip_ws(
if hasattr(stream, "configure"):
stream.configure(max(1, led_count))
# Clamp FPS to sane range
fps = max(1, min(60, fps))
_frame_interval = 1.0 / fps
await websocket.accept()
logger.info(f"CSS test WebSocket connected for {source_id}")
logger.info(f"CSS test WebSocket connected for {source_id} (fps={fps})")
try:
from wled_controller.core.processing.composite_stream import CompositeColorStripStream
@@ -846,7 +851,7 @@ async def test_color_strip_ws(
except Exception as e:
logger.warning(f"JPEG frame preview error: {e}")
await asyncio.sleep(0.05)
await asyncio.sleep(_frame_interval)
except WebSocketDisconnect:
pass
except Exception as e: