Skip to content

Prebuilt FFmpeg archive is pinned to libx264 ABI 163 and fails to link on rolling distros (system x264 is 165) #192

Open

Description

@AlonsoSG0

Summary

On x86_64 Linux, a freshly generated project fails to link with the default h264 feature enabled:

rust-lld: error: undefined symbol: x264_encoder_open_163
  >>> referenced by libx264.c:1406 (libavcodec/libx264.c:1406)
  >>>               libx264.o:(X264_init) in archive .../libffmpeg_sys_fframes-....rlib
  >>> did you mean: x264_encoder_open_165
  >>> defined in: /usr/lib/libx264.so

The prebuilt FFmpeg archive is compiled against libx264 ABI 163, but -lx264 is resolved from the system, which on a rolling distro may already be ABI 165. Because x264 bakes its ABI version into the exported symbol name, the mismatch is a hard link error, and there is no user-side knob to resolve it — the prebuilt archive is simply older than the current system x264.

Environment

OS Arch Linux (rolling)
rustc 1.97.1
fframes 1.2.0
cargo-fframes 1.2.0
ffmpeg-sys-fframes 9.0.0 (prebuilt tag binaries-9.0.0)
system x264 x264 3:0.165.r3222.b35605a-2 → X264_BUILD 165
system ffmpeg ffmpeg 2:9.0.2-2

Steps to reproduce

cargo install --locked cargo-fframes --git https://github.com/dmtrKovalenko/fframes

cargo fframes new hello-world \
  --template single-scene \
  --format landscape \
  --backend skia-vulkan \
  --title "Hello"

cd hello-world
cargo build --release

Expected

The project links, and render writes out.mp4.

Actual

Link failure:

error: linking with `cc` failed: exit status: 1
  = note: rust-lld: error: undefined symbol: x264_encoder_open_163
          >>> referenced by libx264.c:1406 (libavcodec/libx264.c:1406)
          >>>               libx264.o:(X264_init) in archive /…/libffmpeg_sys_fframes-e6f133740cb79c29.rlib
          >>> did you mean: x264_encoder_open_165
          >>> defined in: /usr/lib/libx264.so
          collect2: error: ld returned 1 exit status

Note that the final link line contains both the prebuilt search path (.../ffmpeg-sys-fframes-.../out/dist/lib) and -lx264, which resolves to /usr/lib/libx264.so.

Root cause

ffmpeg-sys-fframes downloads a prebuilt FFmpeg archive, and its README states that external codec libraries are still taken from the system:

"External codec libraries (x264, x265) still come from the system."

The downloaded archive's own extralibs.txt confirms it was built expecting the system x264:

EXTRALIBS-avcodec=-pthread -lm -latomic -lx264

However, that archive was compiled against x264 headers where X264_BUILD was 163, while x264 encodes its ABI version into the symbol name (x264_encoder_open_<X264_BUILD>). Linking it against a system x264 built as 165 therefore cannot succeed.

Evidence from the affected machine:

$ grep -E '^#define X264_BUILD' /usr/include/x264.h
#define X264_BUILD 165

$ nm -D --defined-only /usr/lib/libx264.so | grep x264_encoder_open
x264_encoder_open_165

Because x264's ABI moved from 163 → 165, any rolling distro whose x264 has been rebuilt past 163 is broken on the prebuilt path. This is a timing problem between the archive and the distro, not a user misconfiguration.

Workaround

Disable the h264 feature so the build uses the prebuilt archive without x264 (the release ships both variants — e.g. …-gpl-swresample-swscale-x264.tar.gz and …-swresample-swscale.tar.gz), then select an encoder that does not depend on an external library:

  • Cargo.toml: remove the [target.'cfg(not(windows))'.dependencies] block (features = ["h264", "libav-agree-gpl"])
  • src/main.rs: preferred_encoder: Some("libx264") → Some("mpeg4")

This builds and renders successfully, but forces MPEG-4 Part 2 output instead of H.264 (larger files, lower quality per bit).

The documented escape hatch also works, at the cost of a long source build: FFMPEG_FORCE_BUILD=1 compiles FFmpeg against the system x264. On Linux that additionally requires nasm/yasm to be installed.

Suggested fixes

  1. Rebuild and republish the prebuilt archives against the current x264 ABI, and/or document which x264 ABI each archive was built against.
  2. Add a Linux troubleshooting note: a system x264 newer than the archive's ABI breaks the link, and FFMPEG_FORCE_BUILD=1 is the escape hatch.
  3. Consider not linking x264 from the system by default, so the prebuilt archive is self-contained and rolling-distro ABI bumps cannot break it.

Happy to test a republished archive on Arch Linux if that helps.

Activity

  1. diogochaves commented on Oct 20, 2026

    @diogochaves

    Same here on Arch (x264 0.165.r3222, fframes 1.2.0, the default h264 + libav-agree-gpl features): undefined symbol: x264_encoder_open_163 at the first link.

    One more data point: the …-x264-x265 archive has the same problem with x265. nm -u lib/libavcodec.a there shows x265_api_get_199 (Ubuntu 22.04's x265 3.5), and Arch's x265 4.3 is build 217, so h265 can't link either.

    The archives are made in rust-ffmpeg-sys, so I opened dmtrKovalenko/rust-ffmpeg-sys#1 there: the binaries workflow compiles x264 as a static library and puts libx264.a into the archive's lib/. build.rs already puts that directory first on the link path, so -lx264 finds the bundled one and the system's x264 no longer matters. With an archive built that way, fframes 1.2.0 and 1.2.1-rc.45 projects link and render on Arch. It doesn't cover x265 yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions