Some checks failed
CI / skip-ci-check (pull_request) Successful in 1m4s
CI / lint-and-type-check (pull_request) Has been cancelled
CI / python-lint (pull_request) Has been cancelled
CI / test-backend (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / secret-scanning (pull_request) Has been cancelled
CI / dependency-scan (pull_request) Has been cancelled
CI / sast-scan (pull_request) Has been cancelled
CI / workflow-summary (pull_request) Has been cancelled
Add on-demand H.264/AAC web playback (RQ, ffmpeg) with API routes and Next.js proxies; extend admin UI with WebPlaybackVideo and shared hooks. Store transcode cache beside pending-photos (WEB_VIDEO_CACHE_DIR / UPLOAD_DIR) and ignore data/web_videos. Centralize FastAPI URL helpers, optional Vite and Next base paths for subfolder deploy, and fix modal reopen by using router.replace when closing the home photo viewer. Include migration, install scripts, deployment doc updates, and CI admin build env tweak. Made-with: Cursor
111 lines
2.3 KiB
Python
111 lines
2.3 KiB
Python
"""Video schemas for person identification."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date, datetime
|
|
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class PersonInfo(BaseModel):
|
|
"""Person information for video listings."""
|
|
|
|
id: int
|
|
first_name: str
|
|
last_name: str
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
|
|
|
|
class VideoListItem(BaseModel):
|
|
"""Video item in list response."""
|
|
|
|
id: int
|
|
filename: str
|
|
path: str
|
|
date_taken: Optional[date] = None
|
|
date_added: date
|
|
identified_people: List[PersonInfo]
|
|
identified_people_count: int
|
|
|
|
|
|
class ListVideosResponse(BaseModel):
|
|
"""Response for listing videos."""
|
|
|
|
items: List[VideoListItem]
|
|
page: int
|
|
page_size: int
|
|
total: int
|
|
|
|
|
|
class VideoPersonInfo(BaseModel):
|
|
"""Person information with identification metadata."""
|
|
|
|
person_id: int
|
|
first_name: str
|
|
last_name: str
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
identified_by: Optional[str] = None # Username
|
|
identified_date: datetime
|
|
|
|
|
|
class VideoPeopleResponse(BaseModel):
|
|
"""Response for getting people in a video."""
|
|
|
|
video_id: int
|
|
people: List[VideoPersonInfo]
|
|
|
|
|
|
class IdentifyVideoRequest(BaseModel):
|
|
"""Request to identify a person in a video."""
|
|
|
|
person_id: Optional[int] = None # Use existing person
|
|
first_name: Optional[str] = None # Create new person
|
|
last_name: Optional[str] = None
|
|
middle_name: Optional[str] = None
|
|
maiden_name: Optional[str] = None
|
|
date_of_birth: Optional[date] = None
|
|
|
|
|
|
class IdentifyVideoResponse(BaseModel):
|
|
"""Response for identifying a person in a video."""
|
|
|
|
video_id: int
|
|
person_id: int
|
|
created_person: bool
|
|
message: str
|
|
|
|
|
|
class WebPlaybackPrepareResponse(BaseModel):
|
|
"""Response after requesting browser-safe playback preparation."""
|
|
|
|
status: str
|
|
message: str
|
|
|
|
|
|
class WebPlaybackStatusResponse(BaseModel):
|
|
"""Transcode / readiness status for web playback."""
|
|
|
|
status: str
|
|
error: Optional[str] = None
|
|
|
|
|
|
class RemoveVideoPersonResponse(BaseModel):
|
|
"""Response for removing a person from a video."""
|
|
|
|
video_id: int
|
|
person_id: int
|
|
removed: bool
|
|
message: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|