Every Linux box worth its salt has ffmpeg one apt install away, and almost nobody has read its manual. The manual is 100,000 words of flags; real life is a dozen jobs you do over and over. The trap most people fall into is copying a random invocation from a forum, watching it work once, and never learning why — so the next file breaks in a new and exciting way.

This is the 12-recipe field guide. Learn these and you stop cargo-culting flags.

Ground rules before the recipes

Three things make every ffmpeg command readable:

  • -i marks an input. Options placed before -i configure the input; options after it configure the output. Order matters.
  • -c copy means "don't re-encode." It copies the stream as-is: instant and lossless. Anything else re-encodes, which costs CPU and (slightly) quality.
  • Test on a copy. -y overwrites output without asking; -n refuses to overwrite. For batch jobs, -n is the safe default.

1. Convert anything to a plays-everywhere MP4

BASH
ffmpeg -i input.mkv -c:v libx264 -crf 23 -preset medium -c:a aac -movflags +faststart output.mp4

This is the one you'll use weekly. -crf 23 sets quality (lower is better and bigger; 18–28 is the sane range). -preset medium trades encoding speed for file size — veryfast for rush jobs, slow when size matters. -movflags +faststart moves the metadata to the front so web players start before the whole file downloads.

Gotcha: some old players and picky hardware choke on anything but 8-bit 4:2:0. Add -pix_fmt yuv420p and the "black screen on grandma's TV" class of bugs disappears.

2. Shrink a video for messaging apps

BASH
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset veryfast -vf "scale=1280:-2" -c:a aac -b:a 96k output.mp4

CRF 28 plus downscaling to 1280px wide turns a 200 MB clip into something you can actually send. Audio at 96k is plenty for phone speakers.

Gotcha: scale=1280:-2 — the -2 keeps the aspect ratio and forces an even height. x264 requires even dimensions; scale=1280:-1 on an odd-height source fails with a cryptic error.

3. Extract audio as MP3

BASH
ffmpeg -i video.mp4 -vn -c:a libmp3lame -q:a 2 audio.mp3

-vn drops the video stream; -q:a 2 is VBR quality (~190 kbps, transparent for most ears).

Gotcha: forget -vn and ffmpeg errors out — MP3 can't hold a video stream, and the error message won't say that plainly.

4. Trim a clip without re-encoding

BASH
ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -c copy cut.mp4

Stream copy makes this instant: no quality loss, no waiting.

Gotcha: -ss before -i seeks fast but cuts at the nearest keyframe, so your cut point can drift a second or two. Put -ss after -i for frame-accurate cuts — slower, because it decodes everything up to that point. For sample-exact trims, drop -c copy and re-encode.

5. Make a GIF that doesn't look like a 1998 relic

BASH
ffmpeg -i input.mp4 -vf "fps=12,scale=480:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i input.mp4 -i palette.png -lavfi "fps=12,scale=480:-1:flags=lanczos[x];[x][1:v]paletteuse" out.gif

GIF only holds 256 colors; the two-pass palette trick picks the right 256 for your clip. Twelve fps and 480px wide keeps the file small enough to actually share.

Gotcha: the one-pass ffmpeg -i in.mp4 out.gif everyone tries first produces muddy, banded garbage. The palette pass is the entire trick.

6. Grab a thumbnail frame

BASH
ffmpeg -ss 00:00:42 -i video.mp4 -frames:v 1 -q:v 2 thumb.jpg

Seek to the moment, dump one frame. -q:v 2 sets JPEG quality (2–5 is the sweet spot).

Gotcha: -ss before -i is fast but lands on a keyframe, which might be a blurry scene change. For a precise frame, seek after -i — or just try a few timestamps; it's cheap.

7. Normalize podcast or interview audio

BASH
ffmpeg -i in.wav -af loudnorm=I=-16:TP=-1.5:LRA=11 out.wav

The loudnorm filter targets broadcast loudness standards (-16 LUFS is the podcast norm). One command, consistent volume.

Gotcha: single-pass loudnorm adjusts dynamically and may miss the target on tricky material. The correct workflow is two-pass: first pass with print_format=json to measure, second pass feeding the measured values in. For quick jobs one pass is fine; for published episodes, do both.

8. Join clips with no re-encode

BASH
printf "file 'a.mp4'\nfile 'b.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4

The concat demuxer stitches files together at stream level — instant, lossless.

Gotcha: every file must share the same codec, resolution, and container parameters. Mixing a phone clip with a screen recording? Re-encode instead (-c:v libx264 -crf 20) or the join will glitch.

9. Record your screen

BASH
ffmpeg -f x11grab -video_size 1920x1080 -framerate 30 -i :0.0+0,0 -c:v libx264 -preset ultrafast out.mp4

On X11 this just works: capture the display, encode fast, sort it out later.

Gotcha: on Wayland, x11grab can't see native Wayland windows — that's a security feature, not a bug. Use your compositor's built-in recorder (GNOME and KDE both have one), wf-recorder on wlroots compositors, or OBS. Don't fight the display server; route around it.

10. Extract subtitles

BASH
ffmpeg -i movie.mkv -map 0:s:0 subs.srt

-map 0:s:0 means "first input, subtitle streams, the first one." Without -map, ffmpeg picks a "best" video and audio stream and silently drops everything else.

Gotcha: streams are zero-indexed per type. 0:s:1 is the second subtitle track (often the forced/SDH one you actually want). Check with ffprobe first — that's recipe 12.

11. Batch-convert a whole folder

BASH
for f in *.mkv; do
  ffmpeg -n -i "$f" -c:v libx264 -crf 23 -c:a aac "${f%.mkv}.mp4"
done

Loop, convert, done. -n means "never overwrite" — the batch-safe choice when you're processing 50 files at 2 AM. "${f%.mkv}" strips the old extension.

Gotcha: quote "$f". Filenames with spaces will ruin your evening otherwise — the oldest shell trap in the book, still catching people.

12. Inspect a file before you touch it

BASH
ffprobe -v error -show_entries stream=codec_name,width,height,duration \
  -of default=noprint_wrappers=1 input.mp4

ffprobe ships with ffmpeg and answers the questions you should ask before guessing flags: what codec is this, what resolution, how long, which audio track is English.

Gotcha: "why is this file 4 GB" and "why does the audio drift out of sync" are both answered here in two seconds. Make this a reflex.

What this doesn't cover

Filter graphs, hardware encoding (-hwaccel, NVENC/VAAPI — same recipes, different -c:v), and streaming are the other 5%. And when you want preset-driven encoding with a progress bar instead of flags, HandBrake exists for a reason — no shame in it.

But for the daily work — convert, shrink, trim, extract, join, inspect — these twelve are the whole job. The manual stays on the shelf for the day something truly weird shows up.

Sources: FFmpeg Documentation · FFmpeg Wiki · ffprobe Documentation