MeshWorld India Logo MeshWorld.
Cheatsheet FFmpeg Video Terminal Developer Tools Linux 10 min read

FFmpeg Cheat Sheet: Convert, Compress & Edit Video

Jena
By Jena
| Updated: May 16, 2026
FFmpeg Cheat Sheet: Convert, Compress & Edit Video
TL;DR
  • FFmpeg anatomy: ffmpeg -i input.mp4 [options] output.ext
  • -c copy skips re-encoding (fastest, lossless quality) — use whenever you just need to trim or remux
  • -crf 23 controls H.264 quality: lower = better quality, larger file (0–51 scale, 18–28 is practical range)
  • -vf applies video filters: scale, crop, fps, overlay, palette
  • Always test with a short clip (-t 5) before running on large files

Quick install

| Platform | Command | |---|---| | macOS (Homebrew) | brew install ffmpeg | | Ubuntu / Debian | sudo apt install ffmpeg | | Windows | Download from ffmpeg.org/download.html → add to PATH | | Check version | ffmpeg -version | | Check codecs | ffmpeg -codecs |


Quick reference — most-used flags

| Flag | Meaning | |---|---| | -i input.mp4 | Input file (always before output options) | | -c copy | Copy streams without re-encoding (fast) | | -c:v libx264 | Encode video with H.264 | | -c:v libx265 | Encode video with H.265 (HEVC) — 40% smaller than H.264 | | -c:v libvpx-vp9 | Encode video with VP9 (web/WebM) | | -c:a aac | Encode audio with AAC | | -c:a libmp3lame | Encode audio with MP3 | | -c:a copy | Copy audio without re-encoding | | -an | Remove audio (no audio stream) | | -vn | Remove video (no video stream — audio extraction) | | -crf 23 | Quality factor for H.264/H.265 (lower = better) | | -b:v 2M | Set target video bitrate (2 Mbps) | | -b:a 128k | Set audio bitrate (128 kbps) | | -r 30 | Set output frame rate | | -t 10 | Limit duration to 10 seconds | | -ss 00:00:30 | Seek/start from 30 seconds | | -to 00:01:00 | End at 1 minute | | -vf "filter" | Apply a video filter | | -af "filter" | Apply an audio filter | | -y | Overwrite output without asking | | -n | Skip if output file exists |


Format conversion

Re-wrapping without re-encoding (fastest, no quality loss):

bash
# MP4 → MKV (same streams, different container)
ffmpeg -i input.mp4 -c copy output.mkv

# MKV → MP4
ffmpeg -i input.mkv -c copy output.mp4

# MOV → MP4 (iPhone exports)
ffmpeg -i input.mov -c copy output.mp4

# AVI → MP4
ffmpeg -i input.avi -c:v libx264 -c:a aac output.mp4

# MP4 → WebM (re-encode for web)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 33 -b:v 0 -c:a libopus output.webm

Compress video for web

H.264 (best compatibility, works in all browsers and devices):

bash
# Good quality / reasonable size (CRF 23)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k output.mp4

# Smaller file, slight quality drop (CRF 28)
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k output.mp4

# Maximum quality (CRF 18)
ffmpeg -i input.mp4 -c:v libx264 -crf 18 -preset slow -c:a aac -b:a 192k output.mp4

H.265 / HEVC (half the size of H.264 at same quality — iOS 11+, most modern browsers with codec support):

bash
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset fast -c:a aac -b:a 128k output.mp4

CRF quality guide

| CRF | Quality | File size | Use for | |---|---|---|---| | 0 | Lossless | Very large | Archival | | 18 | Near-lossless | Large | Master file | | 23 | Good | Medium | General web | | 28 | Acceptable | Small | Mobile, social | | 35+ | Poor | Very small | Not recommended |

Preset speed guide

| Preset | Speed | File size | |---|---|---| | ultrafast | Fastest encode | Largest file | | fast | Fast | Slightly larger | | medium (default) | Balanced | Balanced | | slow | Slow | Smaller file | | veryslow | Very slow | Smallest file |


Resize and scale

bash
# Scale to 1280px wide, maintain aspect ratio
ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4

# Scale to 720p height, maintain aspect ratio
ffmpeg -i input.mp4 -vf "scale=-1:720" output.mp4

# Force exact resolution (may stretch)
ffmpeg -i input.mp4 -vf "scale=1920:1080" output.mp4

# Scale to 1080p but pad to exact 16:9 (letterbox)
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" output.mp4

# Scale with even dimensions (required by some encoders)
ffmpeg -i input.mp4 -vf "scale=1280:trunc(ow/a/2)*2" output.mp4

Trim and cut

The fastest way uses -c copy (no re-encoding):

bash
# From 30s to 90s (60-second clip)
ffmpeg -ss 00:00:30 -to 00:01:30 -i input.mp4 -c copy output.mp4

# From 30s, for 10 seconds
ffmpeg -ss 00:00:30 -t 10 -i input.mp4 -c copy output.mp4

# From the beginning, first 60 seconds
ffmpeg -i input.mp4 -t 60 -c copy output.mp4
-ss Before vs After -i

Placing -ss before -i (as above) seeks efficiently using keyframes — fast but may be off by a fraction of a second. Placing -ss after -i decodes every frame — slow but frame-accurate. For social media clips where exact cuts matter, use -ss after -i and remove -c copy to re-encode.

bash
# Frame-accurate cut (re-encodes — slower but precise)
ffmpeg -i input.mp4 -ss 00:00:30 -to 00:01:30 -c:v libx264 -crf 23 output.mp4

Audio operations

bash
# Extract audio as MP3
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3

# Extract audio as AAC
ffmpeg -i input.mp4 -vn -c:a aac -b:a 128k output.aac

# Extract audio losslessly as FLAC
ffmpeg -i input.mp4 -vn -c:a flac output.flac

# Remove audio from video
ffmpeg -i input.mp4 -an -c:v copy output.mp4

# Replace audio in a video
ffmpeg -i video.mp4 -i audio.mp3 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4

# Change audio volume
ffmpeg -i input.mp4 -af "volume=1.5" output.mp4   # 1.5x louder

# Normalize audio (loudnorm)
ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" output.mp4

# Fade in audio (2 second fade starting at 0)
ffmpeg -i input.mp4 -af "afade=t=in:ss=0:d=2" output.mp4

# Add silent audio to a silent video
ffmpeg -i input.mp4 -f lavfi -i anullsrc=r=44100:cl=stereo -c:v copy -c:a aac -shortest output.mp4

Create GIFs

Good GIFs require a two-pass approach for proper color palette:

bash
# Step 1: generate palette
ffmpeg -i input.mp4 -ss 5 -t 3 -vf "fps=12,scale=480:-1:flags=lanczos,palettegen" palette.png

# Step 2: create GIF using the palette
ffmpeg -i input.mp4 -i palette.png -ss 5 -t 3 \
  -filter_complex "fps=12,scale=480:-1:flags=lanczos[x];[x][1:v]paletteuse" \
  output.gif

One-liner (lower quality but simpler):

bash
ffmpeg -i input.mp4 -ss 5 -t 3 -vf "fps=10,scale=320:-1" output.gif

| Parameter | Adjust for | |---|---| | fps=12 | Smoothness (8–15 for GIFs) | | scale=480:-1 | Width (height auto) | | -t 3 | Duration in seconds | | palettegen | Color accuracy (worth the two-pass) |


Screenshots and thumbnails

bash
# Single screenshot at 10 seconds
ffmpeg -i input.mp4 -ss 00:00:10 -frames:v 1 thumbnail.jpg

# High-quality screenshot
ffmpeg -i input.mp4 -ss 00:00:10 -frames:v 1 -q:v 2 thumbnail.jpg

# Screenshot grid (one frame every 60 seconds)
ffmpeg -i input.mp4 -vf "fps=1/60" frames/thumb_%04d.jpg

# Video preview strip (contact sheet)
ffmpeg -i input.mp4 -vf "select=not(mod(n\,300)),scale=160:90,tile=10x5" contact_sheet.jpg

Merge and concatenate

bash
# Merge two videos (same codec/resolution — fast)
# Create a list file:
echo "file 'part1.mp4'
file 'part2.mp4'" > filelist.txt

ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

Stack videos side by side:

bash
# Side by side (horizontal)
ffmpeg -i left.mp4 -i right.mp4 \
  -filter_complex "[0:v][1:v]hstack=inputs=2" \
  output.mp4

# Stack vertically
ffmpeg -i top.mp4 -i bottom.mp4 \
  -filter_complex "[0:v][1:v]vstack=inputs=2" \
  output.mp4

Add text overlay (watermark)

bash
# Simple text overlay
ffmpeg -i input.mp4 \
  -vf "drawtext=text='My Watermark':fontsize=36:fontcolor=white:x=10:y=10" \
  output.mp4

# Timestamp overlay
ffmpeg -i input.mp4 \
  -vf "drawtext=text='%{pts\:hms}':fontsize=24:fontcolor=yellow:x=10:y=10" \
  output.mp4

# Image watermark (logo in bottom-right)
ffmpeg -i input.mp4 -i logo.png \
  -filter_complex "[1:v]scale=100:-1[logo];[0:v][logo]overlay=W-w-10:H-h-10" \
  output.mp4

Batch processing

bash
# Convert all MP4 files in current directory to WebM
for f in *.mp4; do
    ffmpeg -i "$f" -c:v libvpx-vp9 -crf 33 -b:v 0 -c:a libopus "${f%.mp4}.webm"
done

# Resize all videos to 1280px wide
for f in *.mp4; do
    ffmpeg -i "$f" -vf "scale=1280:-1" -c:a copy "resized_$f"
done

# Extract thumbnails from all videos
for f in *.mp4; do
    ffmpeg -i "$f" -ss 5 -frames:v 1 "${f%.mp4}.jpg"
done

Useful one-liners

bash
# Get video info (duration, resolution, codec)
ffprobe -v quiet -print_format json -show_streams input.mp4

# Speed up video 2x (with audio pitch correction)
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" output.mp4

# Slow down video 2x
ffmpeg -i input.mp4 -vf "setpts=2.0*PTS" -af "atempo=0.5" output.mp4

# Rotate video 90 degrees clockwise
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4

# Flip video horizontally (mirror)
ffmpeg -i input.mp4 -vf "hflip" output.mp4

# Stabilize shaky video
ffmpeg -i input.mp4 -vf "vidstabdetect" -f null -
ffmpeg -i input.mp4 -vf "vidstabtransform" output.mp4

# Convert image sequence to video
ffmpeg -framerate 24 -pattern_type glob -i "frames/*.jpg" -c:v libx264 output.mp4

# Create video from a single image with audio
ffmpeg -loop 1 -i image.jpg -i audio.mp3 -c:v libx264 -tune stillimage -c:a aac -shortest output.mp4

Summary

  • Always start with -c copy — only re-encode when you actually need to change codec or quality
  • CRF 23 + -preset fast + AAC 128k covers 90% of web video needs
  • Two-pass GIF generation (palettegen → paletteuse) produces dramatically better results than one-pass
  • Use -ss before -i for speed, after -i for frame accuracy
  • ffprobe is FFmpeg’s companion for inspecting files without modifying them

FAQ

Why is my output file larger than the input? You are re-encoding a compressed file to a lower CRF (higher quality) than the original, or using a slower preset without lowering the CRF. Try raising CRF by 2–3 points or using -c copy if no quality change is needed.

What is the difference between -t and -to? -t specifies a duration from the start point. -to specifies an absolute end timestamp. -ss 30 -t 10 ends at 40s. -ss 30 -to 40 also ends at 40s — but -to is relative to the beginning of the input, not the -ss start.

Can FFmpeg handle 4K and HDR video? Yes. For HDR (HDR10/Dolby Vision), use -c:v libx265 -x265-params "hdr-opt=1:repeat-headers=1:colorprim=bt2020:transfer=smpte2084:colormatrix=bt2020nc" to preserve HDR metadata.

How do I speed up FFmpeg processing? Enable GPU encoding: -c:v h264_nvenc (NVIDIA), -c:v h264_videotoolbox (Apple Silicon), -c:v h264_amf (AMD). Check available encoders with ffmpeg -encoders | grep h264.

What is the smallest file format for web video? AV1 (codec libaom-av1 or libsvtav1) produces the smallest files at a given quality — 30–40% smaller than H.265, 50% smaller than H.264. Trade-off: slow encoding and limited playback support below 2023-era devices.