diff --git a/infra/docker/api-base.Dockerfile b/infra/docker/api-base.Dockerfile index 5e8dc62dd..c9e6938e3 100644 --- a/infra/docker/api-base.Dockerfile +++ b/infra/docker/api-base.Dockerfile @@ -12,8 +12,9 @@ RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debia sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true # 预装系统依赖(gcc 编译 psycopg/pg 扩展,libpq-dev 编译期,libpq5 运行期,ffmpeg 封面取帧) -# 字体修复:fonts-noto-cjk 包的 .ttc 文件混入了 Mono 变体,导致 Bold 匹配到等宽字体 -# 解决方案:删除有问题的 .ttc,使用仓库内预下载的 Noto Sans SC Variable Font(不含 Mono) +# 字体修复:fonts-noto-cjk 包的 Sans .ttc 文件混入了 Mono 变体,导致 Bold 匹配到等宽字体 +# 解决方案:删除 Sans .ttc,保留 Serif .ttc;仓库内预下载 VF 可变字体(不含 Mono) +# #1896 补充开源字体:NotoSerifCJKsc-VF.otf(思源宋体)、LXGWWenKai-Regular.ttf(霞鹜文楷开源楷体) RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libpq-dev \ @@ -21,12 +22,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg \ fonts-noto-cjk \ && rm -rf /var/lib/apt/lists/* \ - # 删除有问题的 .ttc 文件(包含 Mono 变体) + # 删除有问题的 Sans .ttc(含 Mono 变体),保留 Serif .ttc 作为宋体 fallback && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc \ - && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc + && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc \ + && mkdir -p /usr/share/fonts/truetype/lxgw -# 复制预下载的 Noto Sans SC Variable Font(包含所有字重,不含 Mono 变体) +# 复制开源中文字体:思源黑体 VF + 思源宋体 VF(#1896)+ 霞鹜文楷(#1896,开源楷体) COPY infra/fonts/NotoSansSC-VF.ttf /usr/share/fonts/opentype/noto/NotoSansSC-VF.ttf +COPY infra/fonts/NotoSerifCJKsc-VF.otf /usr/share/fonts/opentype/noto/NotoSerifCJKsc-VF.otf +COPY infra/fonts/LXGWWenKai-Regular.ttf /usr/share/fonts/truetype/lxgw/LXGWWenKai-Regular.ttf RUN fc-cache -fv # 创建虚拟环境 diff --git a/infra/docker/worker-base.Dockerfile b/infra/docker/worker-base.Dockerfile index 38a4a62f8..9a358ab2e 100644 --- a/infra/docker/worker-base.Dockerfile +++ b/infra/docker/worker-base.Dockerfile @@ -12,8 +12,11 @@ RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debia sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true # 预装系统依赖(编译工具 + 运行时 + CJK 字体用于 ASS 字幕渲染) -# 字体修复:fonts-noto-cjk 包的 .ttc 文件混入了 Mono 变体,导致 Bold 匹配到等宽字体 -# 解决方案:删除有问题的 .ttc,使用仓库内预下载的 Noto Sans SC Variable Font(不含 Mono) +# 字体修复:fonts-noto-cjk 包的 Sans .ttc 文件混入了 Mono 变体,导致 Bold 匹配到等宽字体 +# 解决方案:删除 Sans .ttc,保留 Serif .ttc(宋体 fallback);仓库内预下载 VF 可变字体(不含 Mono) +# #1896 补充开源字体:NotoSerifCJKsc-VF.otf(思源宋体衬线)、LXGWWenKai-Regular.ttf(霞鹜文楷开源楷体,SIL OFL) +# - 苹方/微软雅黑为 macOS/Windows 系统字体,服务器无对应文件,映射到 Noto Sans SC fallback +# - 华康俪金黑为商业字体有版权风险,前端已移除,后端映射到 Noto Sans SC 兼容老数据 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ g++ \ @@ -23,12 +26,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libglib2.0-0 \ fonts-noto-cjk \ && rm -rf /var/lib/apt/lists/* \ - # 删除有问题的 .ttc 文件(包含 Mono 变体) + # 删除有问题的 Sans .ttc 文件(包含 Mono 变体会导致粗体匹配错误),保留 Serif .ttc 作为宋体 fallback && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc \ - && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc + && rm -f /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc \ + && mkdir -p /usr/share/fonts/truetype/lxgw -# 复制预下载的 Noto Sans SC Variable Font(包含所有字重,不含 Mono 变体) +# 复制开源中文字体:思源黑体 VF + 思源宋体 VF(#1896)+ 霞鹜文楷(#1896,开源楷体) COPY infra/fonts/NotoSansSC-VF.ttf /usr/share/fonts/opentype/noto/NotoSansSC-VF.ttf +COPY infra/fonts/NotoSerifCJKsc-VF.otf /usr/share/fonts/opentype/noto/NotoSerifCJKsc-VF.otf +COPY infra/fonts/LXGWWenKai-Regular.ttf /usr/share/fonts/truetype/lxgw/LXGWWenKai-Regular.ttf RUN fc-cache -fv # 创建虚拟环境 diff --git a/infra/fonts/LXGWWenKai-Regular.ttf b/infra/fonts/LXGWWenKai-Regular.ttf new file mode 100644 index 000000000..3e050e87c Binary files /dev/null and b/infra/fonts/LXGWWenKai-Regular.ttf differ diff --git a/infra/fonts/NotoSerifCJKsc-VF.otf b/infra/fonts/NotoSerifCJKsc-VF.otf new file mode 100644 index 000000000..7b838c0c6 Binary files /dev/null and b/infra/fonts/NotoSerifCJKsc-VF.otf differ diff --git a/packages/domain/ass_subtitle_builder.py b/packages/domain/ass_subtitle_builder.py index d45bf5642..a6e469dba 100755 --- a/packages/domain/ass_subtitle_builder.py +++ b/packages/domain/ass_subtitle_builder.py @@ -25,13 +25,20 @@ TITLE_MARGIN_BOTTOM = 100 TITLE_MARGIN_SIDE = 40 # 字体名称映射:前端中文字体名 → 服务器实际注册名(ffmpeg/ASS 通过注册名匹配字体) +# #1896 字体映射修复:每个字体映射到独立的注册名,而非全部回退到 Noto Sans SC +# - 思源宋体 → Noto Serif CJK SC(fonts-noto-cjk 包预装 + VF.otf) +# - 楷体 → LXGW WenKai(霞鹜文楷,#1896 新增 SIL OFL 开源楷体) +# - 苹方/PingFang/微软雅黑:服务器 Linux 无对应字体,fallback 思源黑体 +# - 华康俪金黑:商业字体有版权风险,前端已移除,后端保留映射 fallback 思源黑体(兼容老数据) FONT_NAME_MAP: dict[str, str] = { "思源黑体": "Noto Sans SC", "思源宋体": "Noto Serif CJK SC", "苹方": "Noto Sans SC", "PingFang": "Noto Sans SC", "微软雅黑": "Noto Sans SC", - "楷体": "Noto Serif CJK SC", + "Microsoft YaHei": "Noto Sans SC", + "楷体": "LXGW WenKai", + "霞鹜文楷": "LXGW WenKai", "华康俪金黑": "Noto Sans SC", } diff --git a/packages/domain/video_filter_builder.py b/packages/domain/video_filter_builder.py index 91f82959f..2dd2edf95 100755 --- a/packages/domain/video_filter_builder.py +++ b/packages/domain/video_filter_builder.py @@ -378,12 +378,16 @@ def _append_audio_concat(parts: list[str], clip_chains: list[ClipFilterChain]) - # ── 标题 drawtext 滤镜构建(#1789)───────────────────────────────────────────── # drawtext 字体搜索路径:按优先级从高到低排列 -# 服务器使用 Noto Sans SC(思源黑体)作为默认字体。 -# - NotoSansSC-VF.ttf 是 worker-base.Dockerfile 中 COPY 的 VF 字体(含所有字重,无 Mono 变体),优先级最高 -# - .ttc 系列为 fonts-noto-cjk 包预装字体(Dockerfile 已删除含 Mono 变体的旧 .ttc,存在时作为 fallback) +# #1896 字体映射修复: +# - NotoSansSC-VF.ttf:思源黑体(VF 可变字体,含所有字重),worker-base.Dockerfile COPY +# - NotoSerifCJKsc-VF.otf:思源宋体(VF 可变字体),#1896 新增,衬线字体 +# - LXGWWenKai-Regular.ttf:霞鹜文楷(开源楷体,SIL OFL),#1896 新增 +# - fonts-noto-cjk 预装 .ttc 作为 fallback(Dockerfile 已删除含 Mono 变体的文件) # - DejaVuSans 仅含拉丁字符不支持中文,已移除 DRAWTEXT_FONT_SEARCH_PATHS: list[str] = [ "/usr/share/fonts/opentype/noto/NotoSansSC-VF.ttf", + "/usr/share/fonts/opentype/noto/NotoSerifCJKsc-VF.otf", + "/usr/share/fonts/truetype/lxgw/LXGWWenKai-Regular.ttf", "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", "/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc", "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc", @@ -393,13 +397,18 @@ DRAWTEXT_FONT_SEARCH_PATHS: list[str] = [ ] # 前端字体名 → drawtext 字体搜索关键字(匹配 DRAWTEXT_FONT_SEARCH_PATHS 中的文件名关键字) +# #1896 字体映射修复:每个字体映射到独立的关键字,而非全部回退到 NotoSansSC +# - 苹方(macOS)/ 微软雅黑(Windows)/ PingFang:服务器 Linux 无对应文件,fallback 思源黑体 +# - 华康俪金黑:商业字体有版权风险,前端已按 #1896 要求移除,后端保留映射但 fallback 思源黑体(兼容老数据) DRAWTEXT_FONT_MAP: dict[str, str] = { "思源黑体": "NotoSansSC", - "思源宋体": "NotoSerifCJK", + "思源宋体": "NotoSerifCJKsc", "苹方": "NotoSansSC", "PingFang": "NotoSansSC", "微软雅黑": "NotoSansSC", - "楷体": "NotoSerifCJK", + "Microsoft YaHei": "NotoSansSC", + "楷体": "LXGWWenKai", + "霞鹜文楷": "LXGWWenKai", "华康俪金黑": "NotoSansSC", } @@ -479,9 +488,7 @@ def build_title_drawtext_filter( return None # 字段名归一化:兼容 content/text/title 三套命名 - text = ( - title_config.get("text") or title_config.get("content") or title_config.get("title") or "" - ).strip() + text = (title_config.get("text") or title_config.get("content") or title_config.get("title") or "").strip() if not text: return None