refactor(music-lab): suno_provider/local_provider → stub (SP-6)
기존 13+1 외부 API 호출 함수는 web-ai/services/music-render/providers로 이식. NAS는 SUNO_MODELS (정적 데이터)만 잔존. SUNO_API_KEY = "" sentinel. Plan-B-Music Phase 3 (cutover 4/4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,122 +1,5 @@
|
|||||||
|
"""DEPRECATED 2026-05-19 — MusicGen 호출은 Windows music-render로 이전.
|
||||||
|
|
||||||
|
기존 run_local_generation은 web-ai/services/music-render/providers/local.py로 이식.
|
||||||
|
NAS는 Redis push (queue:music-render, job_type=local_generation)만 담당.
|
||||||
"""
|
"""
|
||||||
Local MusicGen Provider — Windows AI 서버(MusicGen)를 통한 음악 생성
|
|
||||||
기존 _run_generation 로직을 그대로 분리.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from .db import update_task, add_track
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
MUSIC_AI_SERVER_URL = os.getenv("MUSIC_AI_SERVER_URL", "")
|
|
||||||
MUSIC_DATA_DIR = "/app/data"
|
|
||||||
MUSIC_MEDIA_BASE = os.getenv("MUSIC_MEDIA_BASE", "/media/music")
|
|
||||||
|
|
||||||
|
|
||||||
def run_local_generation(task_id: str, params: dict) -> None:
|
|
||||||
"""BackgroundTask: Windows AI 서버(MusicGen)에 생성 요청 → 파일 저장 → 라이브러리 등록"""
|
|
||||||
try:
|
|
||||||
update_task(task_id, "processing", 10, "AI 서버에 연결 중...")
|
|
||||||
|
|
||||||
if not MUSIC_AI_SERVER_URL:
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error="MUSIC_AI_SERVER_URL이 설정되지 않았습니다")
|
|
||||||
return
|
|
||||||
|
|
||||||
update_task(task_id, "processing", 30, "음악 생성 중... (수 분 소요될 수 있습니다)")
|
|
||||||
|
|
||||||
# 1단계: 생성 요청 → ai_task_id 반환
|
|
||||||
resp = requests.post(
|
|
||||||
f"{MUSIC_AI_SERVER_URL}/generate",
|
|
||||||
json=params,
|
|
||||||
timeout=30,
|
|
||||||
)
|
|
||||||
|
|
||||||
if resp.status_code != 200:
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error=f"AI 서버 오류: {resp.status_code} {resp.text[:200]}")
|
|
||||||
return
|
|
||||||
|
|
||||||
ai_task_id = resp.json().get("task_id")
|
|
||||||
if not ai_task_id:
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error="AI 서버 응답에 task_id가 없습니다")
|
|
||||||
return
|
|
||||||
|
|
||||||
# 2단계: 상태 폴링 (최대 10분, 5초 간격)
|
|
||||||
remote_url = None
|
|
||||||
for _ in range(120):
|
|
||||||
time.sleep(5)
|
|
||||||
status_resp = requests.get(
|
|
||||||
f"{MUSIC_AI_SERVER_URL}/status/{ai_task_id}", timeout=10,
|
|
||||||
)
|
|
||||||
status_data = status_resp.json()
|
|
||||||
ai_status = status_data.get("status")
|
|
||||||
|
|
||||||
ai_progress = status_data.get("progress", 0)
|
|
||||||
ai_message = status_data.get("message", "음악 생성 중...")
|
|
||||||
scaled = 30 + int(ai_progress * 0.49) # 30% ~ 79%
|
|
||||||
update_task(task_id, "processing", scaled, ai_message)
|
|
||||||
|
|
||||||
if ai_status == "succeeded":
|
|
||||||
remote_url = status_data.get("audio_url")
|
|
||||||
break
|
|
||||||
elif ai_status == "failed":
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error=status_data.get("error", "AI 서버 생성 실패"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if not remote_url:
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error="AI 서버 타임아웃 (10분 초과)")
|
|
||||||
return
|
|
||||||
|
|
||||||
update_task(task_id, "processing", 80, "파일 저장 중...")
|
|
||||||
|
|
||||||
filename = f"{task_id}.mp3"
|
|
||||||
file_path = os.path.join(MUSIC_DATA_DIR, filename)
|
|
||||||
|
|
||||||
# 3단계: 오디오 파일 다운로드
|
|
||||||
dl = requests.get(remote_url, timeout=120, stream=True)
|
|
||||||
with open(file_path, "wb") as f:
|
|
||||||
for chunk in dl.iter_content(chunk_size=8192):
|
|
||||||
f.write(chunk)
|
|
||||||
|
|
||||||
audio_url = f"{MUSIC_MEDIA_BASE}/{filename}"
|
|
||||||
|
|
||||||
# 라이브러리 자동 등록
|
|
||||||
genre = params.get("genre", "")
|
|
||||||
moods = params.get("moods", [])
|
|
||||||
mood_str = moods[0] if moods else "Original"
|
|
||||||
title = params.get("title") or (
|
|
||||||
f"{genre} — {mood_str} Mix" if genre else f"{mood_str} Mix"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_track({
|
|
||||||
"title": title,
|
|
||||||
"genre": genre,
|
|
||||||
"moods": params.get("moods", []),
|
|
||||||
"instruments": params.get("instruments", []),
|
|
||||||
"duration_sec": params.get("duration_sec"),
|
|
||||||
"bpm": params.get("bpm"),
|
|
||||||
"key": params.get("key", ""),
|
|
||||||
"scale": params.get("scale", ""),
|
|
||||||
"prompt": params.get("prompt", ""),
|
|
||||||
"audio_url": audio_url,
|
|
||||||
"file_path": file_path,
|
|
||||||
"task_id": task_id,
|
|
||||||
"provider": "local",
|
|
||||||
})
|
|
||||||
|
|
||||||
update_task(task_id, "succeeded", 100, "생성 완료", audio_url=audio_url)
|
|
||||||
|
|
||||||
except requests.Timeout:
|
|
||||||
update_task(task_id, "failed", 0, "",
|
|
||||||
error="AI 서버 타임아웃 (10분 초과)")
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception("Local generation error for task %s", task_id)
|
|
||||||
update_task(task_id, "failed", 0, "", error=str(e))
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user