32blogby StudioMitsu

FFmpeg Commands: A Practical Guide from Basics to Advanced

A comprehensive FFmpeg command reference covering video conversion, compression, trimming, GIF creation, watermarks, noise reduction, and more. Copy-paste ready.

14 min read
On this page

FFmpeg has a reputation for being intimidating. The command syntax is unusual, there are thousands of options, and error messages aren't always helpful. But the truth is, most of what people actually need to do with FFmpeg comes down to about a dozen commands.

This guide covers everything from basic operations to advanced techniques, with every command tested and ready to copy-paste.

What you'll learn

  • How FFmpeg commands are structured and how to read options
  • Video conversion, audio extraction, compression, trimming, and merging
  • GIF conversion, thumbnail extraction, and creating video from images
  • Watermarks, subtitles, cropping, and noise reduction
  • Inspecting media files in detail with ffprobe

How FFmpeg Commands Are Structured

Every FFmpeg command follows this pattern:

bash
ffmpeg [input options] -i input_file [output options] output_file

The position of options matters. Options placed before -i apply to the input. Options placed after -i apply to the output. This is different from most CLI tools and trips up a lot of newcomers.

Some examples:

bash
# Simplest possible command — just convert the format
ffmpeg -i input.mp4 output.avi

# Input option: seek to a specific position before reading
ffmpeg -ss 00:01:00 -i input.mp4 output_trimmed.mp4

# Output option: set the bitrate of the output
ffmpeg -i input.mp4 -b:v 1M output.mp4

Quick reference for common options:

OptionMeaningExample
-c:vVideo codec-c:v libx264
-c:aAudio codec-c:a aac
-b:vVideo bitrate-b:v 2M
-b:aAudio bitrate-b:a 192k
-rFrame rate-r 30
-sResolution-s 1920x1080
-ssSeek start position-ss 00:01:30
-tDuration in seconds-t 60
-toEnd timestamp-to 00:05:00
-vnNo videoFor audio-only extraction
-anNo audioFor silent video output

Converting Video Formats

Convert MP4 to AVI (or any other format)

bash
ffmpeg -i input.mp4 output.avi

FFmpeg reads the file extensions and automatically picks appropriate codecs. For simple format changes, this is all you need.

Change the container without re-encoding

bash
ffmpeg -i input.mp4 -c copy output.mkv

-c copy tells FFmpeg to copy all streams as-is, without re-encoding. This is instant and lossless — it just changes the wrapper format.

Convert iPhone MOV to MP4

bash
ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4

A common use case when sharing iPhone videos with people who aren't on Apple devices.

Extracting and Converting Audio

Extract audio from a video file

bash
ffmpeg -i input.mp4 -vn -c:a libmp3lame -q:a 2 output.mp3

What each option does:

  • -vn = no video (skip the video stream)
  • -c:a libmp3lame = encode audio as MP3
  • -q:a 2 = audio quality (0 is best, 9 is worst; 2 is excellent)

For higher quality, use AAC instead:

bash
ffmpeg -i input.mp4 -vn -c:a aac -b:a 192k output.m4a

Convert between audio formats

bash
# WAV to MP3
ffmpeg -i input.wav -c:a libmp3lame -b:a 320k output.mp3

# MP3 to FLAC (lossless)
ffmpeg -i input.mp3 -c:a flac output.flac

# Reduce audio bitrate (smaller file)
ffmpeg -i input.mp3 -b:a 128k output_compressed.mp3

Compressing Video

Reducing file size while preserving quality is probably the most common FFmpeg use case.

If you're unsure which codec to use, see H.264 vs H.265 vs AV1 Comparison for a detailed breakdown.

Compress with H.265 (HEVC)

bash
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -c:a aac output.mp4

The -crf (Constant Rate Factor) value controls the quality-compression tradeoff:

CRF rangeQualityFile size
Below 18Nearly losslessLarge
18–23High quality (typical use)Medium
24–28Acceptable (web delivery)Small
Above 28Visible degradationVery small

H.265 delivers roughly the same quality as H.264 at half the file size. The tradeoff is longer encoding time.

Compress with H.264

bash
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

H.264 has much broader device compatibility than H.265. The -preset option lets you trade speed for file size:

PresetEncoding speedFile size
ultrafastVery fastLargest
fastFastLarger
mediumBalanced (default)Medium
slowSlowSmaller
veryslowSlowestSmallest
bash
# Speed priority (processing lots of videos)
ffmpeg -i input.mp4 -c:v libx264 -preset fast -crf 23 output.mp4

# Quality priority (archival)
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 18 output.mp4

For a deeper dive into CRF tuning and codec selection, see the FFmpeg Video Compression Guide. To dramatically speed up encoding with your GPU, check out the FFmpeg GPU Encoding Guide.

Trimming, Cutting, and Merging

Cut a specific time range

bash
# Extract 3 minutes 30 seconds starting at 1:30 (= 1:30 to 5:00)
ffmpeg -ss 00:01:30 -t 00:03:30 -i input.mp4 -c copy output_clip.mp4
  • -ss 00:01:30 = start at 1 minute 30 seconds
  • -t 00:03:30 = extract 3 minutes 30 seconds
  • -c copy = no re-encoding (instant, lossless)

Placing -ss before -i uses input seeking, which jumps directly to the position without decoding everything before it. This makes trimming nearly instant even for very long videos.

You can also specify -t in seconds:

bash
# Extract 60 seconds starting at 1:30
ffmpeg -ss 00:01:30 -t 60 -i input.mp4 -c copy output_clip.mp4

If you prefer specifying an absolute end time, place both -ss and -to after -i:

bash
# From 1:30 to 5:00 (-to uses absolute input timestamps)
ffmpeg -i input.mp4 -ss 00:01:30 -to 00:05:00 -c copy output_clip.mp4

This is slower than input seeking (FFmpeg decodes from the start) but -to reliably refers to the absolute position in the input file.

Concatenate videos using a file list

For videos with the same codec and resolution, the file list method is fastest.

Create a text file listing all the videos to join (filelist.txt):

text
file 'video1.mp4'
file 'video2.mp4'
file 'video3.mp4'

Then run:

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

Merge videos with different formats or resolutions

When combining videos with different properties, re-encoding is required:

bash
ffmpeg -i video1.mp4 -i video2.mp4 \
  -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output_merged.mp4

Changing Resolution and Frame Rate

Resize video

bash
# Resize to 1920x1080
ffmpeg -i input.mp4 -s 1920x1080 output.mp4

# Resize width to 1280px, maintain aspect ratio
ffmpeg -i input.mp4 -vf scale=1280:-2 output.mp4

# Resize height to 720px, maintain aspect ratio
ffmpeg -i input.mp4 -vf scale=-2:720 output.mp4

Using -2 for one dimension tells FFmpeg to calculate that dimension automatically while preserving the aspect ratio. The -2 ensures the value is rounded to the nearest even number, which is required by most codecs.

Change frame rate

bash
# Convert to 30fps
ffmpeg -i input.mp4 -r 30 output.mp4

# Convert to 60fps
ffmpeg -i input.mp4 -r 60 output.mp4

Reducing the frame rate (e.g., 60fps to 30fps) significantly reduces file size with minimal perceived quality loss for most content.

GIF Conversion, Thumbnails, and Images to Video

Convert video to GIF

A naive conversion produces large files with poor color quality. Palette optimization dramatically improves both:

bash
# Step 1: Generate an optimized palette
ffmpeg -i input.mp4 -vf "fps=15,scale=480:-2:flags=lanczos,palettegen" palette.png

# Step 2: Convert using the palette
ffmpeg -i input.mp4 -i palette.png \
  -lavfi "fps=15,scale=480:-2:flags=lanczos[x];[x][1:v]paletteuse" output.gif

What each part does:

  • fps=15 = reduce to 15 frames per second (plenty for GIFs)
  • scale=480:-2 = resize to 480px wide
  • flags=lanczos = high-quality resizing algorithm
  • palettegen / paletteuse = generate and apply an optimized color palette

You can also do it in a single command:

bash
ffmpeg -i input.mp4 \
  -lavfi "fps=15,scale=480:-2:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
  output.gif

Extract thumbnails from video

bash
# Extract a single frame at the 10-second mark
ffmpeg -ss 10 -i input.mp4 -frames:v 1 thumbnail.jpg

# Extract frames at regular intervals (every 10 seconds)
ffmpeg -i input.mp4 -vf "fps=1/10" thumbnail_%03d.jpg

# Extract keyframes only (fastest)
ffmpeg -skip_frame nokey -i input.mp4 -fps_mode vfr keyframe_%03d.jpg

-frames:v 1 means "output only 1 video frame." fps=1/10 means "1 frame every 10 seconds."

Create video from an image sequence

bash
# From image001.png, image002.png, image003.png...
ffmpeg -framerate 24 -i image%03d.png -c:v libx264 -pix_fmt yuv420p output.mp4
  • -framerate 24 = 24 frames per second
  • image%03d.png = 3-digit zero-padded sequence (001, 002, 003...)
  • -pix_fmt yuv420p = compatibility mode for most players

Useful for time-lapse videos and animated sequences.

Loop a single image into a video

bash
ffmpeg -loop 1 -i input.jpg -t 10 -c:v libx264 -pix_fmt yuv420p output.mp4

Useful for social media thumbnails and presentation backgrounds.

Watermarks, Subtitles, Cropping, and Noise Reduction

Add a watermark (image overlay)

bash
# Place a logo in the bottom-right corner (10px margin)
ffmpeg -i input.mp4 -i logo.png \
  -filter_complex "overlay=W-w-10:H-h-10" output.mp4

The overlay filter coordinates work like this:

  • W / H = input video width / height
  • w / h = overlay image width / height
  • W-w-10 = position from the right edge minus logo width minus 10px

Common placement patterns:

Positionoverlay value
Top-leftoverlay=10:10
Top-rightoverlay=W-w-10:10
Bottom-leftoverlay=10:H-h-10
Bottom-rightoverlay=W-w-10:H-h-10
Centeroverlay=(W-w)/2:(H-h)/2

Draw text on video

bash
ffmpeg -i input.mp4 \
  -vf "drawtext=text='Sample':fontsize=24:fontcolor=white:x=10:y=10" \
  output.mp4

Soft subtitles (togglable in the player)

bash
ffmpeg -i input.mp4 -i subtitle.srt -c:v copy -c:a copy -c:s mov_text output.mp4

The subtitle data is stored inside the MP4 file but not burned into the video. Players that support it let users turn subtitles on or off.

Hard subtitles (burned into the video)

bash
ffmpeg -i input.mp4 -vf subtitles=subtitle.srt output.mp4

This permanently renders the subtitles onto the video frames. They'll always be visible regardless of player, but can't be removed later.

For AI-powered automatic subtitle generation, see Auto-Generate Subtitles with FFmpeg and Whisper.

Crop (cut out a region)

bash
# Crop 640x480 from the center
ffmpeg -i input.mp4 -vf "crop=640:480" output.mp4

# Crop from the top-left corner
ffmpeg -i input.mp4 -vf "crop=640:480:0:0" output.mp4

# Detect black bars automatically
ffmpeg -i input.mp4 -vf "cropdetect" -f null - 2>&1 | grep cropdetect

The crop filter syntax is crop=width:height:x:y. Omitting x and y crops from the center.

For black bar removal, use a two-step process. First detect the crop values, then apply them:

bash
# cropdetect output example: crop=1920:800:0:140
ffmpeg -i input.mp4 -vf "crop=1920:800:0:140" output.mp4

Noise reduction

For video noise, use the nlmeans (Non-Local Means) filter:

bash
ffmpeg -i input.mp4 -vf "nlmeans=s=3.5:p=7:r=15" output.mp4
  • s = denoising strength (higher = stronger; default 1.0)
  • p = patch size (odd number; default 7)
  • r = search radius (odd number; default 15)

For audio noise, use the arnndn (Recurrent Neural Network) filter. The model file must be downloaded separately:

bash
# Download the model (one-time setup)
curl -LO https://github.com/richardpl/arnndn-models/raw/master/bd.rnnn

# Run noise reduction
ffmpeg -i input.mp4 -af "arnndn=m=bd.rnnn" output.mp4

Model files are available from the arnndn-models repository. bd.rnnn is a general-purpose noise reduction model that works well for background noise in meeting recordings and podcasts.

Inspecting Media with ffprobe

ffprobe is a media analysis tool installed alongside FFmpeg. Use it to check codecs, resolution, bitrate, and more before starting a conversion.

Display file information

bash
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
  • -v quiet = suppress the FFmpeg banner
  • -print_format json = output in JSON format
  • -show_format = container info (format, duration, bitrate)
  • -show_streams = stream info (codec, resolution, fps)

Common ffprobe queries

bash
# Show only resolution
ffprobe -v error -select_streams v:0 \
  -show_entries stream=width,height -of csv=p=0 input.mp4

# Show only duration (seconds)
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4

# Show codec name
ffprobe -v error -select_streams v:0 \
  -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 input.mp4

Making a habit of checking the source file before encoding helps you avoid unexpected conversion results.

Common Questions

How do I adjust audio volume?

bash
# Double the volume
ffmpeg -i input.mp4 -af volume=2.0 output.mp4

# Halve the volume
ffmpeg -i input.mp4 -af volume=0.5 output.mp4

How do I rotate a video?

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

# Rotate 180 degrees
ffmpeg -i input.mp4 -vf "hflip,vflip" output.mp4

How do I change playback speed?

bash
# 2x speed (both video and audio)
ffmpeg -i input.mp4 -vf setpts=0.5*PTS -af atempo=2.0 output.mp4

# 0.5x speed (slow motion)
ffmpeg -i input.mp4 -vf setpts=2.0*PTS -af atempo=0.5 output.mp4

How do I force overwrite an existing output file?

bash
ffmpeg -y -i input.mp4 output.mp4

The -y flag skips the "file already exists, overwrite?" prompt.

What about licensing for commercial projects?

For details on GPL vs LGPL and what to include when redistributing, see the FFmpeg Commercial License Guide.

Next Steps: Learning FFmpeg

Once you've worked through the commands above, here's how to go deeper.

Official documentation

Start here. It's in English and comprehensive.

FFmpeg rewards hands-on practice over passive reading. A structured progression:

  1. Basic commands (this article) — format conversion, audio extraction, trimming
  2. Filters — start with scale and crop, then move to filter_complex. The Video Compression Guide covers CRF tuning in depth
  3. Encoding parameters — CRF vs. bitrate control, codec-specific tuning (x264, x265, SVT-AV1). See the GPU Encoding Guide for hardware acceleration
  4. AutomationPython integration for batch processing, VPS encoding server for remote offloading

Community resources

  • Stack Overflow — the [ffmpeg] tag has thousands of answered questions
  • Reddit r/ffmpeg — practical discussion, good for specific use-case questions
  • FFmpeg mailing list (ffmpeg-user@ffmpeg.org) — developers sometimes respond directly

Wrapping Up

Here's a quick reference table for the most common operations:

TaskKey options
Format conversionffmpeg -i input.mp4 output.avi
Lossless remux-c copy
Audio extraction-vn -c:a libmp3lame
H.265 compression-c:v libx265 -crf 28
Trim a clip-ss start -to end -c copy
Merge clips-f concat -i filelist.txt
Resize-vf scale=1280:-2
GIF conversionpalettegen + paletteuse
Thumbnail extraction-frames:v 1
Watermark-filter_complex overlay=...
Burn subtitles-vf subtitles=subtitle.srt
Crop-vf crop=width:height:x:y
Noise reduction-vf nlmeans / -af arnndn

The best way to learn FFmpeg is to start with one concrete task — say, compressing a video or extracting audio — and then gradually explore from there.

For automating repetitive tasks, Python integration is the way to go: