o2o-castad-backend/app/video/schemas/video_schema.py

207 lines
8.0 KiB
Python

"""
Video API Schemas
영상 생성 관련 Pydantic 스키마를 정의합니다.
"""
from datetime import datetime
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field
# =============================================================================
# Request Schemas
# =============================================================================
class GenerateVideoRequest(BaseModel):
"""영상 생성 요청 스키마
Usage:
POST /video/generate/{task_id}
Request body for generating a video via Creatomate API.
Note:
- music_url과 duration은 task_id로 Song 테이블에서 자동 조회됩니다.
- 같은 task_id로 여러 Song이 있을 경우 가장 최근 생성된 것을 사용합니다.
Example Request:
{
"orientation": "vertical",
"image_urls": ["https://...", "https://..."],
"lyrics": "가사 내용..."
}
"""
model_config = {
"json_schema_extra": {
"example": {
"orientation": "vertical",
"image_urls": [
"https://naverbooking-phinf.pstatic.net/20240514_189/1715688030436xT14o_JPEG/1.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_48/1715688030574wTtQd_JPEG/2.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_92/17156880307484bvpH_JPEG/3.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_7/1715688031000y8Y5q_JPEG/4.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_259/17156880311809wCnY_JPEG/5.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_64/1715688031601oGNsV_JPEG/6.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_175/1715688031657oXc7l_JPEG/7.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_192/1715688031798MbFDj_JPEG/8.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_205/17156880318681JLwX_JPEG/9.jpg",
"https://naverbooking-phinf.pstatic.net/20240514_142/1715688031946hhxHz_JPEG/10.jpg",
],
"lyrics": "인스타 감성의 스테이 머뭄, 머물러봐요\n군산 신흥동 말랭이 마을의 마음 힐링",
}
}
}
orientation: Literal["horizontal", "vertical"] = Field(
default="vertical",
description="영상 방향 (horizontal: 가로형, vertical: 세로형, 기본값: vertical)",
)
image_urls: List[str] = Field(..., description="영상에 사용할 이미지 URL 목록")
lyrics: str = Field(..., description="영상에 표시할 가사")
# =============================================================================
# Response Schemas
# =============================================================================
class GenerateVideoResponse(BaseModel):
"""영상 생성 응답 스키마
Usage:
POST /video/generate/{task_id}
Returns the task IDs for tracking video generation.
Example Response (Success):
{
"success": true,
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
"creatomate_render_id": "render-id-123",
"message": "영상 생성 요청이 접수되었습니다.",
"error_message": null
}
"""
success: bool = Field(..., description="요청 성공 여부")
task_id: Optional[str] = Field(None, description="내부 작업 ID (Project task_id)")
creatomate_render_id: Optional[str] = Field(None, description="Creatomate 렌더 ID")
message: str = Field(..., description="응답 메시지")
error_message: Optional[str] = Field(None, description="에러 메시지 (실패 시)")
class VideoRenderData(BaseModel):
"""Creatomate 렌더링 결과 데이터"""
id: Optional[str] = Field(None, description="렌더 ID")
status: Optional[str] = Field(None, description="렌더 상태")
url: Optional[str] = Field(None, description="영상 URL")
snapshot_url: Optional[str] = Field(None, description="스냅샷 URL")
class PollingVideoResponse(BaseModel):
"""영상 생성 상태 조회 응답 스키마
Usage:
GET /video/status/{creatomate_render_id}
Creatomate API 작업 상태를 조회합니다.
Note:
상태 값:
- planned: 예약됨
- waiting: 대기 중
- transcribing: 트랜스크립션 중
- rendering: 렌더링 중
- succeeded: 성공
- failed: 실패
Example Response (Success):
{
"success": true,
"status": "succeeded",
"message": "영상 생성이 완료되었습니다.",
"render_data": {
"id": "render-id",
"status": "succeeded",
"url": "https://...",
"snapshot_url": "https://..."
},
"raw_response": {...},
"error_message": null
}
"""
success: bool = Field(..., description="조회 성공 여부")
status: Optional[str] = Field(
None, description="작업 상태 (planned, waiting, rendering, succeeded, failed)"
)
message: str = Field(..., description="상태 메시지")
render_data: Optional[VideoRenderData] = Field(None, description="렌더링 결과 데이터")
raw_response: Optional[Dict[str, Any]] = Field(None, description="Creatomate API 원본 응답")
error_message: Optional[str] = Field(None, description="에러 메시지 (실패 시)")
class DownloadVideoResponse(BaseModel):
"""영상 다운로드 응답 스키마
Usage:
GET /video/download/{task_id}
Polls for video completion and returns project info with video URL.
Note:
상태 값:
- processing: 영상 생성 진행 중 (result_movie_url은 null)
- completed: 영상 생성 완료 (result_movie_url 포함)
- failed: 영상 생성 실패
- not_found: task_id에 해당하는 Video 없음
- error: 조회 중 오류 발생
Example Response (Completed):
{
"success": true,
"status": "completed",
"message": "영상 다운로드가 완료되었습니다.",
"store_name": "스테이 머뭄",
"region": "군산",
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
"result_movie_url": "http://localhost:8000/media/2025-01-15/video.mp4",
"created_at": "2025-01-15T12:00:00",
"error_message": null
}
"""
success: bool = Field(..., description="다운로드 성공 여부")
status: str = Field(..., description="처리 상태 (processing, completed, failed, not_found, error)")
message: str = Field(..., description="응답 메시지")
store_name: Optional[str] = Field(None, description="업체명")
region: Optional[str] = Field(None, description="지역명")
task_id: Optional[str] = Field(None, description="작업 고유 식별자")
result_movie_url: Optional[str] = Field(None, description="영상 결과 URL")
created_at: Optional[datetime] = Field(None, description="생성 일시")
error_message: Optional[str] = Field(None, description="에러 메시지 (실패 시)")
class VideoListItem(BaseModel):
"""영상 목록 아이템 스키마
Usage:
GET /videos 응답의 개별 영상 정보
Example:
{
"store_name": "스테이 머뭄",
"region": "군산",
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
"result_movie_url": "http://localhost:8000/media/2025-01-15/video.mp4",
"created_at": "2025-01-15T12:00:00"
}
"""
store_name: Optional[str] = Field(None, description="업체명")
region: Optional[str] = Field(None, description="지역명")
task_id: str = Field(..., description="작업 고유 식별자")
result_movie_url: Optional[str] = Field(None, description="영상 결과 URL")
created_at: Optional[datetime] = Field(None, description="생성 일시")