Building FFmpeg from source is one of those tasks that sounds straightforward until you need to do it repeatedly, across multiple platforms, with a predictable set of codecs and reproducible outputs.
That is the problem ffmpeg-builder is designed to solve.
It is an open source build system for creating portable FFmpeg binaries, plus optional ffprobe, on macOS, Linux, and Windows. It works locally, but it is especially useful in CI where you want versioned artifacts you can drop directly into an app, a release pipeline, or an internal toolchain.
Why I built it
If you have ever shipped FFmpeg with an application, you already know the rough edges:
- the build steps vary by platform
- codec dependencies need to be compiled in the right order
- static linking and packaging are easy to get wrong
- one-off shell scripts tend to drift over time
- licensing decisions, especially around nonfree codecs, need to be explicit
I wanted a cleaner way to define what goes into a build and make that definition portable between local development and GitHub Actions.
What ffmpeg-builder does
At a high level, ffmpeg-builder gives you a declarative way to build FFmpeg with a selected set of codecs and features.
The project currently targets:
- Linux on Ubuntu x86_64, with optional aarch64 support via Docker and QEMU
- macOS on Apple Silicon and Intel
- Windows through MSYS2 and MinGW
It supports building popular libraries from source, including:
x264x265SVT-AV1AOM-AV1libvpxOpusfdk-aacas an opt-in nonfree option
The output is packaged into a zip archive with the binaries, configure flags, bundled licenses, and a build manifest. That makes the result much easier to audit and redistribute internally.
Declarative profiles
The part I like most about this project is the profile system.
Instead of editing a long build script every time you want to tweak a feature set, you define the build in YAML. Profiles control things like:
- which codecs are enabled
- whether the build is GPL or nonfree
- whether FFmpeg should be built static or shared
- which exact versions of ports should be used
- how much parallelism to use during the build
The repository includes a few starting points:
minimal.ymlfor a smaller redistribution-safe builddefault.ymlfor a practical desktop-oriented buildfull.ymlfor an everything-enabled configuration, including nonfree options
Here is the kind of workflow the project is built around:
# Clone the repository
git clone https://github.com/video-commander/ffmpeg-builder.git
cd ffmpeg-builder
# Inspect or duplicate a profile
cat profiles/default.yml
# Bootstrap the host toolchain
./scripts/bootstrap-macos.sh
# Build FFmpeg using a selected profile
PROFILE=profiles/default.yml ./scripts/build-ffmpeg.sh
# Package the artifacts
./scripts/package.sh
After packaging, the artifacts land in dist/ffmpeg-<version>-<os>-<arch>[-nonfree].zip.
Reproducible builds without hiding the details
One of the tradeoffs with tooling around FFmpeg is that abstraction can become a liability if it hides too much.
I did not want a black box.
ffmpeg-builder still exposes the important parts of the build: the profile, the configure flags, the versions, and the resulting manifest. That means it stays scriptable and inspectable, which matters if you are shipping binaries to customers or depending on them in production workflows.
Version pinning is also built in. You can override library versions through the profile itself or through environment variables when you need to test a newer port or temporarily work around an upstream issue.
For example:
PORT_X265_VERSION=3.5 PROFILE=profiles/default.yml ./scripts/build-ffmpeg.sh
That is a small detail, but it becomes important quickly when you want builds that are both reproducible and adaptable.
Good fit for CI and desktop apps
This project is especially useful if you are:
- bundling FFmpeg with a desktop application
- publishing internal FFmpeg toolchains for multiple operating systems
- generating release artifacts in GitHub Actions
- standardizing codec support across a team or product line
The packaged output is designed to be practical rather than theoretical. You do not just get a successful build. You get a release artifact that is ready to move into another system.
A note on licensing
FFmpeg builds are not just technical, they are also legal.
If you enable fdk-aac or other nonfree components, redistribution rules change. ffmpeg-builder makes that boundary explicit in the profile configuration instead of leaving it implied in a pile of shell flags. That was an important design goal from the start.
Try it out
If you need a repeatable way to build FFmpeg for multiple platforms, or you are tired of maintaining one-off build scripts for every target environment, take a look at the project:
https://github.com/video-commander/ffmpeg-builder
I plan to keep improving the profiles, build portability, and packaging story over time, especially as the broader Video Commander toolchain continues to grow.