From bf3d6ee69451ff9becaf4cf9016b829f16276b3e Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 19 May 2026 05:04:56 +0900 Subject: [PATCH] =?UTF-8?q?feat(music-render):=20main.py=20=E2=80=94=20Fas?= =?UTF-8?q?tAPI=20+=20lifespan=20+=20sync=20endpoints=20(SP-5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lifespan에서 worker_loop 스폰. sync forward 4 endpoint: /api/music-render/sync/{lyrics, credits, timestamped-lyrics, style-boost}. NAS music-lab이 이 endpoint들을 httpx forward로 호출. Plan-B-Music Phase 2. Co-Authored-By: Claude Opus 4.7 (1M context) --- services/music-render/main.py | 88 +++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 services/music-render/main.py diff --git a/services/music-render/main.py b/services/music-render/main.py new file mode 100644 index 0000000..743b48a --- /dev/null +++ b/services/music-render/main.py @@ -0,0 +1,88 @@ +"""music-render FastAPI entry — health + lifespan + sync forward endpoints. + +NAS music-lab이 sync helpers(lyrics, credits, timestamped, style-boost)를 +httpx로 forward해서 이 endpoint들을 호출. +""" +from __future__ import annotations + +import asyncio +import logging +from contextlib import asynccontextmanager + +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel + +import worker +from providers.sync_ops import ( + generate_lyrics, get_credits, + get_timestamped_lyrics, generate_style_boost, +) + +logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s") +logger = logging.getLogger(__name__) + + +@asynccontextmanager +async def lifespan(app: FastAPI): + worker_task = asyncio.create_task(worker.worker_loop()) + logger.info("music-render lifespan 시작") + try: + yield + finally: + worker_task.cancel() + try: + await worker_task + except asyncio.CancelledError: + pass + logger.info("music-render lifespan 종료") + + +app = FastAPI(lifespan=lifespan) + + +@app.get("/health") +def health(): + return {"ok": True, "service": "music-render"} + + +# ── Sync forward endpoints ────────────────────────────────────────────── +# NAS music-lab의 /api/music/lyrics 등 sync helpers가 이 endpoint들로 forward. + +class LyricsRequest(BaseModel): + prompt: str + + +@app.post("/api/music-render/sync/lyrics") +def sync_lyrics(req: LyricsRequest): + result = generate_lyrics(req.prompt) + if not result: + raise HTTPException(502, "가사 생성 실패") + return result + + +@app.get("/api/music-render/sync/credits") +def sync_credits(): + result = get_credits() + if result is None: + raise HTTPException(502, "크레딧 조회 실패") + return result + + +@app.get("/api/music-render/sync/timestamped-lyrics") +def sync_timestamped_lyrics(task_id: str, suno_id: str): + result = get_timestamped_lyrics(task_id, suno_id) + if not result: + raise HTTPException(502, "타임스탬프 가사 조회 실패") + return result + + +class StyleBoostRequest(BaseModel): + content: str + + +@app.post("/api/music-render/sync/style-boost") +def sync_style_boost(req: StyleBoostRequest): + result = generate_style_boost(req.content) + if not result: + raise HTTPException(502, "스타일 부스트 생성 실패") + return result