111 lines
3.2 KiB
Python
111 lines
3.2 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import (
|
|
Column,
|
|
DateTime,
|
|
Enum,
|
|
Float,
|
|
ForeignKey,
|
|
Index,
|
|
String,
|
|
Text,
|
|
func,
|
|
)
|
|
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
|
from sqlalchemy.orm import DeclarativeBase, relationship
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
pass
|
|
|
|
|
|
class Job(Base):
|
|
__tablename__ = "jobs"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
source_type = Column(Enum("youtube", "upload", name="source_type"), nullable=False)
|
|
source_url = Column(Text)
|
|
source_filename = Column(Text)
|
|
title = Column(Text)
|
|
duration = Column(Float)
|
|
status = Column(
|
|
Enum(
|
|
"pending",
|
|
"downloading",
|
|
"transcribing",
|
|
"analyzing",
|
|
"extracting",
|
|
"complete",
|
|
"failed",
|
|
name="job_status",
|
|
),
|
|
nullable=False,
|
|
default="pending",
|
|
)
|
|
progress = Column(Float, nullable=False, default=0.0)
|
|
stage_message = Column(Text)
|
|
error_message = Column(Text)
|
|
media_path = Column(Text)
|
|
transcript = Column(JSONB)
|
|
scene_boundaries = Column(JSONB)
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at = Column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
clips = relationship("Clip", back_populates="job", cascade="all, delete-orphan")
|
|
|
|
|
|
class Clip(Base):
|
|
__tablename__ = "clips"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
job_id = Column(
|
|
UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="CASCADE"), nullable=False
|
|
)
|
|
title = Column(Text, nullable=False)
|
|
start_time = Column(Float, nullable=False)
|
|
end_time = Column(Float, nullable=False)
|
|
virality_score = Column(Float, nullable=False, default=0.0)
|
|
category = Column(Text)
|
|
reasoning = Column(Text)
|
|
transcript_segment = Column(Text)
|
|
thumbnail_path = Column(Text)
|
|
raw_clip_path = Column(Text)
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
job = relationship("Job", back_populates="clips")
|
|
renders = relationship(
|
|
"RenderRequest", back_populates="clip", cascade="all, delete-orphan"
|
|
)
|
|
|
|
|
|
class RenderRequest(Base):
|
|
__tablename__ = "render_requests"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
clip_id = Column(
|
|
UUID(as_uuid=True), ForeignKey("clips.id", ondelete="CASCADE"), nullable=False
|
|
)
|
|
aspect_ratio = Column(
|
|
Enum("16:9", "9:16", "1:1", "4:5", name="aspect_ratio"),
|
|
nullable=False,
|
|
default="9:16",
|
|
)
|
|
subtitle_style = Column(String, nullable=False, default="tiktok")
|
|
status = Column(
|
|
Enum("pending", "rendering", "complete", "failed", name="render_status"),
|
|
nullable=False,
|
|
default="pending",
|
|
)
|
|
progress = Column(Float, nullable=False, default=0.0)
|
|
output_path = Column(Text)
|
|
error_message = Column(Text)
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at = Column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
clip = relationship("Clip", back_populates="renders")
|