feat(music-lab): Phase 3 백엔드 — 업로드커버, 업로드확장, 보컬추가, 인스트추가, 뮤직비디오
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ from .local_provider import run_local_generation
|
||||
from .suno_provider import (
|
||||
run_suno_generation, run_suno_extend, run_vocal_removal,
|
||||
run_cover_image, run_wav_convert, run_stem_split,
|
||||
run_upload_cover, run_upload_extend, run_add_vocals, run_add_instrumental, run_video_generate,
|
||||
generate_lyrics, get_credits, get_timestamped_lyrics, generate_style_boost,
|
||||
SUNO_API_KEY, SUNO_MODELS,
|
||||
)
|
||||
@@ -498,6 +499,134 @@ def style_boost(req: StyleBoostRequest):
|
||||
return result
|
||||
|
||||
|
||||
# ── Phase 3: 업로드 + 커버 ──────────────────────────────────────────────────
|
||||
|
||||
class UploadCoverRequest(BaseModel):
|
||||
upload_url: str
|
||||
model: str = "V4"
|
||||
custom_mode: bool = True
|
||||
instrumental: bool = False
|
||||
prompt: str = ""
|
||||
style: str = ""
|
||||
title: str = ""
|
||||
vocal_gender: Optional[str] = None
|
||||
negative_tags: Optional[str] = None
|
||||
style_weight: Optional[float] = None
|
||||
audio_weight: Optional[float] = None
|
||||
|
||||
|
||||
@app.post("/api/music/upload-cover")
|
||||
def upload_cover(req: UploadCoverRequest, background_tasks: BackgroundTasks):
|
||||
"""외부 오디오를 Suno 스타일로 리메이크."""
|
||||
if not SUNO_API_KEY:
|
||||
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
|
||||
task_id = str(uuid.uuid4())
|
||||
params = req.model_dump()
|
||||
create_task(task_id, params, provider="suno")
|
||||
background_tasks.add_task(run_upload_cover, task_id, params)
|
||||
return {"task_id": task_id, "provider": "suno"}
|
||||
|
||||
|
||||
# ── Phase 3: 업로드 + 확장 ──────────────────────────────────────────────────
|
||||
|
||||
class UploadExtendRequest(BaseModel):
|
||||
upload_url: str
|
||||
model: str = "V4"
|
||||
default_param_flag: bool = True
|
||||
continue_at: Optional[float] = None
|
||||
prompt: str = ""
|
||||
style: str = ""
|
||||
title: str = ""
|
||||
instrumental: bool = False
|
||||
vocal_gender: Optional[str] = None
|
||||
negative_tags: Optional[str] = None
|
||||
|
||||
|
||||
@app.post("/api/music/upload-extend")
|
||||
def upload_extend(req: UploadExtendRequest, background_tasks: BackgroundTasks):
|
||||
"""외부 오디오를 이어서 확장."""
|
||||
if not SUNO_API_KEY:
|
||||
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
|
||||
task_id = str(uuid.uuid4())
|
||||
params = req.model_dump()
|
||||
create_task(task_id, params, provider="suno")
|
||||
background_tasks.add_task(run_upload_extend, task_id, params)
|
||||
return {"task_id": task_id, "provider": "suno"}
|
||||
|
||||
|
||||
# ── Phase 3: 보컬 추가 ──────────────────────────────────────────────────────
|
||||
|
||||
class AddVocalsRequest(BaseModel):
|
||||
upload_url: str
|
||||
prompt: str
|
||||
title: str
|
||||
style: str
|
||||
negative_tags: str = ""
|
||||
vocal_gender: Optional[str] = None
|
||||
model: str = "V4_5PLUS"
|
||||
style_weight: Optional[float] = None
|
||||
audio_weight: Optional[float] = None
|
||||
|
||||
|
||||
@app.post("/api/music/add-vocals")
|
||||
def add_vocals(req: AddVocalsRequest, background_tasks: BackgroundTasks):
|
||||
"""인스트루멘탈에 AI 보컬 추가."""
|
||||
if not SUNO_API_KEY:
|
||||
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
|
||||
task_id = str(uuid.uuid4())
|
||||
params = req.model_dump()
|
||||
create_task(task_id, params, provider="suno")
|
||||
background_tasks.add_task(run_add_vocals, task_id, params)
|
||||
return {"task_id": task_id, "provider": "suno"}
|
||||
|
||||
|
||||
# ── Phase 3: 인스트루멘탈 추가 ──────────────────────────────────────────────
|
||||
|
||||
class AddInstrumentalRequest(BaseModel):
|
||||
upload_url: str
|
||||
title: str
|
||||
tags: str
|
||||
negative_tags: str = ""
|
||||
vocal_gender: Optional[str] = None
|
||||
model: str = "V4_5PLUS"
|
||||
style_weight: Optional[float] = None
|
||||
audio_weight: Optional[float] = None
|
||||
|
||||
|
||||
@app.post("/api/music/add-instrumental")
|
||||
def add_instrumental(req: AddInstrumentalRequest, background_tasks: BackgroundTasks):
|
||||
"""보컬에 AI 반주 추가."""
|
||||
if not SUNO_API_KEY:
|
||||
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
|
||||
task_id = str(uuid.uuid4())
|
||||
params = req.model_dump()
|
||||
create_task(task_id, params, provider="suno")
|
||||
background_tasks.add_task(run_add_instrumental, task_id, params)
|
||||
return {"task_id": task_id, "provider": "suno"}
|
||||
|
||||
|
||||
# ── Phase 3: 뮤직비디오 생성 ────────────────────────────────────────────────
|
||||
|
||||
class VideoRequest(BaseModel):
|
||||
suno_task_id: str
|
||||
suno_id: str
|
||||
author: str = ""
|
||||
domain_name: str = ""
|
||||
track_id: Optional[int] = None
|
||||
|
||||
|
||||
@app.post("/api/music/video")
|
||||
def video_generate(req: VideoRequest, background_tasks: BackgroundTasks):
|
||||
"""뮤직비디오(MP4) 생성."""
|
||||
if not SUNO_API_KEY:
|
||||
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
|
||||
task_id = str(uuid.uuid4())
|
||||
params = req.model_dump()
|
||||
create_task(task_id, params, provider="suno")
|
||||
background_tasks.add_task(run_video_generate, task_id, params)
|
||||
return {"task_id": task_id, "provider": "suno"}
|
||||
|
||||
|
||||
# ── 저장된 가사 CRUD API ────────────────────────────────────────────────────
|
||||
|
||||
class LyricsSave(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user