from dataclasses import dataclass from PIL import Image from pydantic import BaseModel, Field Rect = tuple[float, float, float, float] class MaskSpec(BaseModel): """rect — 사각 전체 고정(밝은 배경 포스터. 베벨·그림자까지 덮는다). glyph — 사각 안 글자 픽셀만. 검정 포스터용이며 register와 함께 써야 한다.""" mode: str = "rect" ink_min: int = 55 thin_dilate: int = 9 thick_dilate: int = 25 thick_from_y: float = 0.85 class HybridSpec(BaseModel): clip: str | None = None clip_crop: str | None = None # "x0,y0,w,h" — 9:16 캔버스에 얹힌 클립용 register: bool = False class LayerConfig(BaseModel): """작품별 좌표. 아직 사람이 손으로 쓴다 — 신규 공연은 여기서 멈추는 게 정상이다.""" mask: MaskSpec = MaskSpec() fixed_rects: list[Rect] = [] sil_box: Rect = (0.0, 0.0, 0.0, 0.0) sil_poly: list[tuple[float, float]] = [] glyphs: dict[str, Rect] = {} sweep_at: dict[str, float] = {} punches: list[tuple[Rect, float, float]] = [] # (사각, 시작초, 피크배율) glows: list[tuple[Rect, float]] = [] protect: list[Rect] = [] glyph_dark_ink: bool = True hybrid: HybridSpec = Field(default_factory=HybridSpec) @dataclass class HybridResult: video: bytes frames: int duration: float proof: Image.Image | None = None # 8시점 컨택트 시트