Refactor capture engine architecture, rename PictureStream to PictureSource, and split API modules
- Separate CaptureEngine into stateless factory + stateful CaptureStream session - Add LiveStream/LiveStreamManager for shared capture with reference counting - Rename PictureStream to PictureSource across storage, API, and UI - Remove legacy migration logic and unused compatibility code - Split monolithic routes.py (1935 lines) into 5 focused route modules - Split schemas.py (480 lines) into 7 schema modules with re-exports - Extract dependency injection into dedicated dependencies.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
80
server/src/wled_controller/api/schemas/picture_sources.py
Normal file
80
server/src/wled_controller/api/schemas/picture_sources.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""Picture source schemas."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PictureSourceCreate(BaseModel):
|
||||
"""Request to create a picture source."""
|
||||
|
||||
name: str = Field(description="Stream name", min_length=1, max_length=100)
|
||||
stream_type: Literal["raw", "processed", "static_image"] = Field(description="Stream type")
|
||||
display_index: Optional[int] = Field(None, description="Display index (raw streams)", ge=0)
|
||||
capture_template_id: Optional[str] = Field(None, description="Capture template ID (raw streams)")
|
||||
target_fps: Optional[int] = Field(None, description="Target FPS (raw streams)", ge=10, le=90)
|
||||
source_stream_id: Optional[str] = Field(None, description="Source stream ID (processed streams)")
|
||||
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID (processed streams)")
|
||||
image_source: Optional[str] = Field(None, description="Image URL or file path (static_image streams)")
|
||||
description: Optional[str] = Field(None, description="Stream description", max_length=500)
|
||||
|
||||
|
||||
class PictureSourceUpdate(BaseModel):
|
||||
"""Request to update a picture source."""
|
||||
|
||||
name: Optional[str] = Field(None, description="Stream name", min_length=1, max_length=100)
|
||||
display_index: Optional[int] = Field(None, description="Display index (raw streams)", ge=0)
|
||||
capture_template_id: Optional[str] = Field(None, description="Capture template ID (raw streams)")
|
||||
target_fps: Optional[int] = Field(None, description="Target FPS (raw streams)", ge=10, le=90)
|
||||
source_stream_id: Optional[str] = Field(None, description="Source stream ID (processed streams)")
|
||||
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID (processed streams)")
|
||||
image_source: Optional[str] = Field(None, description="Image URL or file path (static_image streams)")
|
||||
description: Optional[str] = Field(None, description="Stream description", max_length=500)
|
||||
|
||||
|
||||
class PictureSourceResponse(BaseModel):
|
||||
"""Picture source information response."""
|
||||
|
||||
id: str = Field(description="Stream ID")
|
||||
name: str = Field(description="Stream name")
|
||||
stream_type: str = Field(description="Stream type (raw, processed, or static_image)")
|
||||
display_index: Optional[int] = Field(None, description="Display index")
|
||||
capture_template_id: Optional[str] = Field(None, description="Capture template ID")
|
||||
target_fps: Optional[int] = Field(None, description="Target FPS")
|
||||
source_stream_id: Optional[str] = Field(None, description="Source stream ID")
|
||||
postprocessing_template_id: Optional[str] = Field(None, description="Postprocessing template ID")
|
||||
image_source: Optional[str] = Field(None, description="Image URL or file path")
|
||||
created_at: datetime = Field(description="Creation timestamp")
|
||||
updated_at: datetime = Field(description="Last update timestamp")
|
||||
description: Optional[str] = Field(None, description="Stream description")
|
||||
|
||||
|
||||
class PictureSourceListResponse(BaseModel):
|
||||
"""List of picture sources response."""
|
||||
|
||||
streams: List[PictureSourceResponse] = Field(description="List of picture sources")
|
||||
count: int = Field(description="Number of streams")
|
||||
|
||||
|
||||
class PictureSourceTestRequest(BaseModel):
|
||||
"""Request to test a picture source."""
|
||||
|
||||
capture_duration: float = Field(default=5.0, ge=1.0, le=30.0, description="Duration to capture in seconds")
|
||||
border_width: int = Field(default=10, ge=1, le=100, description="Border width in pixels for preview")
|
||||
|
||||
|
||||
class ImageValidateRequest(BaseModel):
|
||||
"""Request to validate an image source (URL or file path)."""
|
||||
|
||||
image_source: str = Field(description="Image URL or local file path")
|
||||
|
||||
|
||||
class ImageValidateResponse(BaseModel):
|
||||
"""Response from image validation."""
|
||||
|
||||
valid: bool = Field(description="Whether the image source is accessible and valid")
|
||||
width: Optional[int] = Field(None, description="Image width in pixels")
|
||||
height: Optional[int] = Field(None, description="Image height in pixels")
|
||||
preview: Optional[str] = Field(None, description="Base64-encoded JPEG thumbnail")
|
||||
error: Optional[str] = Field(None, description="Error message if invalid")
|
||||
Reference in New Issue
Block a user