MeshWorld India LogoMeshWorld.

FFmpeg Cheat Sheet: Convert, Compress & Edit Video

(Updated: May 16, 2026)
Listen to ArticleAI Speech
~10 min read narration
100%
FFmpeg Cheat Sheet: Convert, Compress & Edit Video

Quick install

PlatformCommand
macOS (Homebrew)brew install ffmpeg
Ubuntu / Debiansudo apt install ffmpeg
WindowsDownload from ffmpeg.org/download.html → add to PATH
Check versionffmpeg -version
Check codecsffmpeg -codecs

Quick reference — most-used flags

FlagMeaning
-i input.mp4Input file (always before output options)
-c copyCopy streams without re-encoding (fast)
-c:v libx264Encode video with H.264
-c:v libx265Encode video with H.265 (HEVC) — 40% smaller than H.264
-c:v libvpx-vp9Encode video with VP9 (web/WebM)
-c:a aacEncode audio with AAC
-c:a libmp3lameEncode audio with MP3
-c:a copyCopy audio without re-encoding
-anRemove audio (no audio stream)
-vnRemove video (no video stream — audio extraction)
-crf 23Quality factor for H.264/H.265 (lower = better)
-b:v 2MSet target video bitrate (2 Mbps)
-b:a 128kSet audio bitrate (128 kbps)
-r 30Set output frame rate
-t 10Limit duration to 10 seconds
-ss 00:00:30Seek/start from 30 seconds
-to 00:01:00End at 1 minute
-vf "filter"Apply a video filter
-af "filter"Apply an audio filter
-yOverwrite output without asking
-nSkip 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

CRFQualityFile sizeUse for
0LosslessVery largeArchival
18Near-losslessLargeMaster file
23GoodMediumGeneral web
28AcceptableSmallMobile, social
35+PoorVery smallNot recommended

Preset speed guide

PresetSpeedFile size
ultrafastFastest encodeLargest file
fastFastSlightly larger
medium (default)BalancedBalanced
slowSlowSmaller file
veryslowVery slowSmallest 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
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
ParameterAdjust for
fps=12Smoothness (8–15 for GIFs)
scale=480:-1Width (height auto)
-t 3Duration in seconds
palettegenColor 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.


Reader Quality Feedback

Did this technical guide help solve your problem?

Suggest Errata ($0)
Jena
Primary Author

Jena

Systems Engineer and Linux specialist. Deeply focused on infrastructure automation, terminal productivity, and performance tuning for high-availability systems.

Explore Author Archive
Compute Fuel & Open Testbed
100% Independent & Verified

Fuel High-Density, Zero-Fluff Engineering Deep-Dives

Every guide on MeshWorld is validated on physical Linux nodes and reproducible testbeds. If this article saved you hours of debugging or unblocked production, consider funding our next cluster run.

Weekly Dispatch

Join MeshWorld Dispatch

Get practical tutorials, system blueprints, and curated AI engineering notes straight to your inbox. No fluff, zero spam.

Zero spam. 1-click unsubscribe anytime.Prefer RSS?
Curated Continuations

Up Next in This Domain.

Browse Full Archive