music-lab: Suno API + MusicGen 듀얼 프로바이더 구조 구현
- suno_provider.py: Suno REST API 클라이언트 (곡 생성, 가사, 2변형 저장) - local_provider.py: 기존 MusicGen 로직 분리 - main.py: provider 라우팅, /providers·/lyrics 엔드포인트 추가 - db.py: provider, lyrics, image_url, suno_id 컬럼 마이그레이션 - docker-compose.yml: SUNO_API_KEY 환경변수 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ def init_db() -> None:
|
||||
audio_url TEXT,
|
||||
error TEXT,
|
||||
params TEXT NOT NULL DEFAULT '{}',
|
||||
provider TEXT NOT NULL DEFAULT 'local',
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||||
)
|
||||
@@ -46,11 +47,29 @@ def init_db() -> None:
|
||||
file_path TEXT NOT NULL DEFAULT '',
|
||||
task_id TEXT,
|
||||
tags TEXT NOT NULL DEFAULT '[]',
|
||||
provider TEXT NOT NULL DEFAULT 'local',
|
||||
lyrics TEXT NOT NULL DEFAULT '',
|
||||
image_url TEXT NOT NULL DEFAULT '',
|
||||
suno_id TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_library_created ON music_library(created_at DESC)")
|
||||
|
||||
# 기존 테이블 마이그레이션 (컬럼 없으면 추가)
|
||||
for col, default in [
|
||||
("provider", "'local'"), ("lyrics", "''"),
|
||||
("image_url", "''"), ("suno_id", "''"),
|
||||
]:
|
||||
try:
|
||||
conn.execute(f"ALTER TABLE music_library ADD COLUMN {col} TEXT NOT NULL DEFAULT {default}")
|
||||
except sqlite3.OperationalError:
|
||||
pass # 이미 존재
|
||||
try:
|
||||
conn.execute("ALTER TABLE music_tasks ADD COLUMN provider TEXT NOT NULL DEFAULT 'local'")
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
|
||||
|
||||
# ── music_tasks CRUD ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -63,16 +82,17 @@ def _task_row_to_dict(r) -> Dict[str, Any]:
|
||||
"audio_url": r["audio_url"],
|
||||
"error": r["error"],
|
||||
"params": json.loads(r["params"]),
|
||||
"provider": r["provider"] if "provider" in r.keys() else "local",
|
||||
"created_at": r["created_at"],
|
||||
"updated_at": r["updated_at"],
|
||||
}
|
||||
|
||||
|
||||
def create_task(task_id: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
||||
def create_task(task_id: str, params: Dict[str, Any], provider: str = "local") -> Dict[str, Any]:
|
||||
with _conn() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO music_tasks (id, params) VALUES (?, ?)",
|
||||
(task_id, json.dumps(params)),
|
||||
"INSERT INTO music_tasks (id, params, provider) VALUES (?, ?, ?)",
|
||||
(task_id, json.dumps(params), provider),
|
||||
)
|
||||
row = conn.execute("SELECT * FROM music_tasks WHERE id = ?", (task_id,)).fetchone()
|
||||
return _task_row_to_dict(row)
|
||||
@@ -107,6 +127,7 @@ def get_task(task_id: str) -> Optional[Dict[str, Any]]:
|
||||
# ── music_library CRUD ────────────────────────────────────────────────────────
|
||||
|
||||
def _track_row_to_dict(r) -> Dict[str, Any]:
|
||||
keys = r.keys()
|
||||
return {
|
||||
"id": r["id"],
|
||||
"title": r["title"],
|
||||
@@ -122,6 +143,10 @@ def _track_row_to_dict(r) -> Dict[str, Any]:
|
||||
"file_path": r["file_path"],
|
||||
"task_id": r["task_id"],
|
||||
"tags": json.loads(r["tags"]) if r["tags"] else [],
|
||||
"provider": r["provider"] if "provider" in keys else "local",
|
||||
"lyrics": r["lyrics"] if "lyrics" in keys else "",
|
||||
"image_url": r["image_url"] if "image_url" in keys else "",
|
||||
"suno_id": r["suno_id"] if "suno_id" in keys else "",
|
||||
"created_at": r["created_at"],
|
||||
}
|
||||
|
||||
@@ -138,8 +163,9 @@ def add_track(data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
INSERT INTO music_library
|
||||
(title, genre, moods, instruments, duration_sec, bpm, key, scale,
|
||||
prompt, audio_url, file_path, task_id, tags)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
prompt, audio_url, file_path, task_id, tags,
|
||||
provider, lyrics, image_url, suno_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
data.get("title", ""),
|
||||
@@ -155,6 +181,10 @@ def add_track(data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
data.get("file_path", ""),
|
||||
data.get("task_id"),
|
||||
json.dumps(data.get("tags", [])),
|
||||
data.get("provider", "local"),
|
||||
data.get("lyrics", ""),
|
||||
data.get("image_url", ""),
|
||||
data.get("suno_id", ""),
|
||||
),
|
||||
)
|
||||
row = conn.execute("SELECT * FROM music_library WHERE rowid = last_insert_rowid()").fetchone()
|
||||
|
||||
Reference in New Issue
Block a user