Keo

Keo

steam_profiles
github

Enable Fontconfig support for mpv on macOS to resolve several font issues

Introduction#

Friends who have researched video playback should be familiar with mpv, a feature-rich and flexible player. The Conditional auto profiles feature is particularly appealing to me. For example, you can achieve different fonts for subtitles in different languages with the following configuration:

[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 is also a built-in module for many other players, such as IINA and Jellyfin Media Player, both of which support custom mpv configurations.

For more configuration options for mpv, refer to VCB-S's introductory tutorial.

Issues#

mpv uses libass to render SRT and other plain text fonts, while libass defaults to using CoreText as the font provider on macOS, which brings some issues.

First, for variable fonts, libass can only read the thinnest style, and the --sub-bold=yes parameter does not take effect (this is the case for both the Noto Sans CJK series and Fira Code).

Secondly, emojis in subtitles cannot be displayed by libass. I suspect this is because it falls back to a color emoji font, while libass only supports monochrome fonts (related issue).

After researching, I found that the Fontconfig used by libass on Linux is also supported on macOS, and Fontconfig has rich customization features. With a "desperate times call for desperate measures" mindset, I tried replacing CoreText with Fontconfig, and it indeed resolved the two issues mentioned above.

Practical Steps#

The following uses Homebrew to install libass with Fontconfig support.

First, install Fontconfig:

brew install fontconfig

The default libass on Homebrew does not enable Fontconfig on macOS, so we need to modify the compilation script first.

The latest version of Homebrew defaults to using the API method to obtain installation scripts instead of cloning the tap repository, which prevents modifications to the installation scripts from taking effect. Here, we temporarily disable API mode.

export HOMEBREW_NO_INSTALL_FROM_API=1
brew update
brew edit libass

Remove the Linux conditions related to fontconfig from the formula code, then delete the --disable-fontconfig parameter, and reinstall libass from source:

brew reinstall --build-from-source libass

At this point, the mpv installed by Homebrew can use the --sub-font-provider=fontconfig parameter to enable Fontconfig.

Modify ~/.config/fontconfig/fonts.conf to set the font names used in mpv as aliases for a series of fonts, allowing you to customize the fallback order:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "/opt/homebrew/share/xml/fontconfig/fonts.dtd">
<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>

Here, the monochrome emoji font used is Noto Emoji.

Finally, IINA and Jellyfin Media Player use their own libmpv and libass, so you need to replace libass.9.dylib in their respective packages with /opt/homebrew/lib/libass.9.dylib.


This article is published on several websites:
GitHub Pages
xLog (comments allowed)

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.