diff --git a/music-lab/app/main.py b/music-lab/app/main.py index 0fee6fa..4b4b5d4 100644 --- a/music-lab/app/main.py +++ b/music-lab/app/main.py @@ -171,10 +171,52 @@ class TrackCreate(BaseModel): @app.get("/api/music/library") def list_library(): - """저장된 트랙 목록 전체 조회 (생성일 내림차순)""" + """저장된 트랙 목록 전체 조회 (생성일 내림차순). 파일시스템과 자동 동기화.""" + _sync_library_with_disk() return {"tracks": get_all_tracks()} +def _sync_library_with_disk(): + """파일시스템의 .mp3 파일과 DB를 동기화. + - 디스크에 없는 트랙 → DB에서 삭제 + - DB에 없는 .mp3 파일 → 새 트랙으로 추가 + """ + tracks = get_all_tracks() + media_base = os.getenv("MUSIC_MEDIA_BASE", "/media/music") + + # 디스크의 .mp3 파일 목록 + disk_files = set() + try: + for f in os.listdir(MUSIC_DATA_DIR): + if f.lower().endswith(".mp3"): + disk_files.add(f) + except OSError: + return # 디렉토리 접근 불가 시 동기화 스킵 + + # DB 트랙의 파일명 매핑 + db_filenames = {} # filename → track + for t in tracks: + if t.get("audio_url"): + fname = t["audio_url"].split("/")[-1] + db_filenames[fname] = t + + # DB에는 있지만 디스크에 없는 → 삭제 + for fname, t in db_filenames.items(): + if fname not in disk_files: + delete_track(t["id"]) + + # 디스크에는 있지만 DB에 없는 → 추가 + for f in disk_files: + if f not in db_filenames: + title = os.path.splitext(f)[0].replace("-", " ").replace("_", " ") + add_track({ + "title": title, + "audio_url": f"{media_base}/{f}", + "file_path": os.path.join(MUSIC_DATA_DIR, f), + "provider": "suno", + }) + + @app.post("/api/music/library", status_code=201) def save_to_library(req: TrackCreate): """트랙 수동 추가 (외부 파일 등록 또는 프론트 직접 저장용)"""