找回密码
 立即注册
查看: 469|回复: 8

[已解决] ASS子集化字体提取出来后在Windows下有可能无法打开

  • TA的每日心情
    开心
    2026-3-16 19:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    45

    回帖

    0

    VC币

    白金会员

    Rank: 12Rank: 12Rank: 12

    积分
    76365
    蒙太奇字幕组 发表于 2026-4-17 20:33:10 | 显示全部楼层 |阅读模式
    本帖最后由 蒙太奇字幕组 于 2026-4-20 16:41 编辑

    我是蒙太奇字幕组的小p。最近给之前开发的浏览器ASS字幕字体嵌入工具增加了新功能,包括子集化字幕预览和子集字体提取,方便排查问题。


    但现在遇到一个困扰的问题:


    问题现象:
    部分字体经过子集化后,播放器能正常加载,工具预览也没问题但提取出来的子集字体在Windows上双击打开时显示"这不是有效字体文件"


    有些字体可以正常打开,有些不行,不稳定。尝试过填充所有ASCII字符,有时还是失败暂时还没找到规律。子集化过程没有报错,播放器播放字幕时能加载这些子集字体,唯一的问题就是提取的TTF文件在Windows系统中有时无法打开,偶发现象。


    所以问题应该不是子集化本身的错误,而是提取的字体文件格式上可能有问题。


    请问各位有什么想法吗?如果提取的子集字体在Windows上点不开预览,这个提取功能就没什么实用价值了。

    原始表如下:

    1.     $ python font_diag.py "SourceHanSansSC-Medium.otf"
    2.     Diagnosing: SourceHanSansSC-Medium.otf
    3.     ------------------------------------------------------------
    4.     Platform   | Enc   | Lang   | ID   | Name String
    5.     ------------------------------------------------------------
    6.     3 (Win)    | 1     | 0x409  | 0    | © 2014-2025 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
    7.     3 (Win)    | 1     | 0x409  | 1    | Source Han Sans SC Medium
    8.     3 (Win)    | 1     | 0x804  | 1    | 思源黑体 Medium
    9.     3 (Win)    | 1     | 0x409  | 2    | Regular
    10.     3 (Win)    | 1     | 0x804  | 2    | Regular
    11.     3 (Win)    | 1     | 0x409  | 3    | 2.005;ADBO;SourceHanSansSC-Medium;ADOBE
    12.     3 (Win)    | 1     | 0x409  | 4    | Source Han Sans SC Medium
    13.     3 (Win)    | 1     | 0x804  | 4    | 思源黑体 Medium
    14.     3 (Win)    | 1     | 0x409  | 5    | Version 2.005;addfeatures 5.0.0b21
    15.     3 (Win)    | 1     | 0x409  | 6    | SourceHanSansSC-Medium
    16.     3 (Win)    | 1     | 0x409  | 7    | Source is a trademark of Adobe in the United States and/or other countries.
    17.     3 (Win)    | 1     | 0x409  | 8    | Adobe
    18.     3 (Win)    | 1     | 0x409  | 9    | Ryoko NISHIZUKA 西塚涼子 (kana, bopomofo & ideographs); Paul D. Hunt (Latin, Greek & Cyrillic); Sandoll Communications 산돌커뮤니케이션, Soo-young JANG 장수영 & Joo-yeon KANG 강주연 (hangul elements, letters & syllables)
    19.     3 (Win)    | 1     | 0x409  | 10   | Dr. Ken Lunde (project architect, glyph set definition & overall production); Masataka HATTORI 服部正貴 (production & ideograph elements); Zachary Quinn Scheuren (Variable font and overall production)
    20.     3 (Win)    | 1     | 0x409  | 11   | http://www.adobe.com/type/
    21.     3 (Win)    | 1     | 0x409  | 13   | This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.
    22.     3 (Win)    | 1     | 0x409  | 14   | http://scripts.sil.org/OFL
    23.     3 (Win)    | 1     | 0x409  | 16   | Source Han Sans SC
    24.     3 (Win)    | 1     | 0x804  | 16   | 思源黑体
    25.     3 (Win)    | 1     | 0x409  | 17   | Medium
    26.     3 (Win)    | 1     | 0x804  | 17   | Medium</span>
    复制代码


    新生成子集化字体表如下:
    1.     $ python font_diag.py "思源黑体 Medium_0.ttf"
    2.     Diagnosing: 思源黑体 Medium_0.ttf
    3.     ------------------------------------------------------------
    4.     Platform   | Enc   | Lang   | ID   | Name String
    5.     ------------------------------------------------------------
    6.     1 (Mac)    | 0     | 0x0    | 0    |
    7.     3 (Win)    | 1     | 0x409  | 0    |
    8.     0 (Uni)    | 4     | 0x0    | 1    | 思源黑体 Medium
    9.     3 (Win)    | 1     | 0x409  | 1    | 思源黑体 Medium
    10.     1 (Mac)    | 0     | 0x0    | 2    | Regular
    11.     3 (Win)    | 1     | 0x409  | 2    | Regular
    12.     0 (Uni)    | 4     | 0x0    | 3    |  :思源黑体 Medium Regular
    13.     3 (Win)    | 1     | 0x409  | 3    |  :思源黑体 Medium Regular
    14.     0 (Uni)    | 4     | 0x0    | 4    | 思源黑体 Medium Regular
    15.     3 (Win)    | 1     | 0x409  | 4    | 思源黑体 Medium Regular
    16.     1 (Mac)    | 0     | 0x0    | 5    | Version 0.1
    17.     3 (Win)    | 1     | 0x409  | 5    | Version 0.1
    18.     0 (Uni)    | 4     | 0x0    | 6    | 思源黑体MediumRegular
    19.     3 (Win)    | 1     | 0x409  | 6    | 思源黑体MediumRegular
    20.     1 (Mac)    | 0     | 0x0    | 7    |
    21.     3 (Win)    | 1     | 0x409  | 7    |
    22.     1 (Mac)    | 0     | 0x0    | 8    |
    23.     3 (Win)    | 1     | 0x409  | 8    |
    24.     1 (Mac)    | 0     | 0x0    | 9    |
    25.     3 (Win)    | 1     | 0x409  | 9    |
    26.     1 (Mac)    | 0     | 0x0    | 10   |
    27.     3 (Win)    | 1     | 0x409  | 10   |
    28.     1 (Mac)    | 0     | 0x0    | 11   |
    29.     3 (Win)    | 1     | 0x409  | 11   |
    30.     1 (Mac)    | 0     | 0x0    | 12   |
    31.     3 (Win)    | 1     | 0x409  | 12   |
    32.     1 (Mac)    | 0     | 0x0    | 13   |
    33.     3 (Win)    | 1     | 0x409  | 13   |
    34.     1 (Mac)    | 0     | 0x0    | 14   |
    35.     3 (Win)    | 1     | 0x409  | 14   |
    36.     0 (Uni)    | 4     | 0x0    | 16   | 思源黑体 Medium
    37.     3 (Win)    | 1     | 0x409  | 16   | 思源黑体 Medium
    38.     1 (Mac)    | 0     | 0x0    | 17   | Regular
    39.     3 (Win)    | 1     | 0x409  | 17   | Regular
    复制代码


    开发这个工具期间,开发的检查调试字体表的小python脚本,可以在这里看到:https://github.com/MontageSubs/ass-subset/issues/21#issuecomment-4227174736 我怀疑要么是缺少什么字符,要么是字体表不全,但是就是搞不懂具体原因是什么,到底是为什么?为什么有些转换的能点开有些点不开。

    希望大家帮忙指点一下可能是什么原因导致的。


    附件是生成的两个字体,字体虽然不同,但是表的填充逻辑是一样的,思源黑体_Medium打不开,Source_Han_Serif可打开,两个字体在播放器中都没有问题。

    思源黑体_Medium打不开,Source_Han_Serif可打开.zip

    285.58 KB, 下载次数: 7

    回复

    使用道具 举报

    该用户从未签到

    17

    主题

    117

    回帖

    0

    VC币

    中级会员

    Rank: 3Rank: 3

    积分
    12024
    QH7B 发表于 2026-4-20 12:13:06 | 显示全部楼层
    应该不是缺少字符的原因,因为使用FontCreator导出包含相同字符的字体文件,是可以正常打开的。
    我对比了一下几个文件的name表,发现思源黑体多了Unicode平台的记录,思源宋体和新导出的字体是没有的,不知道是不是因为这个。
    另外楼主提供的两个字体文件都是otf格式的,但不知为何扩展名却是ttf。

    评分

    参与人数 1活跃度 +1000 收起 理由
    蒙太奇字幕组 + 1000

    查看全部评分

    回复

    使用道具 举报

  • TA的每日心情
    开心
    2026-3-16 19:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    45

    回帖

    0

    VC币

    白金会员

    Rank: 12Rank: 12Rank: 12

    积分
    76365
    蒙太奇字幕组  楼主| 发表于 2026-4-20 16:40:57 | 显示全部楼层
    QH7B 发表于 2026-4-20 12:13
    应该不是缺少字符的原因,因为使用FontCreator导出包含相同字符的字体文件,是可以正常打开的。
    我对比了一 ...

    你好,我是蒙太奇字幕组的小p。非常感谢你帮忙排查,我花了近一周时间,昨天才把问题彻底解决。

    问题原因和影响:
    - 每个字体里都有一个 CFF CheckSum,用于校验字体完整性。我用的 opentype.js 在处理这个 CheckSum 时计算错误。这个错误并不会损坏字体内容,大多数播放器会忽略这个校验,仍然能正常加载字体。
    - 但 Windows 对校验比较严格:如果 CheckSum 错误,系统会判定字体“损坏”并阻止打开或安装。

    已采取的修复措施:
    1. 工具级绕过:在我的工具里不再依赖 opentype.js 的校验部分,改为自行计算并写入正确的 CFF CheckSum,保证生成的字体能通过 Windows 校验。
    2. 上游修复:已向 opentype.js 提交修复请求,等待官方合并,以便未来版本直接解决此问题(PR 链接: https://github.com/opentypejs/opentype.js/pull/830 )。

    额外收获:
    - 这次调试促使我完善了子集化工具生成的字体表结构,增加了更多信息,提升了兼容性和稳健性。

    关于 otf 被命名为 ttf 的疑问:
    那是因为我之前听说ass内部嵌入字体只能名为 ttf,否则 ass 会不识别。但是实际字体可以是其他格式,因为最终读取交给底层判断了,我没有验证是否是真的,所以沿用这种方法。

    点评

    libass 支持内嵌的字体是 otf,至于 vsfilter 系列的滤镜不用考虑兼容性,现在没人用那玩意作为参考  发表于 2026-4-21 06:43
    回复

    使用道具 举报

    该用户从未签到

    17

    主题

    117

    回帖

    0

    VC币

    中级会员

    Rank: 3Rank: 3

    积分
    12024
    QH7B 发表于 2026-4-27 12:55:36 | 显示全部楼层
    本帖最后由 QH7B 于 2026-4-27 12:58 编辑
    蒙太奇字幕组 发表于 2026-4-20 16:40
    你好,我是蒙太奇字幕组的小p。非常感谢你帮忙排查,我花了近一周时间,昨天才把问题彻底解决。

    问题原 ...

    感谢回复!

    试用了一下楼主的工具,感觉可以改进一下字体的嵌入,例如:
    1. [V4+ Styles]
    2. Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
    3. Style: Default,微软雅黑,50,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1

    4. [Events]
    5. Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
    6. Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,测试字幕{\b1\fnMicrosoft YaHei}test{\fnMicrosoft YaHei Bold}subtitle
    复制代码
    这里实际只用到了“微软雅黑 Bold”这一个字体文件,而楼主的工具却嵌入了三个字体。

    评分

    参与人数 1活跃度 +1000 收起 理由
    蒙太奇字幕组 + 1000 感谢你的贡献

    查看全部评分

    回复

    使用道具 举报

  • TA的每日心情
    开心
    2026-3-16 19:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    45

    回帖

    0

    VC币

    白金会员

    Rank: 12Rank: 12Rank: 12

    积分
    76365
    蒙太奇字幕组  楼主| 发表于 2026-4-27 14:59:08 | 显示全部楼层
    本帖最后由 蒙太奇字幕组 于 2026-4-27 15:31 编辑
    QH7B 发表于 2026-4-27 12:55
    感谢回复!

    试用了一下楼主的工具,感觉可以改进一下字体的嵌入,例如:

    你好,感谢你的详细测试用例!

    这个现象是符合预期的,原因在于字幕里明确指定了三个不同的字体名称:
    1. [V4+ Styles] 中的 微软雅黑
    2. Dialogue 行内 \fn 标签指定的 Microsoft YaHei
    3. 以及 Microsoft YaHei Bold
    复制代码

    虽然这三个名字在操作系统层面指向同一个字体家族,但系统字体匹配机制是严格按名字字符串查询的,"微软雅黑"和"Microsoft YaHei"对它来说是两个完全不同的查找请求,各自需要一个匹配的字体才能正确渲染。因此工具嵌入了三个字体,是忠实于字幕原始内容的正确行为。

    能不能把多个名字都写入同一个字体文件来合并?我测试过,效果不理想,不同平台的字体 API(GDI、DirectWrite、fontconfig)在读取嵌入字体的 name table 时行为不一致,并不能保证所有名字都被正确识别,稳定性无法保证。

    举个实际的例子:你的 Windows 系统是中文的,字幕里同时指定了"思源宋体"和"Source Han Serif SC",这两个名字内部都指向同一个字体文件,但系统只会暴露当前语言对应的那个 family name。结果很可能是"Source Han Serif SC"无法被渲染,如果你是非中文系统,则大概率"思源宋体"没有被识别(测试时要用第三方字体,别用微软雅黑,因为它是默认回退字体,会掩盖测试效果)

    另一个思路是在转换时自动统一字幕内字体名,比如把"Microsoft YaHei"统一替换成"微软雅黑"。但我不希望工具对字幕内容做这类修改,字幕创作者写了什么名字,工具就应该忠实对待,而不是自作聪明地帮人家改名。

    如果希望减少嵌入字体数量,最直接的方式是在字幕源文件中统一字体名称的写法。


    如果想继续讨论,欢迎移步原帖 :)

    https://bbs.acgrip.com/thread-13556-1-1.html

    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 00:34
  • 签到天数: 795 天

    [LV.10]以坛为家III

    20

    主题

    168

    回帖

    20

    VC币

    至尊会员

    Rank: 16Rank: 16Rank: 16Rank: 16

    积分
    249221
    op200 发表于 2026-4-27 15:19:37 | 显示全部楼层
    蒙太奇字幕组 发表于 2026-4-27 14:59
    你好,感谢你的详细测试用例!

    这个现象是符合预期的,原因在于字幕里明确指定了三个不同的字体名称:

    Snipaste_2026-04-27_15-18-18.png
    这两个家族名显然是同一个字体文件中有不同家族名,并不是两个不同的字体文件,子集化时不要丢弃家族名即可解决
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2026-3-16 19:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    45

    回帖

    0

    VC币

    白金会员

    Rank: 12Rank: 12Rank: 12

    积分
    76365
    蒙太奇字幕组  楼主| 发表于 2026-4-27 15:30:35 | 显示全部楼层
    本帖最后由 蒙太奇字幕组 于 2026-4-27 15:32 编辑
    op200 发表于 2026-4-27 15:19
    这两个家族名显然是同一个字体文件中有不同家族名,并不是两个不同的字体文件,子集化时不要丢弃家族名 ...

    感谢回复与指正,我刚刚也意识到了,我的测试和回复,不正确,那个测试案例和子集化不同,那个测试案例直接走了系统的 GDI/DirectWrite,和 libass 走 FreeType 是不同的。

    我检查了下 libass 行为,具体如下:

    嵌入字体走的路径是:libass 用 FreeType 打开字体数据 → 调用 get_font_info 读取 name table → 注册进内部字体数据库。
    get_font_info 里有段代码:
    1. cif (name.platform_id == TT_PLATFORM_MICROSOFT &&
    2.     (name.name_id == TT_NAME_ID_FULL_NAME ||
    3.      name.name_id == TT_NAME_ID_FONT_FAMILY)) {
    4.     // 转换编码后存入 families[] 或 fullnames[]
    5. }
    复制代码
    它遍历 name table 里所有 TT_PLATFORM_MICROSOFT 平台的 family name 条目,不做语言过滤,全部收进 families[] 数组(上限 100 个)。
    也就是说,嵌入字体的多语言 family name 会被全部读取,"思源宋体"和"Source Han Serif SC"如果都写在 name table 里,libass 都能看到,并且都会注册进数据库供匹配。

    所以 @QH7B 指出的确实是一个 bug,这就开始修

    回复

    使用道具 举报

  • TA的每日心情
    开心
    2026-3-16 19:59
  • 签到天数: 1 天

    [LV.1]初来乍到

    3

    主题

    45

    回帖

    0

    VC币

    白金会员

    Rank: 12Rank: 12Rank: 12

    积分
    76365
    蒙太奇字幕组  楼主| 发表于 2026-4-27 16:36:18 | 显示全部楼层
    本帖最后由 蒙太奇字幕组 于 2026-4-27 16:38 编辑

    非常感谢两位 2.6.19 版本已经修复该问题
    @QH7B  @op200

    具体可见:https://bbs.acgrip.com/forum.php ... id=13556&pid=119368

    非常感谢 @QH7B 汇报,微软雅黑和 Microsoft YaHei 会生成不同字体的问题其实归根结底就是我对子集化字体的原理理解得不够透彻,设计得有点问题。说得好听是设计缺陷,说得直白就是我脑子里的 bug 哈哈哈。

    也非常感谢 @op200 及时指正。

    现在 2.6.19 版本已经把这事搞定了,生成的日志看起来是酱紫的:
    • [font] 「微软雅黑」与 1 个别名 [Microsoft YaHei] 共享同一字体文件,合并为单次嵌入。
    • [font] 正在处理「微软雅黑」(常规,7 字符)...
    • [font] 「微软雅黑」(常规): 19240 KB → 10 KB(缩减 100%)
    • [font] 正在处理「Microsoft YaHei Bold」(常规,7 字符)...
    • [font] 「Microsoft YaHei Bold」(常规): 16485 KB → 5 KB(缩减 100%)
    • [ass] 重写字幕文件...
    • [done] 完成。1 KB → 21 KB(20.7 KB)

    打开工具刷新页面,确保右下角版本号大于 2.6.19 就能看到修复效果了。再次感谢两位的反馈,有你们的帮助这个项目才能越来越完善,真的感激不尽。


    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表