from sqlalchemy import ( Column, Integer, String, Text, Float, Boolean, DateTime, JSON, Enum, ForeignKey, Index, ) from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.sql import func import enum import uuid from app.database import Base class VideoStatus(enum.Enum): PENDING = "pending" DOWNLOADING = "downloading" EXTRACTING = "extracting" ENCODING = "encoding" INDEXING = "indexing" COMPLETED = "completed" FAILED = "failed" class AnalysisType(enum.Enum): SEARCH = "search" GPS = "gps" AI_DETECTION = "ai_detection" FULL = "full" class AnalysisStatus(enum.Enum): PENDING = "pending" RUNNING = "running" COMPLETED = "completed" FAILED = "failed" class Video(Base): __tablename__ = "videos" __table_args__ = ( Index("idx_videos_youtube_id", "youtube_id", unique=True), Index("idx_videos_status", "status"), Index("idx_videos_created_at", "created_at"), ) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) youtube_id = Column(String(20), unique=True, nullable=False, index=True) youtube_url = Column(String(500), nullable=False) title = Column(String(500), nullable=True) description = Column(Text, nullable=True) channel = Column(String(300), nullable=True) duration = Column(Integer, nullable=True) # seconds thumbnail_url = Column(String(500), nullable=True) upload_date = Column(String(20), nullable=True) # File paths local_path = Column(String(500), nullable=True) frames_count = Column(Integer, default=0) features_count = Column(Integer, default=0) # Status status = Column(Enum(VideoStatus), default=VideoStatus.PENDING) error_message = Column(Text, nullable=True) # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) # Relationships analyses = relationship("Analysis", back_populates="video", cascade="all, delete-orphan") def __repr__(self): return f"