diff --git a/config.py b/config.py index 9d741e4..cc371ce 100644 --- a/config.py +++ b/config.py @@ -123,14 +123,21 @@ DB_CONNECTION_STRING = os.getenv("DB_CONNECTION_STRING", f"sqlite:///{BASE_DIR}/ # ============================================================ # 优先检测系统字体,防止乱码 SYSTEM_FONTS = [ - str(FONTS_DIR / "SmileySans-Oblique.otf"), + # 项目内置字体 (跨平台通用,优先使用) + str(FONTS_DIR / "NotoSansSC-Regular.otf"), str(FONTS_DIR / "HarmonyOS-Sans-SC-Regular.ttf"), str(FONTS_DIR / "HarmonyOS-Sans-SC-Bold.ttf"), - str(FONTS_DIR / "NotoSansSC-Regular.otf"), str(FONTS_DIR / "NotoSansSC-Bold.otf"), + str(FONTS_DIR / "SmileySans-Oblique.otf"), + # Linux 系统字体 + "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", + "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", + # macOS 系统字体 "/System/Library/Fonts/PingFang.ttc", "/System/Library/Fonts/STHeiti Medium.ttc", - "/System/Library/Fonts/Supplemental/Arial Unicode.ttf", + # Windows 系统字体 + "C:/Windows/Fonts/msyh.ttc", + "C:/Windows/Fonts/simhei.ttf", ] DEFAULT_FONT = str(FONTS_DIR / "NotoSansSC-Regular.otf") @@ -141,7 +148,8 @@ def pick_font(): for f in SYSTEM_FONTS: if os.path.exists(f) and os.path.getsize(f) > 1000: return f - return "/System/Library/Fonts/PingFang.ttc" + # 极端情况回退到 Arial (所有平台都有) + return "Arial" DEFAULT_FONT = pick_font() DEFAULT_FONT_BOLD = DEFAULT_FONT diff --git a/main_flow.py b/main_flow.py index 4b4744f..ee7b0d5 100644 --- a/main_flow.py +++ b/main_flow.py @@ -107,7 +107,7 @@ def get_demo_data() -> tuple: } # 原始图片路径 - base_image_dir = Path("/Volumes/Tony/video-flow/素材/发夹/原始稿") + base_image_dir = config.BASE_DIR / "素材" / "发夹" / "原始稿" original_images = [ str(base_image_dir / "主图1.png"), str(base_image_dir / "主图2.png"), diff --git a/modules/composer.py b/modules/composer.py index f0f6a01..16da810 100644 --- a/modules/composer.py +++ b/modules/composer.py @@ -146,7 +146,7 @@ class VideoComposer: style=style if isinstance(style, str) else "subtitle", custom_style={ **(custom_style or {}), - "font_name": "/System/Library/Fonts/PingFang.ttc", + "font_name": config.DEFAULT_FONT, }, cache=False ) @@ -156,7 +156,7 @@ class VideoComposer: text=text, style=style if isinstance(style, str) else "subtitle", custom_style={ - "font_name": "/System/Library/Fonts/PingFang.ttc", + "font_name": config.DEFAULT_FONT, }, cache=False ) @@ -662,7 +662,7 @@ def quick_compose( def example_hairclip_video(): """示例:发夹商品视频合成""" - 素材目录 = Path("/Volumes/Tony/video-flow/素材/发夹/合成图拆分镜") + 素材目录 = config.BASE_DIR / "素材" / "发夹" / "合成图拆分镜" video_paths = [ str(素材目录 / "视频-分镜1.mp4"), @@ -706,7 +706,7 @@ def example_hairclip_video(): output = quick_compose( video_folder=str(素材目录), script=script, - output_path="/Volumes/Tony/video-flow/output/发夹_合成视频.mp4", + output_path=str(config.OUTPUT_DIR / "发夹_合成视频.mp4"), voice_type="sweet_female" ) diff --git a/modules/factory.py b/modules/factory.py index aa734f8..8643f06 100644 --- a/modules/factory.py +++ b/modules/factory.py @@ -473,7 +473,7 @@ def generate_voiceover_volcengine_ws( ) -> str: """ 使用火山 WebSocket Binary Demo 生成 TTS 音频 - 依赖目录:/Volumes/Tony/video-flow/volcengine_binary_demo/.venv/bin/python + 依赖目录:{PROJECT_ROOT}/volcengine_binary_demo/.venv/bin/python """ if not text or not text.strip(): logger.warning("Empty text provided for TTS (ws)") @@ -481,8 +481,10 @@ def generate_voiceover_volcengine_ws( voice_id = VOLC_TTS_VOICES.get(voice_type, voice_type) - venv_python = Path("/Volumes/Tony/video-flow/volcengine_binary_demo/.venv/bin/python") - demo_script = Path("/Volumes/Tony/video-flow/volcengine_binary_demo/examples/volcengine/binary.py") + # 跨平台路径:使用项目根目录相对路径 + volc_demo_dir = config.BASE_DIR / "volcengine_binary_demo" + venv_python = volc_demo_dir / ".venv" / "bin" / "python" + demo_script = volc_demo_dir / "examples" / "volcengine" / "binary.py" if not venv_python.exists() or not demo_script.exists(): logger.error("Volcengine WS demo or venv not found. Please install under volcengine_binary_demo/.venv") @@ -505,7 +507,7 @@ def generate_voiceover_volcengine_ws( try: result = subprocess.run( cmd, - cwd="/Volumes/Tony/video-flow/volcengine_binary_demo", + cwd=str(volc_demo_dir), capture_output=True, text=True, timeout=timeout, @@ -515,7 +517,7 @@ def generate_voiceover_volcengine_ws( return "" # demo 保存在 cwd 下 voice_type.mp3 - demo_out = Path("/Volumes/Tony/video-flow/volcengine_binary_demo") / f"{voice_id}.mp3" + demo_out = volc_demo_dir / f"{voice_id}.mp3" if not demo_out.exists(): logger.error("Volc WS TTS output not found") return "" diff --git a/modules/ffmpeg_utils.py b/modules/ffmpeg_utils.py index 79d3593..5d8c591 100644 --- a/modules/ffmpeg_utils.py +++ b/modules/ffmpeg_utils.py @@ -18,20 +18,25 @@ logger = logging.getLogger(__name__) FFMPEG_PATH = str(config.BASE_DIR / "bin" / "ffmpeg") if (config.BASE_DIR / "bin" / "ffmpeg").exists() else "ffmpeg" FFPROBE_PATH = str(config.BASE_DIR / "bin" / "ffprobe") if (config.BASE_DIR / "bin" / "ffprobe").exists() else "ffprobe" -# 字体路径优先使用项目自带中文字体,其次使用 Linux 系统字体,最后再回退到 macOS 路径 +# 字体路径:优先使用项目内置字体,然后按平台回退到系统字体 DEFAULT_FONT_PATHS = [ - # 优先使用 Linux 系统级中文字体 (服务器环境最稳健) - "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", - "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", - - # 项目内字体 (注意:需确保文件不是 LFS 指针) + # 优先使用项目内置字体 (跨平台通用) + str(config.FONTS_DIR / "NotoSansSC-Regular.otf"), str(config.FONTS_DIR / "HarmonyOS-Sans-SC-Regular.ttf"), str(config.FONTS_DIR / "AlibabaPuHuiTi-Regular.ttf"), - # macOS 字体(仅本地调试生效) + # Linux 系统字体 + "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", + "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", + "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc", + + # macOS 系统字体 "/System/Library/Fonts/PingFang.ttc", "/System/Library/Fonts/STHeiti Medium.ttc", - "/System/Library/Fonts/Supplemental/Arial Unicode.ttf", + + # Windows 系统字体 + "C:/Windows/Fonts/msyh.ttc", + "C:/Windows/Fonts/simhei.ttf", ] @@ -495,12 +500,8 @@ def add_multiple_subtitles( return output_path default_style = default_style or {} - # 强制使用完整字体(先用项目内 NotoSansSC,如果不存在则回退 Droid) - font = "/root/video-flow/assets/fonts/NotoSansSC-Regular.otf" - if not (os.path.exists(font) and os.path.getsize(font) > 1024 * 100): # 至少100KB以上认为有效 - font = "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf" - if not (os.path.exists(font) and os.path.getsize(font) > 1024 * 100): - font = _get_font_path() + # 使用统一的字体查找逻辑(跨平台兼容) + font = _get_font_path() print(f"[SubDebug] Using font for subtitles: {font}", flush=True)