"""썸네일 백그라운드 생성 태스크. /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}")