ff-sys
Why ff-sys?
Crates like ffmpeg-sys-next, ffmpeg-next, and rsmpeg already wrap FFmpeg well. ff-sys does not try to replace them; it is the purpose-built FFI base for the ff-* / avio family, optimised for that one job:
- Version and ABI control: it targets FFmpeg 7.x / 8.x directly and owns exactly which versions and ABI quirks it supports (for example the
SWS_*flag change between libswscale 8 and 9, handled via theffmpeg8cfg). - Self-contained build detection: the build script locates FFmpeg per platform on its own (vcpkg via
VCPKG_ROOTon Windows, pkg-config on Linux, Homebrew on macOS) and drives bindgen throughLIBCLANG_PATH, so the family is not bound to another crate's build-script assumptions. - An implementation detail, not a public API: application code uses the safe
ff-*crates, neverff-sysdirectly, so "mature vs. new" matters less for a base you are not meant to depend on.
Building your own project on FFmpeg directly? The crates above are excellent choices. Building on avio? You already get ff-sys transitively; reach for the safe ff-* crates.
Installation Prerequisites
FFmpeg 7.x or 8.x development libraries must be available on your system before building any crate in this workspace. FFmpeg 6.x is not supported (the SWS_* flags differ in API shape); 8.x is detected automatically via the SwsFlags enum (the ffmpeg8 cfg).
Windows
Install FFmpeg via vcpkg:
The build script reads VCPKG_ROOT to locate the installation (defaulting to C:\vcpkg) and expects FFmpeg under <VCPKG_ROOT>\installed\x64-windows. bindgen also requires libclang: set LIBCLANG_PATH to your LLVM bin directory (containing libclang.dll) if it is not in a standard location such as C:\Program Files\LLVM\bin.
Linux
Detected via pkg-config:
If FFmpeg is installed in a non-standard location, set PKG_CONFIG_PATH to its lib/pkgconfig directory.
macOS
Platform Support
| Platform | Detection | Notes |
|---|---|---|
| Windows | vcpkg (VCPKG_ROOT) |
ffmpeg:x64-windows triplet; LIBCLANG_PATH for bindgen |
| Linux | pkg-config | Dev packages (-dev) must be installed |
| macOS | Homebrew, pkg-config | Auto-detects /opt/homebrew or /usr/local, falls back to pkg-config |
Safe layer
Alongside the raw bindgen output, ff-sys ships a hand-written safe layer that isolates the most error-prone FFmpeg call sequences. It is built from owned RAII types: each wraps a NonNull<T>, is neither Copy nor Clone, and frees its FFmpeg resource exactly once on Drop, so a leak or double-free is not expressible in safe code (ADR-0003):
| Owned type | Wraps |
|---|---|
Frame |
AVFrame (owned; drops once) |
Packet |
AVPacket (owned; drops once) |
CodecContext |
AVCodecContext, codec open/close + send/receive drain-flush |
FormatContext |
AVFormatContext, demux/mux lifecycle |
ScaleContext |
SwsContext, pixel-format conversion |
ResampleContext |
SwrContext, sample-format / channel-layout conversion |
HwDeviceContext |
Hardware-acceleration device context |
AvError |
A typed error over FFmpeg's c_int return codes |
The owned types expose no raw pointers across their public API: the as_ptr / as_mut_ptr accessors are pub(crate), sealed so only the ff-* crates in this workspace reach the raw handle (guarded by tests/seal.rs, #1506). As a result the entire ff-* family is raw-pointer-free at its boundaries. Free functions grouped under the avcodec, avformat, swscale, and swresample modules cover the remaining stateless helpers.
Everything here is public (pub) but meant for use by the higher-level ff-* crates rather than for direct consumption.
Usage
ff-sys is normally consumed transitively through the safe ff-* crates. A few of the safe helpers are self-contained, however, and can be called directly:
use ;
Most of the surface is raw FFI and therefore unsafe; the safe wrappers above and the ff-* crates exist so that application code never has to touch it directly.
MSRV
Rust 1.93.0 (edition 2024).
License
MIT OR Apache-2.0