From fef3b3c8fda19cc9090f07a42c65b9eb30e4cf71 Mon Sep 17 00:00:00 2001 From: linyq Date: Thu, 8 May 2025 20:45:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(subtitle):=20=E6=B7=BB=E5=8A=A0=E5=AD=97?= =?UTF-8?q?=E5=B9=95=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BD=8D=E7=BD=AE=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 generate_video.py 中实现自定义字幕位置的逻辑 - 在 schema.py 中添加 custom_position 字段 - 更新 webui 组件以支持自定义位置设置 - 调整任务处理逻辑,支持新的自定义位置参数 --- app/models/schema.py | 5 +++-- app/services/generate_video.py | 16 +++++++++++++--- app/services/task.py | 9 +++++---- webui/components/subtitle_settings.py | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/models/schema.py b/app/models/schema.py index 623a3fd..ddf0ad1 100644 --- a/app/models/schema.py +++ b/app/models/schema.py @@ -362,9 +362,10 @@ class VideoClipParams(BaseModel): text_back_color: Optional[str] = None # 文本背景色 stroke_color: str = "black" # 描边颜色 stroke_width: float = 1.5 # 描边宽度 - subtitle_position: str = "bottom" # top, bottom, center, custom + subtitle_position: str = "bottom" # top, bottom, center, custom + custom_position: float = 70.0 # 自定义位置 - n_threads: Optional[int] = Field(default=16, description="解说语音音量") # 线程���,有助于提升视频处理速度 + n_threads: Optional[int] = Field(default=16, description="线程数") # 线程数,有助于提升视频处理速度 tts_volume: Optional[float] = Field(default=1.0, description="解说语音音量(后处理)") original_volume: Optional[float] = Field(default=1.0, description="视频原声音量") diff --git a/app/services/generate_video.py b/app/services/generate_video.py index 04db992..f125c05 100644 --- a/app/services/generate_video.py +++ b/app/services/generate_video.py @@ -10,7 +10,7 @@ import os import traceback -from typing import Optional, Dict, Any, Union +from typing import Optional, Dict, Any from loguru import logger from moviepy import ( VideoFileClip, @@ -18,7 +18,6 @@ from moviepy import ( CompositeAudioClip, CompositeVideoClip, TextClip, - concatenate_videoclips, afx ) from moviepy.video.tools.subtitles import SubtitlesClip @@ -54,6 +53,7 @@ def merge_materials( - subtitle_color: 字幕颜色,默认白色 - subtitle_bg_color: 字幕背景颜色,默认透明 - subtitle_position: 字幕位置,可选值'bottom', 'top', 'center',默认'bottom' + - custom_position: 自定义位置 - stroke_color: 描边颜色,默认黑色 - stroke_width: 描边宽度,默认1 - threads: 处理线程数,默认2 @@ -71,11 +71,12 @@ def merge_materials( bgm_volume = options.get('bgm_volume', 0.3) original_audio_volume = options.get('original_audio_volume', 0.0) # 默认为0,即不保留原声 keep_original_audio = options.get('keep_original_audio', False) # 是否保留原声 - subtitle_font = options.get('subtitle_font', None) + subtitle_font = options.get('subtitle_font', '') subtitle_font_size = options.get('subtitle_font_size', 40) subtitle_color = options.get('subtitle_color', '#FFFFFF') subtitle_bg_color = options.get('subtitle_bg_color', 'transparent') subtitle_position = options.get('subtitle_position', 'bottom') + custom_position = options.get('custom_position', 70) stroke_color = options.get('stroke_color', '#000000') stroke_width = options.get('stroke_width', 1) threads = options.get('threads', 2) @@ -222,6 +223,15 @@ def merge_materials( _clip = _clip.with_position(("center", video_height * 0.95 - _clip.h)) elif subtitle_position == "top": _clip = _clip.with_position(("center", video_height * 0.05)) + elif subtitle_position == "custom": + margin = 10 + max_y = video_height - _clip.h - margin + min_y = margin + custom_y = (video_height - _clip.h) * (custom_position / 100) + custom_y = max( + min_y, min(custom_y, max_y) + ) + _clip = _clip.with_position(("center", custom_y)) else: # center _clip = _clip.with_position(("center", "center")) diff --git a/app/services/task.py b/app/services/task.py index b798f66..c257d39 100644 --- a/app/services/task.py +++ b/app/services/task.py @@ -306,8 +306,8 @@ def start_subclip(task_id: str, params: VideoClipParams, subclip_path_videos: di output_video_path = path.join(utils.task_dir(task_id), f"combined.mp4") logger.info(f"\n\n## 6. 最后一步: 合并字幕/BGM/配音/视频 -> {output_video_path}") - bgm_path = '/Users/apple/Desktop/home/NarratoAI/resource/songs/bgm.mp3' - # bgm_path = params.bgm_file + # bgm_path = '/Users/apple/Desktop/home/NarratoAI/resource/songs/bgm.mp3' + bgm_path = utils.get_bgm_file() # 调用示例 options = { @@ -315,11 +315,12 @@ def start_subclip(task_id: str, params: VideoClipParams, subclip_path_videos: di 'bgm_volume': params.bgm_volume, # 背景音乐音量 'original_audio_volume': params.original_volume, # 视频原声音量,0表示不保留 'keep_original_audio': True, # 是否保留原声 - 'subtitle_font': 'MicrosoftYaHeiNormal.ttc', # 这里使用相对字体路径,会自动在 font_dir() 目录下查找 + 'subtitle_font': params.font_name, # 这里使用相对字体路径,会自动在 font_dir() 目录下查找 'subtitle_font_size': params.font_size, - 'subtitle_color': '#FFFFFF', + 'subtitle_color': params.text_fore_color, 'subtitle_bg_color': None, # 直接使用None表示透明背景 'subtitle_position': params.subtitle_position, + 'custom_position': params.custom_position, 'threads': params.n_threads } generate_video.merge_materials( diff --git a/webui/components/subtitle_settings.py b/webui/components/subtitle_settings.py index cb624dc..ee27985 100644 --- a/webui/components/subtitle_settings.py +++ b/webui/components/subtitle_settings.py @@ -127,7 +127,7 @@ def get_subtitle_params(): 'font_name': st.session_state.get('font_name', ''), 'font_size': st.session_state.get('font_size', 60), 'text_fore_color': st.session_state.get('text_fore_color', '#FFFFFF'), - 'position': st.session_state.get('subtitle_position', 'bottom'), + 'subtitle_position': st.session_state.get('subtitle_position', 'bottom'), 'custom_position': st.session_state.get('custom_position', 70.0), 'stroke_color': st.session_state.get('stroke_color', '#000000'), 'stroke_width': st.session_state.get('stroke_width', 1.5),