From 32c6c210a001c69c859f5f5eb5586ac079f7929a Mon Sep 17 00:00:00 2001 From: dhlim Date: Wed, 4 Feb 2026 10:28:47 +0000 Subject: [PATCH] =?UTF-8?q?=EA=B0=80=EC=82=AC=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8,=20=ED=8F=B0?= =?UTF-8?q?=ED=8A=B8=20=EC=84=A0=ED=83=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EC=A3=BC=EC=86=8C=20injection=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/utils/creatomate.py | 59 +++++++++++++++++++++++-------- app/utils/nvMapPwScraper.py | 2 +- app/video/api/routers/v1/video.py | 13 +++++-- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/app/utils/creatomate.py b/app/utils/creatomate.py index abbfd51..3e99f20 100644 --- a/app/utils/creatomate.py +++ b/app/utils/creatomate.py @@ -122,7 +122,38 @@ text_template_v_2 = { } ] } - +text_template_v_3 = { + "type": "composition", + "track": 3, + "elements": [ + { + "type": "text", + "time": 0, + "x": "0%", + "y": "80%", + "width": "100%", + "height": "15%", + "x_anchor": "0%", + "y_anchor": "0%", + "x_alignment": "50%", + "y_alignment": "50%", + "font_family": "Noto Sans", + "font_weight": "700", + "font_size_maximum": "7 vmin", + "fill_color": "#ffffff", + "animations": [ + { + "time": 0, + "duration": 1, + "easing": "quadratic-out", + "type": "text-wave", + "split": "line", + "overlap": "50%" + } + ] + } + ] +} text_template_h_1 = { "type": "composition", "track": 3, @@ -408,6 +439,7 @@ class CreatomateService: image_url_list: list[str], lyric: str, music_url: str, + address: str = None ) -> dict: """템플릿 정보와 이미지/가사/음악 리소스를 매핑합니다. @@ -434,9 +466,8 @@ class CreatomateService: idx % len(image_url_list) ] case "text": - modifications[template_component_name] = lyric_splited[ - idx % len(lyric_splited) - ] + if "address_input" in template_component_name: + modifications[template_component_name] = address modifications["audio-music"] = music_url @@ -448,12 +479,11 @@ class CreatomateService: image_url_list: list[str], lyric: str, music_url: str, + address: str = None ) -> dict: """elements 정보와 이미지/가사/음악 리소스를 매핑합니다.""" template_component_data = self.parse_template_component_name(elements) - lyric = lyric.replace("\r", "") - lyric_splited = lyric.split("\n") modifications = {} for idx, (template_component_name, template_type) in enumerate( @@ -465,9 +495,8 @@ class CreatomateService: idx % len(image_url_list) ] case "text": - modifications[template_component_name] = lyric_splited[ - idx % len(lyric_splited) - ] + if "address_input" in template_component_name: + modifications[template_component_name] = address modifications["audio-music"] = music_url @@ -486,7 +515,8 @@ class CreatomateService: case "video": element["source"] = modification[element["name"]] case "text": - element["source"] = modification.get(element["name"], "") + #element["source"] = modification[element["name"]] + element["text"] = modification.get(element["name"], "") case "composition": for minor in element["elements"]: recursive_modify(minor) @@ -704,8 +734,8 @@ class CreatomateService: def extend_template_duration(self, template: dict, target_duration: float) -> dict: """템플릿의 duration을 target_duration으로 확장합니다.""" - target_duration += 0.1 # 수동으로 직접 변경 및 테스트 필요 : 파란박스 생기는것 - template["duration"] = target_duration + template["duration"] = target_duration + 0.5 # 늘린것보단 짧게 + target_duration += 1 # 수동으로 직접 변경 및 테스트 필요 : 파란박스 생기는것 total_template_duration = self.calc_scene_duration(template) extend_rate = target_duration / total_template_duration new_template = copy.deepcopy(template) @@ -727,7 +757,7 @@ class CreatomateService: return new_template - def lining_lyric(self, text_template: dict, lyric_index: int, lyric_text: str, start_sec: float, end_sec: float) -> dict: + def lining_lyric(self, text_template: dict, lyric_index: int, lyric_text: str, start_sec: float, end_sec: float, font_family: str = "Noto Sans") -> dict: duration = end_sec - start_sec text_scene = copy.deepcopy(text_template) text_scene["name"] = f"Caption-{lyric_index}" @@ -735,6 +765,7 @@ class CreatomateService: text_scene["time"] = start_sec text_scene["elements"][0]["name"] = f"lyric-{lyric_index}" text_scene["elements"][0]["text"] = lyric_text + text_scene["elements"][0]["font_family"] = font_family return text_scene def auto_lyric(self, auto_text_template : dict): @@ -744,7 +775,7 @@ class CreatomateService: def get_text_template(self): match self.orientation: case "vertical": - return text_template_v_2 + return text_template_v_3 case "horizontal": return text_template_h_1 diff --git a/app/utils/nvMapPwScraper.py b/app/utils/nvMapPwScraper.py index 0293d12..2885242 100644 --- a/app/utils/nvMapPwScraper.py +++ b/app/utils/nvMapPwScraper.py @@ -15,7 +15,7 @@ class NvMapPwScraper(): _context = None _win_width = 1280 _win_height = 720 - _max_retry = 40 # place id timeout threshold seconds + _max_retry = 60 # place id timeout threshold seconds # instance var page = None diff --git a/app/video/api/routers/v1/video.py b/app/video/api/routers/v1/video.py index 15f32f4..b203082 100644 --- a/app/video/api/routers/v1/video.py +++ b/app/video/api/routers/v1/video.py @@ -201,6 +201,7 @@ async def generate_video( detail=f"task_id '{task_id}'에 해당하는 Project를 찾을 수 없습니다.", ) project_id = project.id + store_address = project.detail_region_info # ===== 결과 처리: Lyric ===== lyric = lyric_result.scalar_one_or_none() @@ -211,6 +212,7 @@ async def generate_video( detail=f"task_id '{task_id}'에 해당하는 Lyric을 찾을 수 없습니다.", ) lyric_id = lyric.id + lyric_language = lyric.language # ===== 결과 처리: Song ===== song = song_result.scalar_one_or_none() @@ -313,6 +315,7 @@ async def generate_video( image_url_list=image_urls, lyric=lyrics, music_url=music_url, + address=store_address ) logger.debug(f"[generate_video] Modifications created - task_id: {task_id}") @@ -333,8 +336,6 @@ async def generate_video( f"[generate_video] Duration extended to {creatomate_service.target_duration}s - task_id: {task_id}" ) - # 이런거 추가해야하는데 AI가 자꾸 번호 달면 제가 번호를 다 밀어야 하나요? - song_timestamp_result = await session.execute( select(SongTimestamp).where( SongTimestamp.suno_audio_id == song.suno_audio_id @@ -350,6 +351,13 @@ async def generate_video( f"[generate_video] timestamp[{i}]: lyric_line={ts.lyric_line}, start_time={ts.start_time}, end_time={ts.end_time}" ) + match lyric_language: + case "English" : + lyric_font = "Noto Sans" + # lyric_font = "Pretendard" # 없어요 + case _ : + lyric_font = "Noto Sans" + # LYRIC AUTO 결정부 if (creatomate_settings.DEBUG_AUTO_LYRIC): auto_text_template = creatomate_service.get_auto_text_template() @@ -363,6 +371,7 @@ async def generate_video( aligned.lyric_line, aligned.start_time, aligned.end_time, + lyric_font ) final_template["source"]["elements"].append(caption) # END - LYRIC AUTO 결정부