149 lines
5.9 KiB
Python
149 lines
5.9 KiB
Python
"""
|
|
Video API Request/Response Schemas.
|
|
|
|
Pydantic models for API serialization and validation.
|
|
"""
|
|
|
|
from typing import List, Optional, Tuple
|
|
from datetime import datetime
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class VideoMetadataResponse(BaseModel):
|
|
"""Video metadata response model"""
|
|
duration_seconds: float = Field(..., description="Video duration in seconds")
|
|
width: int = Field(..., description="Video width in pixels")
|
|
height: int = Field(..., description="Video height in pixels")
|
|
fps: float = Field(..., description="Video frame rate")
|
|
codec: str = Field(..., description="Video codec")
|
|
bitrate: Optional[int] = Field(None, description="Video bitrate in bps")
|
|
aspect_ratio: float = Field(..., description="Video aspect ratio")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"duration_seconds": 120.5,
|
|
"width": 1920,
|
|
"height": 1080,
|
|
"fps": 30.0,
|
|
"codec": "XVID",
|
|
"bitrate": 5000000,
|
|
"aspect_ratio": 1.777
|
|
}
|
|
}
|
|
|
|
|
|
class VideoInfoResponse(BaseModel):
|
|
"""Video file information response"""
|
|
file_id: str = Field(..., description="Unique file identifier")
|
|
camera_name: str = Field(..., description="Camera that recorded the video")
|
|
filename: str = Field(..., description="Original filename")
|
|
file_size_bytes: int = Field(..., description="File size in bytes")
|
|
format: str = Field(..., description="Video format (avi, mp4, webm)")
|
|
status: str = Field(..., description="Video status")
|
|
created_at: datetime = Field(..., description="Creation timestamp")
|
|
start_time: Optional[datetime] = Field(None, description="Recording start time")
|
|
end_time: Optional[datetime] = Field(None, description="Recording end time")
|
|
machine_trigger: Optional[str] = Field(None, description="Machine that triggered recording")
|
|
metadata: Optional[VideoMetadataResponse] = Field(None, description="Video metadata")
|
|
is_streamable: bool = Field(..., description="Whether video can be streamed")
|
|
needs_conversion: bool = Field(..., description="Whether video needs format conversion")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"file_id": "camera1_recording_20250804_143022.avi",
|
|
"camera_name": "camera1",
|
|
"filename": "camera1_recording_20250804_143022.avi",
|
|
"file_size_bytes": 52428800,
|
|
"format": "avi",
|
|
"status": "completed",
|
|
"created_at": "2025-08-04T14:30:22",
|
|
"start_time": "2025-08-04T14:30:22",
|
|
"end_time": "2025-08-04T14:32:22",
|
|
"machine_trigger": "vibratory_conveyor",
|
|
"is_streamable": True,
|
|
"needs_conversion": True
|
|
}
|
|
}
|
|
|
|
|
|
class VideoListResponse(BaseModel):
|
|
"""Video list response"""
|
|
videos: List[VideoInfoResponse] = Field(..., description="List of videos")
|
|
total_count: int = Field(..., description="Total number of matching videos (ignores pagination)")
|
|
page: Optional[int] = Field(None, description="Current page number (if using page/limit)")
|
|
total_pages: Optional[int] = Field(None, description="Total pages (if using page/limit)")
|
|
has_next: Optional[bool] = Field(None, description="Is there a next page?")
|
|
has_previous: Optional[bool] = Field(None, description="Is there a previous page?")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"videos": [],
|
|
"total_count": 0,
|
|
"page": 1,
|
|
"total_pages": 1,
|
|
"has_next": False,
|
|
"has_previous": False
|
|
}
|
|
}
|
|
|
|
|
|
class StreamingInfoResponse(BaseModel):
|
|
"""Streaming information response"""
|
|
file_id: str = Field(..., description="Video file ID")
|
|
file_size_bytes: int = Field(..., description="Total file size")
|
|
content_type: str = Field(..., description="MIME content type")
|
|
supports_range_requests: bool = Field(..., description="Whether range requests are supported")
|
|
chunk_size_bytes: int = Field(..., description="Recommended chunk size for streaming")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"file_id": "camera1_recording_20250804_143022.avi",
|
|
"file_size_bytes": 52428800,
|
|
"content_type": "video/x-msvideo",
|
|
"supports_range_requests": True,
|
|
"chunk_size_bytes": 262144
|
|
}
|
|
}
|
|
|
|
|
|
class VideoListRequest(BaseModel):
|
|
"""Video list request parameters"""
|
|
camera_name: Optional[str] = Field(None, description="Filter by camera name")
|
|
start_date: Optional[datetime] = Field(None, description="Filter by start date")
|
|
end_date: Optional[datetime] = Field(None, description="Filter by end date")
|
|
limit: Optional[int] = Field(50, description="Maximum number of results")
|
|
offset: Optional[int] = Field(0, description="Number of items to skip (for pagination)")
|
|
include_metadata: bool = Field(False, description="Include video metadata for returned items only")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"camera_name": "camera1",
|
|
"start_date": "2025-08-04T00:00:00",
|
|
"end_date": "2025-08-04T23:59:59",
|
|
"limit": 50,
|
|
"offset": 0,
|
|
"include_metadata": True
|
|
}
|
|
}
|
|
|
|
|
|
class ThumbnailRequest(BaseModel):
|
|
"""Thumbnail generation request"""
|
|
timestamp_seconds: float = Field(1.0, description="Timestamp to extract thumbnail from")
|
|
width: int = Field(320, description="Thumbnail width")
|
|
height: int = Field(240, description="Thumbnail height")
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"timestamp_seconds": 5.0,
|
|
"width": 320,
|
|
"height": 240
|
|
}
|
|
}
|