📝 Originally published (in Japanese) at forge.workstyle.tech.
This article is for anyone who wants to bundle ffmpeg with a desktop app but is concerned about licensing when enabling libx264. ffmpeg is a tool for working with video and audio, and libx264 is a library used to encode video. In my test with a 3-second clip, user CPU time was 1.26 seconds for libx264 and 0.20 seconds for VideoToolbox. This article covers builds for macOS and Windows, encoder arguments, and checks to run before distribution.
TL;DR
Enabling libx264 makes ffmpeg itself GPL-licensed, so we removed it from the bundled build. On macOS, we use h264_videotoolbox; for Windows, we have a configuration using h264_nvenc and h264_mf. We use separate arguments for each encoder, align the build settings with the license information, and verify that the distribution includes the executable and the full license text.
Why I Removed libx264 from the Bundled Build
The design documents state that FFmpeg itself is licensed under LGPL 2.1+, while libx264 is GPL-licensed. Linking libx264 would make FFmpeg itself GPL-licensed, so I removed it from the bundled version.
On macOS, I use h264_videotoolbox. When encoding a 3-second clip, user CPU time was 1.26 seconds with libx264 and 0.20 seconds with h264_videotoolbox—about one-sixth as much. These measurements are specific to the tested clip and environment.
For Windows, one configuration uses h264_nvenc and h264_mf. h264_mf is provided as a Windows fallback. Enabling NVENC requires nv-codec-headers. QSV and AMF are not included in this configuration because they require external libraries.
How to Build ffmpeg for macOS
The build steps for bundling are collected in a script. It downloads the source archive, verifies its SHA-256 checksum, and then extracts it. After the build, it copies the executable and the full LGPL license text to the output directory.
sh scripts/build-ffmpeg.sh
The script’s configure options disable GPL, nonfree, and version3, and enable VideoToolbox and AudioToolbox. After the build, it checks the output of ffmpeg -version and fails if it contains --enable-gpl.
One record notes that the resulting build was 13 MB. The build artifact is not committed to the repository; it is built before creating a release. Place COPYING.LGPLv2.1 alongside the executable.
When NVENC Isn’t Found on Windows
Run the Windows build script inside UCRT64, the build environment for Windows.
sh scripts/build-ffmpeg-win.sh
Fetch a pinned version of the NVENC headers and install them under /ucrt64. In configure, specify --enable-ffnvcodec and --enable-nvenc.
The combination of --disable-autodetect and NVENC is where I got stuck. Since ffnvcodec is subject to autodetection, disabling autodetection makes it appear that the dependency can’t be found. --enable-nvenc alone isn’t enough; you also need to explicitly specify --enable-ffnvcodec.
One more thing: adding a comment in the middle of a configure command continued with backslashes can cause the command to break there. There’s a report that sh -n won’t catch it even if the remaining options run as a separate command. Avoid comments in the middle of a continued command, and check the output after the build.
How to Choose Streaming Arguments for Each Encoder
When you change the encoder, review the arguments passed to ffmpeg as well. -preset and -tune are for libx264. Passing them unchanged to VideoToolbox or another encoder will cause it to fail. In my implementation, I pass -preset veryfast -tune zerolatency only when using libx264, and pass -realtime 1 to all other encoders.
You can check which encoders are available with this command:
ffmpeg -hide_banner -encoders
In the bundled macOS version, I confirmed that h264_videotoolbox and aac are available, while libx264 is not included. For Windows, I confirmed that h264_nvenc, h264_mf, and aac are available.
If the bundled version has no usable video encoder, do not automatically fall back to libx264. The bundled version does not include libx264. The design reports an error before streaming starts if no supported encoder is available. When using a separate ffmpeg installed on the device, its executable may include libx264. Be careful not to confuse the bundled version with the one installed on the device.
Keeping Build Settings and License Information in Sync
When bundling LGPL software, you need to provide not only the full license text but also instructions for obtaining the corresponding source code. To make it possible to reproduce the same build, our records include the source URL, SHA-256 checksum, and every configure option alongside the license information.
When you change the configure options in the build script, update the options in the license information as well. Compare the two and make sure they match. The same applies to Windows builds. If the build instructions and the published information don’t agree, they can’t help someone reproduce the same version.
Even if you don’t track build artifacts in Git, you still need to prepare them before distribution. Use the script to build FFmpeg, confirm that the executable and full license text are in the output directory, and then package the app.
How to Check Whether ffmpeg Is Included in a Release
The last issue I ran into was that the packaging process continued even though the ffmpeg output directory didn’t exist. The log showed a “file source doesn't exist” warning, but the build itself succeeded, producing a release package without ffmpeg.
That’s why a successful CI run alone doesn’t confirm that ffmpeg is bundled. For a Windows release, after packaging, open dist/win-unpacked/resources/ffmpeg/ and check that it contains both ffmpeg.exe and COPYING.LGPLv2.1. Before building, also verify that the executable is in the expected output location, the full license text is present, and no GPL designation is included.
Before releasing, I check three things: the encoder, the build configuration, and the bundled files. I verify separately that ffmpeg built successfully and that it was bundled in a distributable form.
If You Run Into the Same Issue
- Check the build script’s configure options to confirm that GPL is disabled.
- Check the configuration and available encoders with
ffmpeg -versionandffmpeg -hide_banner -encoders. - Pass arguments that match the encoder, and report an error before starting the stream if the required encoder is unavailable.
- Open the build output directory and the distribution package to confirm they contain the executable and
COPYING.LGPLv2.1.
Top comments (0)