o2o-castad-backend/app/video/worker/thumbnail_task.py

70 lines
2.9 KiB
Python

"""썸네일 백그라운드 생성 태스크.
/video/generate 요청 시 응답을 막지 않도록 BackgroundTasks로 실행되며,
세로형 영상에 한해 썸네일 정지 이미지를 렌더해 Video.video_thumbnail_url에 저장한다.
모든 실패는 경고 로그 후 무시하며 예외를 전파하지 않는다.
"""
from sqlalchemy import select
from app.database.session import BackgroundSessionLocal
from app.utils.creatomate import CreatomateService
from app.utils.logger import get_logger
from app.video.models import Video
from app.video.services.video import get_image_tags_by_task_id
logger = get_logger("video")
async def _save_thumbnail_url(video_id: int, thumbnail_url: str) -> None:
"""렌더된 썸네일 URL을 Video 행에 저장한다."""
async with BackgroundSessionLocal() as session:
result = await session.execute(select(Video).where(Video.id == video_id))
video = result.scalar_one_or_none()
if video is None:
logger.warning(f"[generate_thumbnail_background] Video 없음 - video_id: {video_id}")
return
video.video_thumbnail_url = thumbnail_url
await session.commit()
async def generate_thumbnail_background(
video_id: int,
task_id: str,
orientation: str,
brand_name: str,
region: str,
brand_concept: str,
category_definition: str,
target_keywords: list[str],
) -> None:
"""세로형 영상의 썸네일을 렌더해 Video.video_thumbnail_url에 저장한다.
보조 자산이므로 어떤 실패(이미지 없음, API 오류, 렌더 실패)도 예외를
전파하지 않고 경고 로그 후 종료한다. 가로형은 대상이 아니다.
"""
if orientation != "vertical":
return
try:
service = CreatomateService(orientation=orientation)
taged_image_list = await get_image_tags_by_task_id(task_id)
image_url = service.select_thumbnail_image(taged_image_list)
if not image_url:
logger.warning(f"[generate_thumbnail_background] 썸네일 배경 이미지 없음 — skip - task_id: {task_id}")
return
text_mods = service.make_thumbnail_modification(
brand_name=brand_name,
region=region,
brand_concept=brand_concept,
category_definition=category_definition,
target_keywords=target_keywords,
)
thumbnail_url = await service.render_thumbnail(image_url, text_mods)
if thumbnail_url:
await _save_thumbnail_url(video_id, thumbnail_url)
logger.info(f"[generate_thumbnail_background] 저장 완료 - video_id: {video_id}, url: {thumbnail_url}")
else:
logger.warning(f"[generate_thumbnail_background] 렌더 실패 — skip - task_id: {task_id}")
except Exception as e:
logger.warning(f"[generate_thumbnail_background] 실패(무시) - task_id: {task_id}, error: {e}")