FFmpeg for sandboxed macOS apps: a Swift package you link, an XPC service behind it, and FFmpeg itself in a separate process per job so a conversion can be cancelled and a crash on a malformed file takes nothing with it.
import XPCFFmpeg
let ffmpeg = FFmpeg()
let info = try await ffmpeg.probe(url)
try await ffmpeg.convert(Conversion(from: source, to: destination, video: .h264()))Documentation is in docs/ — Usage,
Integrating, Building,
Architecture, Testing.
| Probe | Format, streams, colour and HDR tags, chapters — typed, not a JSON blob |
| Convert | Codecs, rate control (CRF, or bitrate with a ceiling and window), size, frame rate, profile, level, tune, pixel and colour format |
| Two-pass | A flag. convert runs ffmpeg twice and reports one continuous progress |
| Loudness | loudnorm to a target, measured first so it actually hits it |
| Streams | Per-stream overrides, subtitles, channel layouts, metadata, -map |
| Filters | -filter_complex graphs; joining, thumbnails and contact sheets built on them |
| Progress | Streamed as an AsyncStream, with a fraction and an ETA |
| Cancel | job.cancel(), or cancel the awaiting Task — SIGTERM, grace, SIGKILL |
| Capabilities | Fifteen queries answering from the real build: what it encodes, muxes, filters |
| Sandbox | Files travel as descriptors, so a conversion works from inside an App Sandbox |
Encoders compiled in: x264, x265, VideoToolbox (H.264/HEVC/ProRes), LAME, libvpx, Opus, Vorbis, libaom, plus AAC, ALAC and FLAC. Hardware encoding and decoding are available and never automatic — see Usage.
git submodule update --init
brew install nasm pkg-config x264 x265 lame libvpx opus libogg libvorbis aom libvmaf
xcodebuild -project XPCFFmpegService.xcodeproj -scheme TestXPCFFmpegService -configuration DebugThe first build compiles FFmpeg from source and takes a few minutes. See Building for what that phase does and the pitfalls it has.
XPCFFmpeg/ |
The package an app links — the whole public API. |
XPCFFmpegService/ |
The XPC service. Spawns FFmpegTask per job. |
FFmpegTask/ |
The executable that links FFmpeg and FFprobe. |
XPCFFmpegServiceFramework/ |
Protocol types shared by both sides of the connection. |
XPCServiceFramework/ |
Generic XPC listener and proxy plumbing. |
TestXPCFFmpegService/ |
Sample app, and the target that builds the whole stack. |
Scripts/ |
Coverage gate, FFmpeg fixture regeneration, end-to-end checks. |
EndToEndTests/ |
Harnesses that drive the real service and FFmpegTask. |
This project's source is MIT — see LICENSE. A built FFmpegTask binary statically
links FFmpeg, x264 and x265 and is therefore GPL v3; the other codec libraries it links (LAME,
libvpx, libopus, libvorbis, libaom) are LGPL or BSD and add nothing to that. Nothing else in the
project contains FFmpeg code. Keeping FFmpeg in its own process is what makes that true, and means an app using this service
does not have to publish its own source. See NOTICE for the boundary, and
FFmpegTask/README.md for
the reasoning.