ffmpeg: The Swiss Army Knife You're Underusing
ffmpeg does the work of five SaaS subscriptions from a single command line. Video compression, audio extraction, thumbnail generation, format conversion, batch processing. If you're creating any kind of content as a solo builder and you're not using it, you're either overpaying for tools or doing things by hand that a one-liner could handle.
It's been around since 2000. It powers the backends of YouTube, VLC, and most of the streaming infrastructure on the internet. And it runs locally, for free, with no upload limits, no watermarks, and no monthly invoice.
Getting It Running
On Mac:
brew install ffmpeg
That's it. No account creation, no API key, no license tier to evaluate. The Homebrew formula pulls in hardware acceleration support for Apple Silicon automatically.
Confirm it's working:
ffmpeg -version
You'll see a wall of text listing every codec, format, and protocol it supports. The list is long. That's the point.
Compression: The Command That Saves Money
Raw screen recordings and camera footage are absurdly large. A 10-minute 1080p screen recording can be 500MB-1GB depending on the codec your capture tool uses. Hosting that on any CDN adds up fast.
One command brings it down to size:
ffmpeg -i raw-recording.mov -c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k -movflags +faststart output.mp4
What each flag does:
- -c:v libx264: H.264 video codec, universally supported by every browser and device
- -crf 23: Constant Rate Factor. Lower means better quality, higher means smaller files. 18-23 is the sweet spot for web content. 18 is visually lossless. 28 starts looking rough.
- -preset medium: Encoding speed tradeoff. Slower presets produce smaller files at the same quality. For batch processing overnight, use
slow. For quick turnaround,fast. - -movflags +faststart: Moves the metadata to the beginning of the file so browsers can start playing before the full download completes. Skip this and your embedded videos will buffer needlessly.
I ran this on a 47-minute screen recording. The source file was 2.1GB. The output was 310MB. Same resolution, no visible quality difference at normal playback. That's ~85% reduction with a single command.
For Apple Silicon Macs, you can use the hardware encoder instead:
ffmpeg -i raw-recording.mov -c:v h264_videotoolbox -b:v 3M \
-c:a aac -b:a 128k -movflags +faststart output.mp4
VideoToolbox encoding is 3-5x faster than software encoding. The tradeoff: slightly larger files at the same visual quality. For a quick compress-and-upload workflow, it's worth it.
Extracting Audio, Thumbnails, and Clips
Every long-form video you record contains multiple pieces of content trapped inside it. ffmpeg is how you get them out.
Extract audio from a video (for a podcast feed or transcription pipeline):
ffmpeg -i video.mp4 -vn -c:a libmp3lame -q:a 2 audio.mp3
The -vn flag strips the video stream entirely. No re-encoding the video, no wasted CPU cycles. The audio extraction takes seconds regardless of how long the source file is.
Grab a thumbnail at a specific timestamp:
ffmpeg -i video.mp4 -ss 00:02:15 -frames:v 1 thumbnail.jpg
Cut a 60-second clip starting at the 5-minute mark (for social media):
ffmpeg -i video.mp4 -ss 00:05:00 -t 60 -c copy clip.mp4
The -c copy flag is important here. It tells ffmpeg to copy the streams without re-encoding. The clip operation takes under a second because it's just slicing bytes, not reprocessing video frames. Without -c copy, a 60-second clip from an hour-long video would take minutes instead of milliseconds.
Generate a thumbnail grid (contact sheet) from an entire video:
ffmpeg -i video.mp4 -vf "select=not(mod(n\,300)),scale=320:-1,tile=4x4" \
-frames:v 1 contact-sheet.jpg
This grabs every 300th frame, scales them to 320px wide, and tiles them in a 4x4 grid. One image that gives you and your audience a visual summary of the entire video.
Batch Processing with Shell Scripts
The real leverage comes when you stop running ffmpeg one file at a time. A shell loop replaces an entire video processing SaaS.
Compress every .mov file in a directory:
for f in raw/*.mov; do
ffmpeg -i "$f" -c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k -movflags +faststart \
"compressed/$(basename "${f%.mov}.mp4")"
done
Extract audio from an entire season of video content:
for f in episodes/*.mp4; do
ffmpeg -i "$f" -vn -c:a libmp3lame -q:a 2 \
"audio/$(basename "${f%.mp4}.mp3")"
done
Generate thumbnails for every video in a batch:
for f in videos/*.mp4; do
ffmpeg -i "$f" -ss 00:00:10 -frames:v 1 \
"thumbnails/$(basename "${f%.mp4}.jpg")"
done
Three scripts, maybe 15 lines total, doing the work of Cloudinary's video transformation API, an audio extraction tool, and a thumbnail generator. The scripts run overnight, process everything in the queue, and cost nothing per invocation. No per-minute pricing. No upload bandwidth. No API rate limits.
The Gotchas
ffmpeg's power comes with sharp edges. Here's what will waste your time if nobody warns you.
Codec compatibility is a minefield. H.265 (HEVC) produces smaller files than H.264 at the same quality, but Safari on older macOS versions doesn't support it, and some Android browsers handle it poorly. Stick with H.264 (libx264) for anything that needs to play everywhere. The file size savings from H.265 aren't worth the support headaches for web content.
Audio codec mismatches cause silent failures. You'll produce a video that plays fine on your machine but has no audio in a browser. The usual culprit: the source audio was in a format the output container doesn't support, and ffmpeg silently dropped it. Always explicitly set your audio codec with -c:a aac for MP4 output. Don't rely on defaults.
Hardware acceleration flags are platform-specific. h264_videotoolbox works on macOS. h264_nvenc works on Linux with NVIDIA GPUs. h264_qsv works with Intel Quick Sync. A script that works on your Mac won't work on your Linux server without changing the encoder. If you're writing scripts meant to run on multiple machines, use libx264 (software encoding) and accept the speed penalty. It works everywhere.
The flag order matters more than the documentation suggests. Input flags go before -i. Output flags go after. Put -ss before -i for fast seeking (it skips to the timestamp before decoding). Put it after -i for frame-accurate seeking (it decodes everything up to the timestamp). The difference between a 0.1-second operation and a 30-second operation is where you place one flag.
Error messages are cryptic. "Invalid data found when processing input" could mean a corrupted file, a missing codec, an unsupported format, or a filename encoding issue. The way to debug ffmpeg is to add -v debug and read the full output. The answer is always in there, buried in 200 lines of log output.
What It Replaces
| SaaS Tool / Service | What ffmpeg Does Instead | Monthly Savings |
|---|---|---|
| Cloudinary / Mux (video processing) | Compress, transcode, resize locally | $20-$100+ |
| Descript / Riverside (audio extraction) | -vn -c:a libmp3lame |
$24-$40 |
| Canva video / Kapwing (clip creation) | -ss -t -c copy |
$13-$25 |
| Thumbnail generators | -frames:v 1 |
$0-$10 |
| Format converters (online) | ffmpeg -i input.webm output.mp4 |
$0 (but reclaims privacy) |
For a solo builder producing even modest amounts of video or audio content, that's $50-$150/month in tools replaced by a single binary that ships with every Linux server and installs in 10 seconds on Mac.
Where It Fits in the Stack
ffmpeg is infrastructure, not an application. It sits at the bottom of your content pipeline and everything else builds on top of it. Record with whatever tool you prefer. Process with ffmpeg. Serve from your own storage or CDN.
The learning curve is real, but it's front-loaded. You'll spend an afternoon figuring out the flags you need for your specific workflow. After that, you have shell scripts that run the same way every time, on any machine, with no login required. No service to go down. No pricing change to react to. No terms of service update that removes a feature you depend on.
These commands cover 90% of what a solo builder doing content work will need. Bookmark the ones that apply to your workflow. The rest you'll find when you need them, one Stack Overflow answer at a time.
Twenty-six years old and still the best tool for the job. That's the kind of software worth learning.