Setting Up FFmpeg
Singulink.FulcrumFS.Videos does its work by running the ffmpeg and ffprobe executables of an FFmpeg build you provide, and that build needs a few libraries that not every build has. This guide covers what a build needs, how to check one, and how to make one with the scripts in the repository's Tools/FFmpeg folder, which build a complete one on Windows, Linux or macOS without any configuration. Once you have a build, see Video Processing for configuring the library with it.
What a Build Needs
When you construct a VideoProcessor or VideoFrameExtractionProcessor, the library asks ffprobe what the build supports and throws NotSupportedException if something its options need is missing. What it uses falls into three groups.
Required by every processor:
- The
libx264encoder for H.264 output and thelibx265encoder for HEVC output (a build needs only the one for the codec you produce, but the predefined options use both). - FFmpeg's own
aacencoder,pngencoder (for frame extraction) andmp4muxer. - The
zscalefilter, which needs FFmpeg to be built withlibzimg, and thescale,fps,tonemap,format,bwdif,setsar,transpose,hflip,vflipandsidedatafilters, which FFmpeg includes by default.
Required for the source codecs and formats accepted by default. A processor accepts every source codec and container format the library knows unless its options narrow them, and it needs a decoder or demuxer for each one it accepts:
- Video decoders:
h264,hevc,mpeg1video,mpeg2video,mpeg4,h263andvvc;vp8andvp9together with thelibvpxandlibvpx-vp9decoders (fromlibvpx);av1together with thelibdav1ddecoder (fromdav1d). - Audio decoders:
aac,mp2,mp3,vorbis,opus,amr_nbandamr_wb. - Demuxers:
mov(MP4, MOV, M4A, 3GP, 3G2, MJ2),matroska(MKV, WebM),avi,mpegts(TS, M2TS) andmpeg.
If a build lacks one of these, you can still use it by leaving the codec or format out of SourceVideoCodecs, SourceAudioCodecs or SourceFormats; uploads in that codec or format are then rejected. An older FFmpeg without a VVC decoder, for example, works once H266 is left out.
Optional, used when present:
- The
libfdk_aacencoder (from Fraunhofer's FDK AAC library), which gives noticeably better AAC audio than FFmpeg's own encoder, especially at low bitrates. Without it, the library uses FFmpeg'saacencoder. See Licensing for the catch. - The
mov_textanddvdsubencoders, which are needed when TryPreserveUnrecognizedStreams is set. FFmpeg includes them by default. - Hardware acceleration, when the processing options ask for it. See Hardware Acceleration.
ffmpeg and ffprobe must come from the same build: the library checks what ffprobe supports and transcodes with ffmpeg.
Checking a Build
check-ffmpeg.sh (bash, for Linux and macOS) and check-ffmpeg.ps1 (PowerShell, for Windows or PowerShell 7 anywhere) check a directory containing ffmpeg and ffprobe for all of the above, the same way the library does, and report what is missing:
./check-ffmpeg.sh /opt/ffmpeg
.\check-ffmpeg.ps1 C:\Tools\ffmpeg
Checking /opt/ffmpeg
ffmpeg version 9.0.2 Copyright (c) 2000-2026 the FFmpeg developers
ffprobe version 9.0.2 Copyright (c) 2007-2026 the FFmpeg developers
Required:
ok libx264 encoder H.264 output
ok libx265 encoder HEVC output
...
MISSING zscale filter colour conversion and HDR tone mapping (needs libzimg)
...
Hardware acceleration (optional; used only when the processing options ask for it):
videotoolbox not built in
cuda built in, works on this machine
...
1 required feature(s) missing: the library's processors will refuse this build (with their default options).
The exit code is 0 when nothing required is missing and 1 when something is. --strict (-Strict) also fails on a missing optional feature. For each hardware acceleration mode the build has, the script decodes a short test stream with it, as the library does before using a mode, so running it on the server tells you which modes will actually work there; --skip-hwaccel-test (-SkipHWAccelTest) only lists them.
Building with the Scripts
The build scripts make a build with everything the library uses, including libfdk_aac, check it with --strict and copy ffmpeg and ffprobe into the directory you give them. Both executables link the libraries they use statically (on Linux, all but the system's C and C++ runtime libraries), so the output directory is all you need to deploy. The scripts drive two well-established build systems: ffmpeg-build-script on Linux and macOS, and media-autobuild_suite on Windows. Each downloads and compiles FFmpeg and its libraries from source, which takes a while: allow from half an hour to a few hours, depending on the machine.
To get the scripts, clone the repository or copy the Tools/FFmpeg folder; the scripts use the other files in it.
Both scripts build in a work directory of their own (by default ~/fulcrumfs-ffmpeg-build on Linux and macOS, and C:\ffbuild on Windows). A script refuses to start if that directory exists and it did not make it; one left by an earlier run is deleted and made again, so a failed build can simply be run again. The work directory is left in place after a build, for looking into, and can be deleted then.
Note
FulcrumFS's CI builds FFmpeg with these same scripts on every change and every week, and runs the library's tests against the result, so a change upstream that breaks them is noticed quickly.
Linux and macOS
On Linux, the build needs a C/C++ toolchain, git, curl, tar, xz, python3, meson and ninja. --install-prerequisites installs them with apt-get (Debian, Ubuntu), dnf (Fedora, RHEL) or Homebrew (macOS), using sudo unless run as root. On macOS, install the Xcode command line tools first (xcode-select --install).
./build-ffmpeg.sh --install-prerequisites ~/ffmpeg
| Option | Meaning |
|---|---|
--ffmpeg-version VERSION |
The FFmpeg release to build, such as 9.0.2, or snapshot for FFmpeg's current master. By default, the latest release of the major version ffmpeg-build-script supports. |
--script-ref REF |
The tag or branch of ffmpeg-build-script to build with. By default, the head of its default branch. |
--work-dir DIR |
The directory to build in. |
--install-prerequisites |
Install the packages the build needs first. |
On Linux, the executables link the system's C and C++ runtime libraries dynamically, and need versions of them at least as new as the ones they were built with. Build on the distribution you deploy to, or an older one; for containers, see Building in Docker.
Windows
The build needs only Git and around 20 GB of disk space: media-autobuild_suite installs its own MSYS2 environment and compilers into the work directory. Run the script from PowerShell (Windows PowerShell 5.1 or PowerShell 7):
.\build-ffmpeg.ps1 C:\Tools\ffmpeg
| Parameter | Meaning |
|---|---|
-FFmpegVersion |
The FFmpeg release to build, such as 9.0.2, latest (the default) for the latest release, or master for FFmpeg's current master. The libraries are always built at the heads of their repositories. |
-WorkDir |
The directory to build in, which must be a short path without spaces. |
-Cores |
The number of processors to compile with. By default, all of them. |
Tip
An antivirus that scans files as they are written slows the build down considerably, since it writes a very large number of small files. Consider excluding the work directory from on-access scanning for the duration of the build.
Building in Docker
To run the application in a Linux container, build FFmpeg in a stage of the image's Dockerfile, based on the .NET SDK image (which is built on the same distribution as the runtime images of the same tag), and copy the executables into the final image. Copy the Tools/FFmpeg folder into the build context first:
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS ffmpeg
COPY Tools/FFmpeg /tools/ffmpeg
RUN bash /tools/ffmpeg/build-ffmpeg.sh --install-prerequisites --work-dir /tmp/ffmpeg-build /opt/ffmpeg && rm -rf /tmp/ffmpeg-build
FROM mcr.microsoft.com/dotnet/aspnet:10.0
COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg
# ... the rest of your image; configure the library with /opt/ffmpeg.
Docker caches the stage's result, so FFmpeg is only built again when the stage, the scripts or the base image change.
Using a Prebuilt Build
Any build that passes check-ffmpeg works. None of the widely available prebuilt builds include libfdk_aac, because a build with it cannot be redistributed (see Licensing), so with one of them the library uses FFmpeg's own AAC encoder. Some are also missing required libraries. At the time of writing:
- On Windows, the "full" builds from gyan.dev and the GPL builds from BtbN include the required libraries. gyan.dev's "essentials" builds do not include
dav1d, so they cannot read AV1 sources. - On Linux, BtbN's GPL builds include the required libraries. Distribution packages vary in what they include, and can be too old to have a VVC decoder.
- On macOS, Homebrew's
ffmpegis built withoutlibzimg, so it lacks the requiredzscalefilter. The homebrew-ffmpeg tap builds one with it:brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-zimg.
BtbN's build scripts can also make a "nonfree" variant with libfdk_aac, for Windows or Linux, with Docker on a Linux machine.
Hardware Acceleration
A hardware acceleration mode can only be used if FFmpeg was built with support for it, and the machine has a device and driver it works with. What the build scripts include:
- Windows: CUDA (NVIDIA), AMF (AMD), QSV (Intel) and D3D12 are always built in. At run time, each needs the GPU's driver.
- macOS: VideoToolbox is always built in.
- Linux: AMF and QSV are built in on x86-64. AMF needs AMD's AMF runtime on the server. QSV on Linux also needs VA-API, which is only built in when the libva development files (
libva-devon Debian and Ubuntu) are installed at build time, and which then makes the executables depend onlibva(and Intel's media driver) on the server. CUDA is built in only when the CUDA toolkit (nvcc) is installed at build time; ffmpeg-build-script then builds for the compute capability of the machine's NVIDIA GPU, or for the one in theCUDA_COMPUTE_CAPABILITYenvironment variable when building for a different GPU.
Run check-ffmpeg on the server to see which modes work there. The library falls back to software when a requested mode is unavailable, so a build without acceleration still processes every file; see Hardware Acceleration in the video processing guide.
Licensing
FFmpeg itself is LGPL, but a build with libx264 and libx265, which the library requires, is GPL. Adding libfdk_aac, whose license is not compatible with the GPL, makes it what FFmpeg's configure calls "nonfree and unredistributable": you may build it and use it, but not give it to others, which includes shipping it in an installer or publishing a container image with it. The builds the scripts make are of this kind.
If you need to distribute FFmpeg with your application, use a build without libfdk_aac (any of the prebuilt GPL builds above, for example) and meet the GPL's terms for it. The library works the same with such a build, using FFmpeg's own AAC encoder. See FFmpeg's license page for the details, and take legal advice where it matters.
Next Steps
- Video Processing - Configuring the library with your build, and the processors and their options.