From d2606d731754c6380bf0a062ce3e800951fb0d09 Mon Sep 17 00:00:00 2001 From: gahusb Date: Sat, 4 Apr 2026 13:56:42 +0900 Subject: [PATCH] =?UTF-8?q?music-lab:=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=EB=9F=AC=EB=A6=AC=20=ED=8C=8C=EC=9D=BC=EC=8B=9C=EC=8A=A4?= =?UTF-8?q?=ED=85=9C=20=EB=8F=99=EA=B8=B0=ED=99=94=20+=20v2=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=AA=85=20=EC=A4=91=EB=B3=B5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /api/music/library 호출 시 디스크 .mp3 파일과 DB 자동 동기화 - 디스크에 없는 트랙 → DB에서 삭제 - DB에 없는 .mp3 → 새 트랙으로 자동 등록 - NAS에서 파일명 변경 시 웹에 자동 반영 - _v2_v2 파일명 중복 버그 수정 Co-Authored-By: Claude Opus 4.6 --- music-lab/app/main.py | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) 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): """트랙 수동 추가 (외부 파일 등록 또는 프론트 직접 저장용)"""