modify suno file name
parent
eff711e03e
commit
ca7c0858e2
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue