Enable Complex Text Layout with FriBidi in FFmpeg

Rendering scripts such as Arabic, Hebrew, Persian, or Devanagari in FFmpeg requires Complex Text Layout (CTL) and bidirectional (BiDi) text processing to properly shape glyphs and order characters. This guide outlines how to build FFmpeg with libfribidi and libharfbuzz enabled and how to apply these features using the drawtext filter to ensure complex and right-to-left scripts render correctly.

1. Install Required Development Libraries

FriBidi handles bidirectional layout and character reordering, while HarfBuzz performs the actual glyph shaping (ligatures, contextual forms). Both libraries work together inside FFmpeg's drawtext filter.

On Debian/Ubuntu:

sudo apt-get update
sudo apt-get install -y libfreetype6-dev libfribidi-dev libharfbuzz-dev

On Fedora/RHEL:

sudo dnf install -y freetype-devel fribidi-devel harfbuzz-devel

On macOS (via Homebrew):

brew install freetype fribidi harfbuzz

2. Configure and Compile FFmpeg

To enable bidirectional and CTL support, pass --enable-libfribidi, --enable-libharfbuzz, and --enable-libfreetype to the configure script when building FFmpeg from source:

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg

./configure \
  --enable-gpl \
  --enable-libfreetype \
  --enable-libfribidi \
  --enable-libharfbuzz

make -j$(nproc)
sudo make install

3. Verify FriBidi and HarfBuzz Support

After the compilation finishes, verify that the configuration flags are active by checking the build configuration:

ffmpeg -buildconf

Confirm that --enable-libfribidi and --enable-libharfbuzz are present in the output.

4. Apply CTL and BiDi Text Using drawtext

When FFmpeg is compiled with both libfribidi and libharfbuzz, the drawtext filter automatically handles character reordering and complex glyph shaping. You must provide a TrueType or OpenType font that contains the appropriate glyphs and OpenType shaping tables for your target language.

Example command to overlay Arabic or Hebrew text onto a video:

ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/suitable-font.ttf:text='مرحبا بالعالم':fontcolor=white:fontsize=36:x=(w-text_w)/2:y=h-text_h-50" -codec:a copy output.mp4

For external text files, specify the file path while ensuring the file is saved with UTF-8 encoding:

ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/suitable-font.ttf:textfile=subtitles.txt:fontcolor=white:fontsize=32:x=(w-text_w)/2:y=h-100" -codec:a copy output.mp4

5. Alternative: Subtitle Rendering via libass

If you are burning complex subtitle files (such as .ass or .srt), compile FFmpeg with --enable-libass. The libass library internally relies on libfribidi and libharfbuzz for subtitle shaping and layout:

ffmpeg -i input.mp4 -vf "subtitles=subtitles.srt" -codec:a copy output.mp4