feat(music-lab): Phase 2 백엔드 — WAV 변환, 12스템 분리, 타임스탬프 가사, 스타일 부스트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-08 08:58:37 +09:00
parent 3e46cc41ca
commit 94969f97a8
2 changed files with 245 additions and 2 deletions

View File

@@ -15,8 +15,8 @@ from .db import (
from .local_provider import run_local_generation
from .suno_provider import (
run_suno_generation, run_suno_extend, run_vocal_removal,
run_cover_image,
generate_lyrics, get_credits,
run_cover_image, run_wav_convert, run_stem_split,
generate_lyrics, get_credits, get_timestamped_lyrics, generate_style_boost,
SUNO_API_KEY, SUNO_MODELS,
)
@@ -428,6 +428,76 @@ def cover_image(req: CoverImageRequest, background_tasks: BackgroundTasks):
return {"task_id": task_id, "provider": "suno"}
# ── WAV 변환 API ────────────────────────────────────────────────────────────
class WavRequest(BaseModel):
suno_task_id: str
suno_id: str
track_id: Optional[int] = None
@app.post("/api/music/wav")
def wav_convert(req: WavRequest, background_tasks: BackgroundTasks):
"""곡을 WAV 포맷으로 변환."""
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_wav_convert, task_id, params)
return {"task_id": task_id, "provider": "suno"}
# ── 12스템 분리 API ─────────────────────────────────────────────────────────
class StemSplitRequest(BaseModel):
suno_task_id: str
suno_id: str
track_id: Optional[int] = None
@app.post("/api/music/stem-split")
def stem_split(req: StemSplitRequest, background_tasks: BackgroundTasks):
"""곡을 12개 스템으로 분리 (50 크레딧). 보컬, 드럼, 베이스, 기타 등."""
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_stem_split, task_id, params)
return {"task_id": task_id, "provider": "suno"}
# ── 타임스탬프 가사 API ─────────────────────────────────────────────────────
@app.get("/api/music/timestamped-lyrics")
def timestamped_lyrics(task_id: str, suno_id: str):
"""타임스탬프 가사 조회 (가라오케 스타일 싱크용)."""
if not SUNO_API_KEY:
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
result = get_timestamped_lyrics(task_id, suno_id)
if not result:
raise HTTPException(status_code=502, detail="타임스탬프 가사 조회 실패")
return result
# ── 스타일 부스트 API ───────────────────────────────────────────────────────
class StyleBoostRequest(BaseModel):
content: str
@app.post("/api/music/style-boost")
def style_boost(req: StyleBoostRequest):
"""AI로 최적 스타일 프롬프트 생성."""
if not SUNO_API_KEY:
raise HTTPException(status_code=400, detail="Suno API 키가 설정되지 않았습니다")
result = generate_style_boost(req.content)
if not result:
raise HTTPException(status_code=502, detail="스타일 부스트 생성 실패")
return result
# ── 저장된 가사 CRUD API ────────────────────────────────────────────────────
class LyricsSave(BaseModel):