Moving my video transcoding to Apple Silicon
By Daniel Samson · 2026-03-31
I started out transcoding my media library on a rack of Rock Pi 5 boards. Cheap, low-power, quietly charming. They were also far too slow for the job, and managing FFmpeg across a pile of little ARM boards over SSH turned out to be the fragile part. So I moved transcoding to Apple Silicon — and built a job daemon called Barn to run it properly.
Why convert the whole library, instead of transcoding live
There are two ways to serve media that isn't already in a web-friendly format. You can transcode it live, on demand, the instant someone hits play — the Jellyfin and Plex approach — or you can convert the entire library to a web-native format once, ahead of time, and direct-play it forever after.
Live transcoding needs real horsepower for every concurrent stream, and a Raspberry Pi — or a Rock Pi-class board — simply isn't powerful enough to do it. It can't keep up with even a single live transcode without stuttering, never mind several at once. So the decision made itself: convert everything up front. Each file is transcoded a single time, in the background, into a faststart MP4 that every client can play directly — there is no transcoding in the playback path at all.
That makes the SBCs' weakness a non-issue at watch time. But it doesn't make the work disappear — it just moves it to the conversion stage, which still has to chew through the whole library. And that is exactly the part the Rock Pis couldn't keep up with.
Why Apple Silicon
Batch-converting a library is bound by the CPU and the video encoder, and the Rock Pis only managed a trickle. A single Apple Silicon machine outruns the whole rack: it has a dedicated media engine (VideoToolbox) for hardware-accelerated H.264/HEVC encoding, it sips power for the work it does, and it's silent. One or two Macs beat a rack of single-board computers on throughput, watts, and noise all at once.
The real problem was never the hardware
Running FFmpeg over SSH ad-hoc breaks the moment you need more than one job at a time, or the SSH session drops, or a machine reboots mid-encode. There's no recovery, no concurrency control, and no visibility into what's running or why something failed. The bottleneck I actually hit was orchestration, not compute — faster boxes just let me hit it sooner.
So I built Barn
Barn is a cross-platform job daemon — launchd on macOS, systemd on Linux, a Windows service — that treats FFmpeg jobs as first-class managed units of work rather than fire-and-forget shell commands. The pipeline submits a job over SSH; Barn runs it in the background, independent of the SSH session, and it survives disconnects, restarts and crashes. The client and the service are the same single binary; the client just talks to the daemon over IPC.
What Barn gives me
Durable job state —
queued → running → succeeded/failedwith retries, heartbeats, and explicit failure reasons, all inspectable after the fact.Crash recovery with no database: all job state lives in atomic filesystem operations under a temp dir, so a reboot mid-encode is recoverable rather than a mystery. (Yes, I'm the database-for-everything person — for ephemeral local job state on a machine that might vanish, the filesystem was the right call.)
Load levels — each job is auto-classified
HIGH/MEDIUM/LOWso the daemon won't kick off six heavy transcodes at once and thrash the machine.One CLI for everything:
barn run,barn status,barn describe --logs,barn usage,barn kill— all with--output=jsonso the pipeline can drive it programmatically.
How it fits the pipeline
The conversion pipeline hasn't changed shape — scan storage for new media, dispatch a job — but the job now runs as barn run over SSH on whichever Mac is free: pull the source from WebDAV, probe it, transcode to a faststart MP4, extract subtitles, upload the result. Each step is a tagged Barn job the pipeline can poll and reason about. If a machine drops off mid-run, the state survives on disk instead of evaporating with the SSH session.
The result
Faster transcodes, a quieter house, a smaller power bill, and — the bit that actually matters — a transcoding tier I can trust to run unattended. The Rock Pis were a genuinely fun experiment in cheap horizontal scale, and I don't regret the detour. But shifting a real library takes both the muscle of Apple Silicon and a daemon that treats every job as a durable unit of work. Barn is the thing that turned "a pile of Macs running FFmpeg" into something I'd actually call a pipeline.