ffmpeg does almost anything to a media file from one command line: convert a container, cut a clip, resize, strip or swap the audio, build a GIF, re-encode at a target quality. The flag surface is enormous and the documentation is a wall, so this page is the reference I actually keep open: the canonical 2026 command for each common task, grouped by what you are trying to do, with a one-line "why" on each. Every command below uses the current spellings, not the legacy aliases that still float around old blog posts.
Unlike a website-based downloader, ffmpeg is its own tool: free, open source, no account, and it runs entirely on your machine. There is nothing to agree to and nothing to upload. What you do with the output file is between you and the rights holder of the source.
The modern syntax in one minute
Old ffmpeg tutorials are full of -vcodec, -acodec, -ab, and -vframes. Those still work as aliases, but they are the legacy form and they make examples harder to read. The current spellings, and the few knobs that matter, are short enough to learn in a minute:
-c:vand-c:aset the codecs, not-vcodec/-acodec. So-c:v libx264 -c:a aac. Bitrate is-b:a 192k(audio) or-b:v 2M(video), and-frames:v 1grabs a single frame, not-vframes 1.-c copyis stream copy: remux with no re-encode. It is instant and lossless because the audio and video bytes are passed through untouched. Reach for it any time you are only changing the container or cutting on keyframes. The opposite is a re-encode, which is slow but lets you change codec, quality, resolution, or do frame-accurate cuts.-crfis the quality knob forlibx264andlibx265(constant rate factor: lower is better quality and a bigger file). For x264 the sane range is 18 to 28, default 23; x265 defaults to 28; the AV1 encoderlibsvtav1uses a wider 0 to 63 scale (its own default is 35, but a CRF around 30 is a common starting point).-presettrades encode speed for compression efficiency (ultrafasttoveryslowon x264/x265; a numeric-preset 6style on SVT-AV1): a slower preset gives a smaller file at the same quality, not better quality.-yoverwrites the output without asking,-nnever overwrites.-hide_bannerdrops the version preamble so the useful output is not buried. Put input options like-ssbefore-i, and output options after the last-i. That ordering is not cosmetic: ffmpeg applies options to the next file on the command line, so where they sit changes what they do.
That is the whole mental model. The cheat sheet below is those rules applied to each task.
Jump to: Basics | Trim and cut | Resize and crop | Audio | Video to GIF | Codecs and quality | Speed | Concat and merge | Subtitles | Common fixes
ffmpeg Cheat Sheet
The canonical 2026 command for each common task. -c copy means no re-encode (instant, lossless); -crf is the quality knob for x264/x265/AV1.
The rest of this page is the detail behind the rows: the gotchas that turn a command that "runs" into one that does what you meant.
Basics
Before transforming a file, look at it. ffprobe reports the streams, codecs, resolution, and duration:
ffprobe -hide_banner in.mp4That tells you whether -c copy is even an option (you cannot stream-copy a codec the target container does not support) and what the audio and video tracks actually are. For a single value in a script, ask for one field:
ffprobe -v error -show_entries format=duration -of csv=p=0 in.mp4A plain container change re-encodes by default. If the existing codecs already fit the target container, skip the re-encode entirely with -c copy. Remuxing an MKV to MP4 this way takes a second and loses nothing:
ffmpeg -i in.mkv -c copy out.mp4Trim and cut
There are two ways to cut, and the difference is the single most common ffmpeg confusion. With -ss before -i and -c copy, the cut is fast and lossless but lands on the nearest keyframe, so the start can be a fraction of a second early or late:
ffmpeg -ss 00:00:05 -t 12 -i in.mp4 -c copy out.mp4Use -t for a duration or -to for an absolute end timestamp. When you need a frame-accurate cut, drop -c copy, move -ss after -i, and let ffmpeg re-encode:
ffmpeg -i in.mp4 -ss 00:00:05 -t 12 -c:v libx264 -crf 18 out.mp4It is slower, but the cut lands exactly where you asked. For the full treatment of keyframe alignment and splitting one file into segments, see trim and cut a video with ffmpeg.
Resize and crop
Scaling takes a scale filter. Set one dimension and use -2 for the other so ffmpeg keeps the aspect ratio and rounds to an even number (most codecs reject odd dimensions):
ffmpeg -i in.mp4 -vf scale=1280:-2 out.mp4Cropping uses crop=w:h:x:y: output width, output height, then the left and top offset of the box. Omit x:y and ffmpeg centers the crop for you:
ffmpeg -i in.mp4 -vf crop=500:500:0:0 -c:a copy out.mp4Add -c:a copy so the audio is passed through rather than silently re-encoded. You can use the input-dimension variables in_w and in_h to express a ratio crop, like center-cropping to 16:9 regardless of source size. The full filter reference, plus using cropdetect to find black bars automatically, is in crop a video with ffmpeg.
Audio
To pull the audio out of a video, -vn drops the video stream. If the audio codec already fits the target container, copy it out with no quality loss:
ffmpeg -i in.mp4 -vn -c:a copy out.m4aWhen the target format differs (say you need MP3), re-encode and pick a quality. -q:a 2 is variable-bitrate around 190 kbps, a better default than a fixed CBR rate:
ffmpeg -i in.mp4 -vn -c:a libmp3lame -q:a 2 out.mp3The reverse, removing audio, copies the video untouched and drops the sound with -an:
ffmpeg -i in.mp4 -c:v copy -an out.mp4To replace or add a track, give ffmpeg two inputs and map explicitly so it does not guess. -shortest stops at the shorter of the two so you do not get a long silent tail:
ffmpeg -i video.mp4 -i audio.m4a -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 -shortest out.mp4For the full extract workflow, including grabbing one track out of a multi-track file with -map 0:a:1, see extract audio from a video with ffmpeg.
Video to GIF
A bare ffmpeg -i in.mp4 out.gif produces a muddy, dithered GIF because it maps every frame against a single global palette. The fix is a two-step palette: palettegen builds an optimal 256-color palette from the source, paletteuse maps the frames to it. The single-command form uses split so the input is read once and no temp file is needed:
ffmpeg -i in.mp4 -vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" out.giffps and scale are the two biggest file-size levers; flags=lanczos gives a sharp downscale. To grab a short clip first, fast-seek with -ss before -i:
ffmpeg -ss 2 -t 3 -i in.mp4 -vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" clip.gifThe full walkthrough, including per-frame palettes and the "use MP4 instead of GIF for big files" reality, is in convert video to a high-quality GIF with ffmpeg. Once you have a GIF, optimize and compress it with gifsicle shaves it down further, and converting it to WebP is usually a bigger win than any GIF tweak.
Codecs and quality
For H.264, the universal default, the quality knob is -crf (lower is better, 23 is the baseline) and -preset trades encode time for a smaller file at the same quality:
ffmpeg -i in.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 192k out.mp4libx265 (HEVC) gets you roughly half the file size at the same visual quality, at the cost of slower encoding and patchier playback support; its CRF scale runs a little different (default 28):
ffmpeg -i in.mp4 -c:v libx265 -crf 28 -preset medium -c:a aac -b:a 192k out.mp4AV1 through libsvtav1 compresses best of the three and is royalty-free. Its -crf runs 0 to 63 (the encoder's own default is 35; a CRF around 30 is a common starting point for 1080p) and -preset is numeric from 0 to 13, where a lower number is slower and smaller:
ffmpeg -i in.mp4 -c:v libsvtav1 -crf 30 -preset 6 -c:a libopus -b:a 128k out.mp4Note -c copy cannot bridge incompatible codecs, so converting between MP4 and WebM always re-encodes. The codec-by-codec tradeoffs and the VP9 path are in convert WebM to MP4 (and back) with ffmpeg.
Speed
The setpts filter rescales the video presentation timestamps: a smaller multiplier plays faster. For video alone, drop the audio with -an:
ffmpeg -i in.mp4 -filter:v "setpts=0.5*PTS" -an out.mp4To speed up the audio in sync, use atempo, which changes tempo without shifting pitch. The catch readers hit constantly: while current ffmpeg accepts a single atempo value from 0.5 to 100.0, any tempo above 2.0 skips samples rather than blending them, so for clean results you chain atempo instances each within the 0.5 to 2.0 sweet spot. Here is a clean 2x with both streams:
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" out.mp4For a clean 4x you would write atempo=2.0,atempo=2.0. The chaining trick and smooth slow motion via frame interpolation are in speed up or slow down a video with ffmpeg.
Concat and merge
If the files share the same codecs, parameters, and resolution, the concat demuxer joins them with no re-encode. Write a text file listing them, then:
ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4where list.txt holds one file 'clip1.mp4' line per input. When the inputs differ (different codec, resolution, or framerate), the concat demuxer will produce a broken file; use the concat filter instead, which re-encodes everything to a common format:
ffmpeg -i a.mp4 -i b.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]" -map "[v]" -map "[a]" out.mp4Subtitles
There are two ways to attach subtitles, and they are not interchangeable. Soft subtitles ride along as a selectable track the viewer can toggle; for an MP4 the subtitle codec is mov_text:
ffmpeg -i in.mp4 -i subs.srt -c copy -c:s mov_text out.mp4Hard subtitles are burned into the picture, so they always show and survive any re-upload, but they require a re-encode and cannot be turned off:
ffmpeg -i in.mp4 -vf subtitles=subs.srt out.mp4Common fixes
A few errors come up so often they are worth memorizing. An MP4 that will not start playing until fully downloaded has its moov atom at the end; move it to the front:
ffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4The dreaded height not divisible by 2 error means a codec rejected an odd dimension after scaling. Force both dimensions even:
ffmpeg -i in.mp4 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" out.mp4And a video that displays sideways (common with phone footage) rotates with transpose:
ffmpeg -i in.mp4 -vf "transpose=1" out.mp4transpose=1 is 90 degrees clockwise, transpose=2 counter-clockwise. To grab a single still frame for a thumbnail instead, see extract a thumbnail or frame from a video with ffmpeg.
FAQ
See also
- Trim and cut a video with ffmpeg: the keyframe vs frame-accurate tradeoff,
-ssplacement, and splitting into segments. - Crop a video with ffmpeg: the
crop=w:h:x:yorder spelled out, ratio crops, andcropdetectfor black bars. - Convert video to a high-quality GIF with ffmpeg: the full
palettegen/paletteuseworkflow and tuning. - Extract audio from a video with ffmpeg: stream-copy vs re-encode, bitrate guidance, and picking a specific track.
- Speed up or slow down a video with ffmpeg:
setpts, theatempoclamp and chaining, and smooth slow motion. - Convert WebM to MP4 (and back) with ffmpeg: codec tradeoffs and the
-crfsettings per codec. - Extract a thumbnail or frame from a video with ffmpeg: first frame, timestamp, frame number, and the
thumbnailfilter. - Optimize and compress an animated GIF with gifsicle:
--lossy,--colors, and downscaling to shrink a finished GIF. - Convert images to WebP from the command line:
cwebpandgif2webp, usually a bigger win than tuning a GIF.
Sources
Authoritative references this article was fact-checked against.
- ffmpeg documentation (official)ffmpeg.org
- ffmpeg filters documentation (official)ffmpeg.org
- ffmpeg codecs documentation (official)ffmpeg.org
- ffmpeg wiki: Encode/AV1 (SVT-AV1)trac.ffmpeg.org
- ffmpeg wiki: Encode/MP3 (libmp3lame VBR quality)trac.ffmpeg.org
- ffmpeg wiki: Encode/H.265 (libx265 CRF and preset)trac.ffmpeg.org





