219 lines
8.0 KiB
Python
219 lines
8.0 KiB
Python
from typing import Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
# =============================================================================
|
|
# Pydantic Schemas for Song Generation API
|
|
# =============================================================================
|
|
|
|
|
|
class GenerateSongRequest(BaseModel):
|
|
"""노래 생성 요청 스키마
|
|
|
|
Usage:
|
|
POST /song/generate/{task_id}
|
|
Request body for generating a song via Suno API.
|
|
|
|
Example Request:
|
|
{
|
|
"lyrics": "인스타 감성의 스테이 머뭄...",
|
|
"genre": "k-pop",
|
|
"language": "Korean"
|
|
}
|
|
"""
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"example": {
|
|
"lyrics": "인스타 감성의 스테이 머뭄, 머물러봐요 \n군산 신흥동 말랭이 마을의 마음 힐링 \n사진같은 하루, 여행의 시작 \n보석 같은 이곳은 감성 숙소의 느낌 \n\n인근 명소와 아름다움이 가득한 거리 \n힐링의 바람과 여행의 추억 \n글로벌 감성의 스테이 머뭄, 인스타 감성 \n사진으로 남기고 싶은 그 순간들이 되어줘요",
|
|
"genre": "k-pop",
|
|
"language": "Korean",
|
|
}
|
|
}
|
|
}
|
|
|
|
lyrics: str = Field(..., description="노래에 사용할 가사")
|
|
genre: str = Field(
|
|
...,
|
|
description="음악 장르 (K-Pop, Pop, R&B, Hip-Hop, Ballad, EDM, Rock, Jazz 등)",
|
|
)
|
|
language: str = Field(
|
|
default="Korean",
|
|
description="노래 언어 (Korean, English, Chinese, Japanese, Thai, Vietnamese)",
|
|
)
|
|
|
|
|
|
class GenerateSongResponse(BaseModel):
|
|
"""노래 생성 응답 스키마
|
|
|
|
Usage:
|
|
POST /song/generate/{task_id}
|
|
Returns the task IDs for tracking song generation.
|
|
|
|
Note:
|
|
실패 조건:
|
|
- task_id에 해당하는 Project가 없는 경우 (404 HTTPException)
|
|
- task_id에 해당하는 Lyric이 없는 경우 (404 HTTPException)
|
|
- Suno API 호출 실패
|
|
|
|
Example Response (Success):
|
|
{
|
|
"success": true,
|
|
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
|
|
"song_id": "abc123...",
|
|
"message": "노래 생성 요청이 접수되었습니다. song_id로 상태를 조회하세요.",
|
|
"error_message": null
|
|
}
|
|
|
|
Example Response (Failure):
|
|
{
|
|
"success": false,
|
|
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
|
|
"song_id": null,
|
|
"message": "노래 생성 요청에 실패했습니다.",
|
|
"error_message": "Suno API connection error"
|
|
}
|
|
"""
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"examples": [
|
|
{
|
|
"success": True,
|
|
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
|
|
"song_id": "abc123...",
|
|
"message": "노래 생성 요청이 접수되었습니다. song_id로 상태를 조회하세요.",
|
|
"error_message": None,
|
|
},
|
|
{
|
|
"success": False,
|
|
"task_id": "019123ab-cdef-7890-abcd-ef1234567890",
|
|
"song_id": None,
|
|
"message": "노래 생성 요청에 실패했습니다.",
|
|
"error_message": "Suno API connection error",
|
|
},
|
|
]
|
|
}
|
|
}
|
|
|
|
success: bool = Field(..., description="요청 성공 여부")
|
|
task_id: Optional[str] = Field(None, description="내부 작업 ID (Project/Lyric task_id)")
|
|
song_id: Optional[str] = Field(None, description="Suno API 작업 ID (상태 조회에 사용)")
|
|
message: str = Field(..., description="응답 메시지")
|
|
error_message: Optional[str] = Field(None, description="에러 메시지 (실패 시)")
|
|
|
|
|
|
class SongClipData(BaseModel):
|
|
"""생성된 노래 클립 정보"""
|
|
|
|
id: Optional[str] = Field(None, description="클립 ID")
|
|
audio_url: Optional[str] = Field(None, description="오디오 URL")
|
|
stream_audio_url: Optional[str] = Field(None, description="스트리밍 오디오 URL")
|
|
image_url: Optional[str] = Field(None, description="이미지 URL")
|
|
title: Optional[str] = Field(None, description="곡 제목")
|
|
status: Optional[str] = Field(None, description="클립 상태")
|
|
duration: Optional[float] = Field(None, description="노래 길이 (초)")
|
|
|
|
|
|
class PollingSongResponse(BaseModel):
|
|
"""노래 생성 상태 조회 응답 스키마 (Suno API)
|
|
|
|
Usage:
|
|
GET /song/status/{song_id}
|
|
Suno API 작업 상태를 조회합니다.
|
|
|
|
Note:
|
|
상태 값 (Suno API 응답):
|
|
- PENDING: Suno API 대기 중
|
|
- processing: Suno API에서 노래 생성 중
|
|
- uploading: MP3 다운로드 및 Azure Blob 업로드 중
|
|
- SUCCESS: Suno API 노래 생성 완료 (백그라운드 Blob 업로드 시작)
|
|
- TEXT_SUCCESS: Suno API 노래 생성 완료
|
|
- failed: Suno API 노래 생성 실패
|
|
- error: API 조회 오류
|
|
|
|
SUCCESS 상태 시:
|
|
- 백그라운드에서 MP3 파일 다운로드 및 Azure Blob 업로드 시작
|
|
- Song 테이블의 status가 uploading으로 변경
|
|
- 업로드 완료 시 status가 completed로 변경, song_result_url에 Blob URL 저장
|
|
- completed 상태인 경우 song_result_url 반환
|
|
|
|
Example Response (Pending):
|
|
{
|
|
"success": true,
|
|
"status": "PENDING",
|
|
"message": "노래 생성 대기 중입니다.",
|
|
"error_message": null,
|
|
"song_result_url": null
|
|
}
|
|
|
|
Example Response (Processing):
|
|
{
|
|
"success": true,
|
|
"status": "processing",
|
|
"message": "노래를 생성하고 있습니다.",
|
|
"error_message": null,
|
|
"song_result_url": null
|
|
}
|
|
|
|
Example Response (Uploading):
|
|
{
|
|
"success": true,
|
|
"status": "uploading",
|
|
"message": "노래 생성이 완료되었습니다.",
|
|
"error_message": null,
|
|
"song_result_url": null
|
|
}
|
|
|
|
Example Response (Success - Completed):
|
|
{
|
|
"success": true,
|
|
"status": "SUCCESS",
|
|
"message": "노래 생성이 완료되었습니다.",
|
|
"error_message": null,
|
|
"song_result_url": "https://blob.azure.com/.../song.mp3"
|
|
}
|
|
|
|
Example Response (Failure):
|
|
{
|
|
"success": false,
|
|
"status": "error",
|
|
"message": "상태 조회에 실패했습니다.",
|
|
"error_message": "ConnectionError: ...",
|
|
"song_result_url": null
|
|
}
|
|
"""
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"examples": [
|
|
{
|
|
"success": True,
|
|
"status": "processing",
|
|
"message": "노래를 생성하고 있습니다.",
|
|
"error_message": None,
|
|
"song_result_url": None,
|
|
},
|
|
{
|
|
"success": True,
|
|
"status": "SUCCESS",
|
|
"message": "노래 생성이 완료되었습니다.",
|
|
"error_message": None,
|
|
"song_result_url": "https://blob.azure.com/.../song.mp3",
|
|
},
|
|
]
|
|
}
|
|
}
|
|
|
|
success: bool = Field(..., description="조회 성공 여부")
|
|
status: Optional[str] = Field(
|
|
None,
|
|
description="작업 상태 (PENDING, processing, uploading, SUCCESS, TEXT_SUCCESS, failed, error)",
|
|
)
|
|
message: str = Field(..., description="상태 메시지")
|
|
error_message: Optional[str] = Field(None, description="에러 메시지 (실패 시)")
|
|
song_result_url: Optional[str] = Field(
|
|
None, description="노래 결과 URL (Song 테이블 status가 completed일 때 반환)"
|
|
)
|