"""Pydantic schemas for the Higgsfield Shorts wrapper. VideoSpec mirrors the Remotion data contract (remotion/src/data/mumum.ts) 1:1. The LLM (spec_builder) fills VideoSpec; Higgsfield consumes higgsfield_prompt; Remotion consumes the rest (hook / selling_point / brand_lines / end_card). """ from __future__ import annotations from typing import Literal, Optional from pydantic import BaseModel, Field # ---------- Inbound: interview answers (no complex analysis) ---------- class GenerateRequest(BaseModel): kind: Literal["place", "product", "message"] biz_name: str = Field(..., description="업체명·상품명·메시지 제목") addr: Optional[str] = Field(None, description="주소 또는 판매 사이트 URL") price: Optional[str] = Field(None, description="가격 정보") selling: str = Field(..., description="주인/마케터가 생각하는 강력한 한방 셀링포인트") # ---------- VideoSpec sub-objects (mirror mumum.ts) ---------- class Hook(BaseModel): eyebrow: str title: str class SellingPoint(BaseModel): items: list[str] = Field(..., description="3개 독립 배지 카피") class EndCard(BaseModel): brand: str location: str disclosure: str = "실제 사진 기반, AI 카메라 효과를 적용한 영상입니다." class VideoSpec(BaseModel): # 에너지 프로파일 → Remotion 리듬/트랜지션 기본값 결정 profile: Literal["Still Cinema", "Rhythm Reveal", "Maximum Viral"] # Higgsfield marketing_studio_video 프롬프트 (유형별 톤) higgsfield_prompt: str hook: Hook selling_point: SellingPoint brand_lines: list[str] = Field(..., description="감성 카피 2줄") end_card: EndCard caption: str = Field(..., description="업로드용 캡션+해시태그") # ---------- Outbound: 자막 스크립트 4블록 ---------- class ScriptResult(BaseModel): intro: str = Field(..., description="인트로 (후킹)") selling: str = Field(..., description="셀링포인트") story: str = Field(..., description="감성 스토리") cta: str = Field(..., description="CTA") # ---------- Outbound: final result ---------- class GenerateResult(BaseModel): video_url: str caption: str profile: str cost_credits: float = 0.0 job_id: Optional[str] = None