在macOS上为mpv启用Fontconfig支持以解决若干字体问题

前言

对视频播放有所研究的朋友应该都对mpv这个功能丰富，配置灵活的播放器不陌生，其中的Conditional auto profiles功能甚得我心，比如说你可以通过下面的配置实现不同语言的字幕使用不同的字体：

Copy
[zh-Hans]
profile-cond=string.sub(get("current-tracks/sub/lang"), 1, 7) == "zh-Hans"
sub-font='Source Han Sans SC'

[zh-Hant]
profile-cond=string.sub(get("current-tracks/sub/lang"), 1, 7) == "zh-Hant"
sub-font='Source Han Sans HC'

mpv 同时也是许多其他播放器的内置模块，比如IINA和Jellyfin Media Player，这两个播放器也支持自定义的 mpv 配置。

关于 mpv 的更多配置项，可参考VCB-S 的入门教程。

问题

mpv 使用libass渲染 SRT 等纯文本字体，而 libass 在 macOS 上默认使用 CoreText 作为 font provider 读取字体，这带来了一些问题。

首先是可变字体，libass 只能读取到最细的样式，--sub-bold=yes参数也无法生效（测试了 Noto Sans CJK 系列和 Fira Code 都是如此）。

其次是字幕中的 Emoji，libass 无法显示，我猜是因为 fallback 到了一个彩色的 Emoji 字体，而 libass 只支持单色（monochrome）字体（相关 issue）。

查阅了资料发现 libass 在 Linux 上使用的 Fontconfig 也是支持 macOS 的，而 Fontconfig 有着丰富的自定义配置功能。抱着死马当活马医的想法，我试了试用 Fontconfig 替换掉 CoreText，结果确实可以解决上述两个问题。

实操

以下使用 Homebrew 安装启用 Fontconfig 支持的 libass。

首先安装 Fontconfig：

Copy
brew install fontconfig

Homebrew 上的 libass 默认是不会在 macOS 上启用 Fontconfig 的，我们需要先修改编译脚本。

最新版的 Homebrew 默认使用 API 的方式获取安装脚本，而不是克隆 tap 仓库，这会导致对安装脚本的修改无法生效，这里先暂时禁用 API 模式。

Copy
export HOMEBREW_NO_INSTALL_FROM_API=1
brew update

Copy
brew edit libass

把 formula code 里 fontconfig 相关的 Linux 条件删除，再删除--disable-fontconfig参数，然后重新从源码安装 libass：

Copy
brew reinstall --build-from-source libass

到这一步 Homebrew 安装的 mpv 已经可以使用--sub-font-provider=fontconfig参数来启用 Fontconfig 了。

修改~/.config/fontconfig/fonts.conf，将 mpv 中使用的字体名设置为一系列字体的别名，就可以自定义 fallback 顺序了：

Copy
<?xml version="1.0"?>

<fontconfig>
<include ignore_missing="yes">/opt/homebrew/etc/fonts/fonts.conf</include>

<alias>
<family>Source Han Sans HC</family>
<prefer>
<family>Noto Sans CJK HK</family>
<family>Noto Emoji</family>
</prefer>
</alias>
</fontconfig>

这里使用的是 monochrome 的 Emoji 字体Noto Emoji。

最后，IINA 和 Jellyfin Media Player 使用的是自带的 libmpv 和 libass，需要使用/opt/homebrew/lib/libass.9.dylib替换掉各自包内的libass.9.dylib。

本文章发布在以下多个网站：
GitHub Pages
xLog