modify suno file name

insta
Dohyun Lim 2026-02-02 17:01:18 +09:00
parent eff711e03e
commit ca7c0858e2
2 changed files with 7 additions and 87 deletions

View File

@ -415,13 +415,6 @@ async def get_song_status(
# processing 상태인 경우에만 백그라운드 태스크 실행 (중복 방지) # processing 상태인 경우에만 백그라운드 태스크 실행 (중복 방지)
if song and song.status == "processing": if song and song.status == "processing":
# store_name 조회
project_result = await session.execute(
select(Project).where(Project.id == song.project_id)
)
project = project_result.scalar_one_or_none()
store_name = project.store_name if project else "song"
# 상태를 uploading으로 변경 (중복 호출 방지) # 상태를 uploading으로 변경 (중복 호출 방지)
song.status = "uploading" song.status = "uploading"
song.suno_audio_id = first_clip.get("id") song.suno_audio_id = first_clip.get("id")
@ -435,12 +428,11 @@ async def get_song_status(
download_and_upload_song_by_suno_task_id, download_and_upload_song_by_suno_task_id,
suno_task_id=song_id, suno_task_id=song_id,
audio_url=audio_url, audio_url=audio_url,
store_name=store_name,
user_uuid=current_user.user_uuid, user_uuid=current_user.user_uuid,
duration=clip_duration, duration=clip_duration,
) )
logger.info( logger.info(
f"[get_song_status] Background task scheduled - song_id: {suno_task_id}, store_name: {store_name}" f"[get_song_status] Background task scheduled - song_id: {suno_task_id}"
) )
suno_audio_id = first_clip.get("id") suno_audio_id = first_clip.get("id")

View File

@ -4,8 +4,6 @@ Song Background Tasks
노래 생성 관련 백그라운드 태스크를 정의합니다. 노래 생성 관련 백그라운드 태스크를 정의합니다.
""" """
import traceback
from datetime import date
from pathlib import Path from pathlib import Path
import aiofiles import aiofiles
@ -15,10 +13,8 @@ from sqlalchemy.exc import SQLAlchemyError
from app.database.session import BackgroundSessionLocal from app.database.session import BackgroundSessionLocal
from app.song.models import Song from app.song.models import Song
from app.utils.common import generate_task_id
from app.utils.logger import get_logger from app.utils.logger import get_logger
from app.utils.upload_blob_as_request import AzureBlobUploader from app.utils.upload_blob_as_request import AzureBlobUploader
from config import prj_settings
# 로거 설정 # 로거 설정
logger = get_logger("song") logger = get_logger("song")
@ -109,87 +105,23 @@ async def _download_audio(url: str, task_id: str) -> bytes:
return response.content return response.content
async def download_and_save_song(
task_id: str,
audio_url: str,
store_name: str,
) -> None:
"""백그라운드에서 노래를 다운로드하고 Song 테이블을 업데이트합니다.
Args:
task_id: 프로젝트 task_id
audio_url: 다운로드할 오디오 URL
store_name: 저장할 파일명에 사용할 업체명
"""
logger.info(f"[download_and_save_song] START - task_id: {task_id}, store_name: {store_name}")
try:
# 저장 경로 생성: media/song/{날짜}/{uuid7}/{store_name}.mp3
today = date.today().strftime("%Y-%m-%d")
unique_id = await generate_task_id()
# 파일명에 사용할 수 없는 문자 제거
safe_store_name = "".join(
c for c in store_name if c.isalnum() or c in (" ", "_", "-")
).strip()
safe_store_name = safe_store_name or "song"
file_name = f"{safe_store_name}.mp3"
# 절대 경로 생성
media_dir = Path("media") / "song" / today / unique_id
media_dir.mkdir(parents=True, exist_ok=True)
file_path = media_dir / file_name
logger.info(f"[download_and_save_song] Directory created - path: {file_path}")
# 오디오 파일 다운로드
logger.info(f"[download_and_save_song] Downloading audio - task_id: {task_id}, url: {audio_url}")
content = await _download_audio(audio_url, task_id)
async with aiofiles.open(str(file_path), "wb") as f:
await f.write(content)
logger.info(f"[download_and_save_song] File saved - task_id: {task_id}, path: {file_path}")
# 프론트엔드에서 접근 가능한 URL 생성
relative_path = f"/media/song/{today}/{unique_id}/{file_name}"
base_url = f"{prj_settings.PROJECT_DOMAIN}"
file_url = f"{base_url}{relative_path}"
logger.info(f"[download_and_save_song] URL generated - task_id: {task_id}, url: {file_url}")
# Song 테이블 업데이트
await _update_song_status(task_id, "completed", file_url)
logger.info(f"[download_and_save_song] SUCCESS - task_id: {task_id}")
except httpx.HTTPError as e:
logger.error(f"[download_and_save_song] DOWNLOAD ERROR - task_id: {task_id}, error: {e}", exc_info=True)
await _update_song_status(task_id, "failed")
except SQLAlchemyError as e:
logger.error(f"[download_and_save_song] DB ERROR - task_id: {task_id}, error: {e}", exc_info=True)
await _update_song_status(task_id, "failed")
except Exception as e:
logger.error(f"[download_and_save_song] EXCEPTION - task_id: {task_id}, error: {e}", exc_info=True)
await _update_song_status(task_id, "failed")
async def download_and_upload_song_by_suno_task_id( async def download_and_upload_song_by_suno_task_id(
suno_task_id: str, suno_task_id: str,
audio_url: str, audio_url: str,
store_name: str,
user_uuid: str, user_uuid: str,
duration: float | None = None, duration: float | None = None,
) -> None: ) -> None:
"""suno_task_id로 Song을 조회하여 노래를 다운로드하고 Azure Blob Storage에 업로드한 뒤 Song 테이블을 업데이트합니다. """suno_task_id로 Song을 조회하여 노래를 다운로드하고 Azure Blob Storage에 업로드한 뒤 Song 테이블을 업데이트합니다.
파일명은 suno_task_id를 사용하여 고유성을 보장합니다.
Args: Args:
suno_task_id: Suno API 작업 ID suno_task_id: Suno API 작업 ID (파일명으로도 사용)
audio_url: 다운로드할 오디오 URL audio_url: 다운로드할 오디오 URL
store_name: 저장할 파일명에 사용할 업체명
user_uuid: 사용자 UUID (Azure Blob Storage 경로에 사용) user_uuid: 사용자 UUID (Azure Blob Storage 경로에 사용)
duration: 노래 재생 시간 () duration: 노래 재생 시간 ()
""" """
logger.info(f"[download_and_upload_song_by_suno_task_id] START - suno_task_id: {suno_task_id}, store_name: {store_name}, duration: {duration}") logger.info(f"[download_and_upload_song_by_suno_task_id] START - suno_task_id: {suno_task_id}, duration: {duration}")
temp_file_path: Path | None = None temp_file_path: Path | None = None
task_id: str | None = None task_id: str | None = None
@ -211,12 +143,8 @@ async def download_and_upload_song_by_suno_task_id(
task_id = song.task_id task_id = song.task_id
logger.info(f"[download_and_upload_song_by_suno_task_id] Song found - suno_task_id: {suno_task_id}, task_id: {task_id}") logger.info(f"[download_and_upload_song_by_suno_task_id] Song found - suno_task_id: {suno_task_id}, task_id: {task_id}")
# 파일명에 사용할 수 없는 문자 제거 # suno_task_id를 파일명으로 사용 (고유 ID이므로 sanitize 불필요)
safe_store_name = "".join( file_name = f"{suno_task_id}.mp3"
c for c in store_name if c.isalnum() or c in (" ", "_", "-")
).strip()
safe_store_name = safe_store_name or "song"
file_name = f"{safe_store_name}.mp3"
# 임시 저장 경로 생성 # 임시 저장 경로 생성
temp_dir = Path("media") / "temp" / task_id temp_dir = Path("media") / "temp" / task_id