Tanya ff47c87e41
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
feat: web video transcoding, admin playback, and viewer fixes
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
2026-03-25 15:33:05 -04:00

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