Unknown encoder 'libx264' isn't a bug. It's your FFmpeg build

Your Dockerfile built clean. The ffmpeg command is copied from a machine where it works. The container still exits with Unknown encoder 'libx264' before it writes a single frame.
Quick answer: FFmpeg's "Unknown encoder 'libx264'" error means the ffmpeg binary you're running was compiled without--enable-gpl --enable-libx264, not that your command is wrong or that FFmpeg is broken. Runffmpeg -encoders | grep 264to see which H.264 encoders your build actually contains, then install a GPL-enabled build (Alpine'sapk add ffmpeg, Debian'sapt-get install ffmpeg, or a pinned static release) or fall back to-c:v libopenh264 -b:v 2M. If you'd rather not audit an encoder table on every deploy, send the job to FFmpeg Micro instead: one API call, no binary to install and no configure flags to get right.
The error is a build report, not a bug
Conventional wisdom says this error means something is wrong with your FFmpeg install, so people reinstall it. That's half right: something is wrong with the install, but reinstalling the same package gets you the same binary. FFmpeg prints Unknown encoder 'libx264' when it looks up the string you passed to -c:v in its encoder table and finds nothing. The table is fixed at compile time. If whoever built your binary didn't pass --enable-gpl --enable-libx264 to ./configure, x264 was never linked in and no amount of apt-get install --reinstall will conjure it.
One command tells you which side you're on:
ffmpeg -hide_banner -encoders | grep 264
A build with x264 answers like this:
V....D libx264 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
V....D libx264rgb libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB (codec h264)
V....D h264_vaapi H.264/AVC (VAAPI) (codec h264)
A build without it answers like this, and the absence of the libx264 line is your whole diagnosis:
V....D libopenh264 OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
V....D h264_v4l2m2m V4L2 mem2mem H.264 encoder wrapper (codec h264)
For the full picture, ffmpeg -buildconf prints every configure flag the binary was compiled with. Grep it for --enable-libx264. If it isn't there, stop debugging your command.
This question has been recurring for over a decade with the same answer every time: the ffmpeg-user mailing list fielded it in 2013, LinuxQuestions has a [SOLVED] thread on it, and the mobile builds have their own long-running versions in arthenica/ffmpeg-kit issue #1159 and tanersener/mobile-ffmpeg issue #127. Nobody's binary was corrupt. Every one of them had the wrong package variant.
libx264, h264, libopenh264, and h264_nvenc are four different things
Those four names get used interchangeably in tutorials, and mixing them up is how people end up debugging the wrong layer. h264 is the codec, the standard itself. libx264 is one software encoder that produces H.264, the GPL-licensed x264 library. libopenh264 is a different software encoder for the same codec, Cisco's implementation, shipped under a license distros are more comfortable with. h264_nvenc, h264_qsv, h264_vaapi, h264_videotoolbox, and h264_amf are hardware encoders that hand the work to a GPU or a fixed-function block.
There's a portable trick here. -c:v h264 asks FFmpeg for the codec rather than a named encoder, and FFmpeg resolves it to whichever H.264 encoder the build has, preferring libx264 when present. Run with -v verbose and you'll see it log Matched encoder 'libx264' for codec name 'h264'. For a script that has to run on machines you don't control, -c:v h264 survives builds that -c:v libx264 dies on.
The catch is that the encoders aren't interchangeable in their options. libopenh264 has no -crf, so every quality flag you copied from an x264 tutorial fails silently or errors out, and you have to switch to target bitrate with -b:v 2M. It also produces visibly worse output at the same bitrate on hard content. If your pipeline was tuned around constant quality, read when two-pass actually beats CRF before you pick a bitrate at random.
Which images and packages ship libx264 and which don't
Most mainstream Linux packages do include x264, which is exactly why the failures feel random: the images that don't ship it are the minimal, hardened, or license-cautious ones people move to for good reasons. Here's where the line falls.
| Base image or package | libx264 present | What's actually going on |
|---|---|---|
| `alpine:3.20` + `apk add ffmpeg` | Yes | Alpine's community package is built with `--enable-gpl --enable-libx264` |
| `debian:bookworm-slim`, `ubuntu:24.04` + `apt-get install ffmpeg` | Yes | Debian and Ubuntu ship the GPL build |
| `python:3.12-slim`, `node:22-slim` + apt install | Yes | Debian-based, same package |
| Fedora / RHEL 9 `dnf install ffmpeg-free` | No | Patent-encumbered encoders stripped; you get libopenh264 and hardware encoders only |
| conda-forge `ffmpeg` (default resolve) | No | conda-forge publishes both lgpl and gpl build variants; the default lands on lgpl |
| `gcr.io/distroless/*`, `FROM scratch` | No | No package manager, nothing to install into |
| Recent official n8n images | No | The image went distroless in 2026, so `apk add ffmpeg` fails outright |
| ffmpeg-kit / mobile-ffmpeg `min`, `https`, `video`, `full` | No | x264 is GPL, so only the `-gpl` package variants carry it |
| AWS Lambda AL2023 base | No FFmpeg at all | You bring a layer or a static binary |
| johnvansickle and BtbN static release builds | Yes | GPL builds, x264 included |
The n8n one bites hardest because every published "install ffmpeg in n8n" answer predates the change. The old USER root; RUN apk add --no-cache ffmpeg recipe just fails now. The community workaround is a multi-stage build that copies Alpine's apk and libapk.so* into the distroless base, which has to be re-verified on every n8n release.
Rebuilding FFmpeg from source is the wrong fix in a deploy pipeline
The top answer on most forums is to compile FFmpeg yourself with --enable-gpl --enable-libx264. That works on your laptop and it's a bad trade in a build pipeline. Compiling FFmpeg with x264, lame, and freetype runs roughly 10 to 20 minutes on a 4-vCPU CI runner, pulls nasm, pkg-config, and a C toolchain into your image, and hands you ongoing responsibility for tracking CVEs in FFmpeg and x264 yourself. There's a licensing consequence too: linking libx264 makes the resulting binary GPL, which is precisely why Fedora and conda-forge ship openh264 by default instead.
Pin a static build instead. Download a specific versioned artifact from johnvansickle.com or the BtbN/FFmpeg-Builds releases, verify its checksum, and copy it into the image. Never curl a URL that means "latest," because that's a silent version bump on a random Tuesday.
Then assert the encoder exists at build time rather than discovering it in production:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg \
&& rm -rf /var/lib/apt/lists/*
RUN ffmpeg -hide_banner -encoders | grep -q '^ V.*libx264 ' \
|| (echo "FATAL: this ffmpeg has no libx264" && exit 1)
That single RUN line converts a runtime failure on a customer's upload into a red build. It costs nothing and it's the highest-value line in the Dockerfile.
There's a third option, which is to stop shipping an encoder at all. FFmpeg Micro is a managed FFmpeg build behind a REST API: you POST the job, poll or take a webhook, and download the output, with no binary in your image and no encoder table to audit. It's the same reasoning behind running video work outside Firebase Cloud Functions, and it works the same way from n8n, Make, Zapier, or an MCP tool call. The free tier is enough to test whether your job encodes correctly before you decide.
Common pitfalls that produce the same error
Once you know the build is the cause, a handful of specific mistakes account for most remaining cases.
- Two ffmpeg binaries on the box. You compiled to
/usr/local/bin/ffmpegbut the shell cached the old/usr/bin/ffmpeg. Runwhich -a ffmpegandhash -r, and in a container check that your entrypoint isn't using an absolute path to the wrong one. - Picking the non-GPL mobile package. In ffmpeg-kit and mobile-ffmpeg,
fulldoes not include x264. Only the-gplvariants do. That single suffix is the entire content of both long-running issue threads. - Assuming
h264_nvencin the encoder list means NVENC works. The encoder is compiled in; it still fails at runtime without the NVIDIA Container Toolkit and a mapped GPU. That failure readsCannot load libnvidia-encode.so.1, which is a driver problem, not a build problem. - Configure not finding x264 even though you installed it.
./configure --enable-gpl --enable-libx264needsx264.pcon the pkg-config path, which usually means the-devor-develpackage, not just the runtime library. Checkconfig.logfor the failed pkg-config probe. - Passing the codec name with stray whitespace. Template interpolation in n8n, Make, or a Node
spawncall can hand FFmpeglibx264with a trailing space, and the lookup fails on a string that looks correct in your logs.
If your pipeline is accumulating this kind of input-shaped failure, the same discipline applies to moov atom not found and height not divisible by 2: validate at the boundary, fail loudly, and don't let a class of error reach the encode step.
FAQ
Does apt install ffmpeg include libx264?
Debian and Ubuntu's ffmpeg package includes libx264, so apt-get install ffmpeg on debian:bookworm-slim, ubuntu:24.04, or any Debian-derived image like python:3.12-slim gives you a working -c:v libx264. Red Hat and Fedora are the exception: their ffmpeg-free package strips x264, and you need the RPM Fusion build or a static binary instead.
Can I use -c:v h264 instead of -c:v libx264?
-c:v h264 works and is more portable than -c:v libx264 because FFmpeg resolves the codec name to whatever H.264 encoder the build contains, preferring libx264 when it's present. The trade-off is that you no longer know which encoder you got, so options like -crf and -preset may not apply if the build resolves to libopenh264.
Is libopenh264 a real replacement for libx264?
libopenh264 encodes valid H.264 that plays everywhere, but it isn't a drop-in swap for libx264. It has no CRF mode, so you control quality with -b:v instead, and at matched bitrates it loses detail on high-motion footage that x264 holds. Use it when license constraints force your hand, not when you have a choice.
Why doesn't my self-compiled FFmpeg have libx264 when x264 is installed?
FFmpeg's configure script only links x264 when you explicitly pass both --enable-gpl and --enable-libx264 and pkg-config can find x264.pc. Installing the x264 runtime library alone isn't enough; you need the development package that ships the headers and the pkg-config file, and config.log will show the probe that failed.
How do I check FFmpeg's encoders without running a job?
Run ffmpeg -hide_banner -encoders | grep 264 to list every H.264 encoder in the binary, or ffmpeg -h encoder=libx264 to query one directly. A build without x264 answers the second command with Codec 'libx264' is not recognized by FFmpeg, which is the same diagnosis in one line.
Auditing encoder tables across four base images is work that produces no video. If you'd rather have H.264 output be a request instead of a build artifact, sign up free and run your first encode against a build that's already configured.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

FFmpeg fontconfig error isn't fatal. It ships the wrong font.
The FFmpeg fontconfig error is a warning, not a failure: the job exits 0 and ships the wrong font. Fix it in Alpine, Debian slim, and distroless images.

MP4 Not Playing in Browser? Four Encoder Flags Fix It
MP4 not playing in browser? VLC decodes almost anything, hiding the four real breakers: pixel format, H.264 profile/level, moov placement, audio codec.

FFmpeg NVENC vs libx264: When GPU Encoding Actually Wins
FFmpeg NVENC is faster than libx264, but only if the whole filter graph stays on the GPU. The QP-vs-CRF trap, session limits, and the real per-job cost math.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free