Digital Minimalism · · 20 min read

Complete FFmpeg Tutorial and Reference Manual (2025)

Complete FFmpeg Tutorial and Reference Manual (2025)

What does FFmpeg have to do with digital minimalism? I think it does A lot. Do you use an application for screen capturing? Streaming? Screenshots? To convert videos, extract audio, change dimensions or frame rate, etc... There's a very high chance that under the hood your tool FFmpeg is the one doing the actual work. It's amazing how many tools rely on this "simple" open-source, command-line solution.

It may feel intimidating at first, but this unlocks an entirely new level of freedom and potential automations. Leading AI models know it very well, so if you're lazy like me, you can just ask for a command that does what you need and skip the learning curve...

If you want to dig a little deeper - here's a complete FFmpeg tutorial/manual!

Installation Instructions

Latest FFmpeg Version Information (2025)

  • Latest Stable: FFmpeg 8.0 "Huffman" (August 2025)
  • Previous Stable: FFmpeg 7.1.1 (March 2025)
  • Recommendation: Use git master builds for the latest features and active maintenance

Windows Installation

Download and Setup:

  1. Visit gyan.dev builds for the most popular Windows builds
  2. Choose your build type:
    • Release Essentials (27MB): Basic use, common codecs
    • Release Full: Advanced use, additional codecs
    • Git Master: Daily builds with latest features

Installation Steps:

:: Create directory
mkdir C:\ffmpeg
:: Extract downloaded files to C:\ffmpeg\
:: Your folder structure should be: C:\ffmpeg\bin\ffmpeg.exe

Add to PATH (Windows):

# Via PowerShell (Administrator)
$ffmpeg = 'C:\ffmpeg\bin'
$path = [Environment]::GetEnvironmentVariable('Path', 'Machine').TrimEnd([Char]';')
[Environment]::SetEnvironmentVariable("Path", "$path;$ffmpeg", 'Machine')

# Verify installation
ffmpeg -version

Method 2: Package Managers

# Chocolatey
choco install ffmpeg          # Essentials
choco install ffmpeg-full     # Full build

# Winget
winget install "FFmpeg (Essentials Build)"

# Scoop
scoop install ffmpeg
scoop install ffmpeg-gyan-nightly  # Git master builds

macOS Installation

# Install Homebrew (if not installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install FFmpeg
brew update
brew install ffmpeg

# With additional codecs
brew tap homebrew-ffmpeg/ffmpeg
brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-fdk-aac --with-librsvg

# Git master version
brew install ffmpeg --HEAD

# Update FFmpeg
brew update && brew upgrade ffmpeg

Static Build (Manual)

# Download from EverMeet
curl -O https://evermeet.cx/ffmpeg/ffmpeg-latest.zip
unzip ffmpeg-latest.zip
sudo cp ffmpeg /usr/local/bin/
sudo chmod +x /usr/local/bin/ffmpeg

# Verify installation
ffmpeg -version

Linux Installation

Debian/Ubuntu

# Update and install
sudo apt update
sudo apt install ffmpeg

# For latest version
sudo add-apt-repository ppa:savoury1/ffmpeg4
sudo apt update && sudo apt install ffmpeg

# Via Snap (latest version)
sudo snap install ffmpeg

Fedora/CentOS/RHEL

# Enable RPM Fusion
sudo dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
sudo dnf install -y https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

# Install FFmpeg
sudo dnf install ffmpeg ffmpeg-devel

Static Build (All Linux)

# Download and install
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
tar -xf ffmpeg-release-amd64-static.tar.xz
sudo cp ffmpeg-*-static/ffmpeg /usr/local/bin/
sudo cp ffmpeg-*-static/ffprobe /usr/local/bin/
sudo chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe

Build Types and Codec Support

  • Static Builds: Self-contained, no dependencies, larger files
  • Shared Builds: Smaller executable, requires separate libraries
  • Essentials: H.264, H.265, VP9, AAC, MP3, common formats
  • Full: Additional codecs, including ProRes, DNxHD,and specialized filters

Basic Concepts and Terminology

Core Concepts

Containers vs Codecs

Container: Wrapper format combining multiple streams

  • MP4: Universal compatibility, H.264/H.265 + AAC
  • MKV: Highly flexible, supports any codec
  • WebM: Open format, VP8/VP9 + Opus only
  • AVI: Legacy format with broad compatibility

Video Codecs: Compression algorithms for video

  • H.264 (libx264): Most widely supported, good compression
  • H.265 (libx265): Better compression, less compatibility
  • VP9: Open-source alternative to H.265
  • AV1: Next-generation codec, excellent compression

Audio Codecs: Compression algorithms for audio

  • AAC: Modern, efficient, widely supported
  • MP3: Legacy but universal compatibility
  • Opus: Superior quality at low bitrates
  • FLAC: Lossless compression for archival

Streams and Stream Mapping

Stream Types:

  • Video (v): Visual content
  • Audio (a): Sound content
  • Subtitle (s): Text overlays
  • Data (d): Metadata or other data

Stream Specifiers:

0:0      # First stream of first input
0:v:0    # First video stream of first input
0:a:1    # Second audio stream of first input

Quality Control Parameters

Video Quality:

  • CRF (Constant Rate Factor): 0-51 scale, lower = better quality
    • H.264: 18-28 range (23 default)
    • H.265: 20-30 range (28 default)
  • Bitrate: Fixed bitrate in bits per second (e.g., 2M = 2 Mbps)

Audio Quality:

  • Sample Rate: -ar 44100 (CD quality), -ar 48000 (high quality)
  • Bitrate: -b:a 128k (good), -b:a 320k (high quality)
  • Channels: -ac 2 (stereo), -ac 1 (mono)

Command Structure and Syntax

Basic Command Structure

ffmpeg [global_options] {[input_options] -i input} ... {[output_options] output} ...

Key Principles:

  • Options apply to the next specified file
  • Order matters: input options before -i, output options before output filename
  • Multiple inputs/outputs supported with separate option sets

Essential Global Options

-y                    # Overwrite output files without asking
-hide_banner         # Suppress startup information  
-loglevel quiet      # Suppress all output except errors
-stats              # Show encoding progress
-threads 0          # Auto-detect optimal thread count

Basic Examples

# Simple format conversion
ffmpeg -i input.mp4 output.avi

# With options
ffmpeg -y -hide_banner -i input.mp4 -c:v libx264 -crf 23 -c:a aac output.mp4

# Multiple inputs/outputs
ffmpeg -i input1.mp4 -i input2.mp4 -c copy output1.mkv -c:v libx264 output2.mp4

File Format Conversion

Common Video Conversions

MKV to MP4 (Stream Copy - Fastest)

# Windows CMD
ffmpeg -i input.mkv -c copy output.mp4

# macOS Terminal  
ffmpeg -i input.mkv -c copy output.mp4

# Linux Bash
ffmpeg -i input.mkv -c copy output.mp4

MKV to MP4 (Re-encode for Compatibility)

# All Platforms
ffmpeg -i input.mkv -c:v libx264 -crf 23 -c:a aac -movflags +faststart output.mp4

WebM to MP4 (High Quality)

# All Platforms
ffmpeg -i input.webm -c:v libx264 -preset slow -crf 22 -c:a aac -b:a 128k output.mp4

MOV to MP4 (Usually Stream Copy)

# All Platforms
ffmpeg -i input.mov -c copy output.mp4

Audio Format Conversions

Extract Audio to MP3

# Windows
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3

# macOS/Linux
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3

Convert to Different Audio Formats

# To AAC (M4A)
ffmpeg -i input.wav -c:a aac -b:a 256k output.m4a

# To FLAC (Lossless)  
ffmpeg -i input.wav -c:a flac -compression_level 12 output.flac

# To Opus (Modern Codec)
ffmpeg -i input.wav -c:a libopus -b:a 128k output.opus

Batch Conversion Scripts

Windows PowerShell

# Convert all MKV files to MP4
Get-ChildItem *.mkv | ForEach-Object {
    $outputFile = $_.BaseName + ".mp4"
    & ffmpeg -i $_.Name -c copy $outputFile
    Write-Host "Converted: $($_.Name)"
}

macOS/Linux Bash

#!/bin/bash
# Convert all MKV files to MP4
for file in *.mkv; do
    if [[ -f "$file" ]]; then
        output="${file%.*}.mp4"
        ffmpeg -i "$file" -c copy "$output"
        echo "Converted: $file"
    fi
done

Video Processing Operations

Scaling and Resolution Changes

Basic Scaling

# Scale to specific resolution
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4

# Maintain aspect ratio (auto height)
ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4

# Scale by percentage
ffmpeg -i input.mp4 -vf "scale=iw*0.5:ih*0.5" output.mp4

High-Quality Scaling

# Upscaling with Lanczos algorithm
ffmpeg -i input.mp4 -vf "scale=3840:2160:flags=lanczos" -c:v libx264 -crf 18 output.mp4

# Force aspect ratio with letterboxing
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Cropping Videos

Fixed Dimension Cropping

# Basic crop: width:height:x:y
ffmpeg -i input.mp4 -vf "crop=640:480:100:50" output.mp4

# Center crop
ffmpeg -i input.mp4 -vf "crop=640:480:(main_w-640)/2:(main_h-480)/2" output.mp4

# Remove black bars (crop sides)
ffmpeg -i input.mp4 -vf "crop=ih*16/9:ih" output.mp4

Automatic Black Border Detection

# Detect crop parameters
ffmpeg -i input.mp4 -vf cropdetect -f null -

# Apply detected crop (example output from detection)
ffmpeg -i input.mp4 -vf "crop=1072:1072:4:424" output.mp4

Rotation and Flipping

Rotation

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

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

# Rotate 180 degrees
ffmpeg -i input.mp4 -vf "transpose=2,transpose=2" output.mp4

# Arbitrary angle rotation
ffmpeg -i input.mp4 -vf "rotate=PI/4:fillcolor=black" output.mp4

Flipping

# Horizontal flip (mirror)
ffmpeg -i input.mp4 -vf "hflip" output.mp4

# Vertical flip
ffmpeg -i input.mp4 -vf "vflip" output.mp4

# Both flips (equivalent to 180° rotation)
ffmpeg -i input.mp4 -vf "hflip,vflip" output.mp4

Video Cutting and Trimming

Time-Based Cutting

# Cut from 10 seconds, duration 30 seconds
ffmpeg -i input.mp4 -ss 10 -t 30 -c copy output.mp4

# Cut from 1:30 to 2:45
ffmpeg -i input.mp4 -ss 00:01:30 -to 00:02:45 -c copy output.mp4

# Cut last 10 minutes
ffmpeg -sseof -600 -i input.mp4 -c copy output.mp4

Frame-Accurate Cutting

# Accurate seeking (slower but precise)
ffmpeg -i input.mp4 -ss 10 -t 30 -avoid_negative_ts make_zero -fflags +genpts output.mp4

# Re-encode for frame accuracy
ffmpeg -i input.mp4 -ss 10 -t 30 -c:v libx264 -c:a copy output.mp4

Audio Processing

Volume Control and Normalization

Basic Volume Adjustment

# Increase volume by 3dB
ffmpeg -i input.mp4 -af "volume=3dB" output.mp4

# Decrease volume by 50%
ffmpeg -i input.mp4 -af "volume=0.5" output.mp4

# Set specific volume level
ffmpeg -i input.mp4 -af "volume=2.0" output.mp4

Professional Audio Normalization

# EBU R128 Loudness Normalization (Recommended)
# Two-pass for best results
ffmpeg -i input.wav -af loudnorm=I=-16:LRA=11:tp=-1.5:print_format=json -f null -

# Apply with measured values from first pass
ffmpeg -i input.wav -af loudnorm=I=-16:LRA=11:tp=-1.5:measured_I=-23.01:measured_tp=-10.11:measured_LRA=18.80 output.wav

# Dynamic normalization (single pass)
ffmpeg -i input.wav -af "dynaudnorm=p=0.9:s=5" output.wav

Channel Manipulation

# Convert stereo to mono
ffmpeg -i stereo.wav -ac 1 mono.wav

# Extract left channel only
ffmpeg -i stereo.wav -af "pan=mono|c0=0.5*c0" left_only.wav

# Extract right channel only  
ffmpeg -i stereo.wav -af "pan=mono|c0=0.5*c1" right_only.wav

# Swap left and right channels
ffmpeg -i input.wav -af "pan=stereo|c0=c1|c1=c0" output.wav

Audio Filtering and Enhancement

Noise Reduction

# FFT-based noise reduction
ffmpeg -i noisy_audio.wav -af "afftdn=nr=12:nf=-25" clean_audio.wav

# High/low pass filtering
ffmpeg -i input.wav -af "highpass=f=80" output.wav  # Remove rumble
ffmpeg -i input.wav -af "lowpass=f=8000" output.wav  # Remove hiss

Equalization

# Parametric EQ - boost 1kHz by 5dB
ffmpeg -i input.wav -af "equalizer=f=1000:width_type=o:width=2:g=5" output.wav

# Multi-band EQ
ffmpeg -i input.wav -af "equalizer=f=100:g=3,equalizer=f=1000:g=-2,equalizer=f=5000:g=1" output.wav

Dynamic Range Compression

# Basic compression
ffmpeg -i input.wav -af "acompressor=threshold=0.05:ratio=4:attack=200:release=1000" compressed.wav

# Noise gate (remove quiet background noise)
ffmpeg -i input.wav -af "agate=threshold=0.1:attack=50:release=50" output.wav

Advanced Video Editing

Video Concatenation and Merging

Same Format Concatenation (Fast)

# Create file list
echo "file 'video1.mp4'" > files.txt
echo "file 'video2.mp4'" >> files.txt
echo "file 'video3.mp4'" >> files.txt

# Concatenate without re-encoding
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

Different Format Concatenation

# Two different formats with complex filter
ffmpeg -i input1.mp4 -i input2.wmv -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

# Scale videos before concatenating
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v]scale=1920:1080[v0];[1:v]scale=1920:1080[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

Multi-Layout Arrangements

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

# Vertical stacking
ffmpeg -i top.mp4 -i bottom.mp4 -filter_complex "[0:v][1:v]vstack=inputs=2[v]" -map "[v]" output.mp4

# 2x2 grid
ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -i input4.mp4 -filter_complex "[0:v][1:v]hstack=inputs=2[top];[2:v][3:v]hstack=inputs=2[bottom];[top][bottom]vstack=inputs=2[v]" -map "[v]" output.mp4

Subtitle Integration

Soft Subtitles (Embedded, Toggleable)

# Add SRT as soft subtitle
ffmpeg -i input.mp4 -i subtitles.srt -c copy -c:s mov_text output.mp4

# Multiple subtitle tracks with language metadata
ffmpeg -i input.mp4 -i english.srt -i spanish.srt -c copy -c:s mov_text -metadata:s:s:0 language=eng -metadata:s:s:1 language=spa output.mp4

Hard Subtitles (Burned In)

# Basic subtitle burning
ffmpeg -i input.mp4 -vf "subtitles=subtitles.srt" output.mp4

# Styled subtitles
ffmpeg -i input.mp4 -vf "subtitles=subtitles.srt:force_style='Fontsize=24,Fontname=Arial,PrimaryColour=&H00FFFFFF'" output.mp4

# From embedded subtitle track
ffmpeg -i input.mkv -vf "subtitles=input.mkv:si=0" output.mp4

Watermarks and Overlays

Image Watermarks

# Basic logo overlay (top-left)
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4

# Bottom-right positioning
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=main_w-overlay_w-10:main_h-overlay_h-10" output.mp4

# Center positioning
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" output.mp4

# Semi-transparent watermark
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1]format=rgba,colorchannelmixer=aa=0.5[logo];[0][logo]overlay=main_w-overlay_w-10:main_h-overlay_h-10" output.mp4

Text Watermarks

# Basic text watermark
ffmpeg -i input.mp4 -vf "drawtext=text='Copyright 2025':fontcolor=white:fontsize=24:x=10:y=10" output.mp4

# Text with background box
ffmpeg -i input.mp4 -vf "drawtext=text='My Company':fontcolor=white:fontsize=20:x=10:y=10:box=1:boxcolor=black@0.5" output.mp4

# Dynamic timestamp
ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime}':fontcolor=white:fontsize=18:x=w-tw-10:y=10" output.mp4

Advanced Video Effects

Denoising

# High-quality denoising (slow)
ffmpeg -i input.mp4 -vf "nlmeans=s=1.0:p=7:r=15" output.mp4

# Fast denoising
ffmpeg -i input.mp4 -vf "hqdn3d=2:1:2:1" output.mp4

Video Stabilization

# Two-pass stabilization (best quality)
# Pass 1: Analyze
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=8:accuracy=15:result=transforms.trf -f null -

# Pass 2: Apply stabilization
ffmpeg -i input.mp4 -vf vidstabtransform=input=transforms.trf:zoom=5:smoothing=15 output.mp4

Color Correction

# Basic color adjustment
ffmpeg -i input.mp4 -vf "eq=contrast=1.2:brightness=0.1:saturation=1.3:gamma=1.1" output.mp4

# Color balance
ffmpeg -i input.mp4 -vf "colorbalance=rs=0.1:gs=-0.1:bs=0.05" output.mp4

# Automatic color correction
ffmpeg -i input.mp4 -vf "normalize" output.mp4

Streaming and Live Broadcasting

RTMP Live Streaming

Basic RTMP Stream Setup

# Stream to YouTube/Twitch from webcam
ffmpeg -f v4l2 -i /dev/video0 -f alsa -i default -c:v libx264 -preset ultrafast -tune zerolatency -b:v 2500k -c:a aac -b:a 128k -f flv rtmp://a.rtmp.youtube.com/live2/YOUR_STREAM_KEY

# Stream existing file
ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac -preset ultrafast -tune zerolatency -f flv rtmp://127.0.0.1/live/stream_name

Hardware-Accelerated Streaming

# NVIDIA GPU encoding for streaming
ffmpeg -f v4l2 -i /dev/video0 -c:v h264_nvenc -preset llhq -tune ull -b:v 3000k -c:a aac -b:a 128k -f flv rtmp://ingest.server.com/live/stream_key

HLS (HTTP Live Streaming)

Basic HLS Generation

# Simple HLS conversion
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -hls_time 4 -hls_playlist_type vod -hls_segment_filename "segment%d.ts" playlist.m3u8

Multi-Quality HLS (Adaptive Bitrate)

# Create multiple quality levels
ffmpeg -i input.mp4 \
  -filter_complex "[0:v]split=3[v1][v2][v3]; [v1]copy[v1out]; [v2]scale=w=1280:h=720[v2out]; [v3]scale=w=640:h=360[v3out]" \
  -map "[v1out]" -c:v:0 libx264 -b:v:0 5000k -maxrate:v:0 5350k -bufsize:v:0 7500k \
  -map "[v2out]" -c:v:1 libx264 -b:v:1 2500k -maxrate:v:1 2675k -bufsize:v:1 3750k \
  -map "[v3out]" -c:v:2 libx264 -b:v:2 1000k -maxrate:v:2 1070k -bufsize:v:2 1500k \
  -map a:0 -c:a:0 aac -b:a:0 256k \
  -map a:0 -c:a:1 aac -b:a:1 128k \
  -map a:0 -c:a:2 aac -b:a:2 96k \
  -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" \
  -master_pl_name master.m3u8 \
  -f hls -hls_time 4 -hls_list_size 0 \
  -hls_segment_filename "v%v/segment%d.ts" \
  "v%v/playlist.m3u8"

DASH (Dynamic Adaptive Streaming)

# Basic DASH streaming
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -b:v 1000k -s 1280x720 -f dash -seg_duration 4 -use_template 1 -use_timeline 1 output.mpd

# Multi-bitrate DASH
ffmpeg -i input.mp4 \
  -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
  -b:v:0 2000k -s:v:0 1280x720 -profile:v:0 main \
  -b:v:1 500k -s:v:1 640x360 -profile:v:1 baseline \
  -b:a:0 128k -b:a:1 64k \
  -use_timeline 1 -use_template 1 -window_size 5 \
  -adaptation_sets "id=0,streams=v id=1,streams=a" \
  -f dash output.mpd

Low-Latency Streaming

Ultra-Low Latency HLS

ffmpeg -i input -c:v libx264 -tune zerolatency -preset ultrafast \
  -b:v 2500k -g 30 -keyint_min 30 -sc_threshold 0 \
  -c:a aac -b:a 128k \
  -f hls -hls_time 1 -hls_list_size 3 -hls_flags delete_segments \
  -hls_allow_cache 0 playlist.m3u8

Batch Processing and Automation

Cross-Platform Batch Scripts

Windows PowerShell Batch Processing

# Audio processing batch script
$inputPath = ".\input"
$outputPath = ".\output"

if (-not (Test-Path $outputPath)) {
    New-Item -ItemType Directory -Path $outputPath
}

Get-ChildItem $inputPath -Include *.mp3,*.wav,*.flac -Recurse | ForEach-Object {
    $inputFile = $_.FullName
    $outputFile = Join-Path $outputPath ($_.BaseName + "_processed.mp3")
    
    Write-Host "Processing: $($_.Name)"
    
    & ffmpeg -y -i $inputFile -af "loudnorm=I=-16:LRA=11:tp=-1.5" -c:a libmp3lame -b:a 192k $outputFile
    
    Write-Host "Completed: $($_.Name)"
}

macOS/Linux Bash Batch Processing

#!/bin/bash
# Advanced batch processing with parallel execution

input_dir="./input"
output_dir="./output"
max_jobs=4  # Number of parallel jobs

process_file() {
    local file="$1"
    local filename=$(basename "$file")
    local filename_no_ext="${filename%.*}"
    
    echo "Processing: $filename"
    
    # Complex processing chain
    ffmpeg -y -i "$file" \
        -af "afftdn=nr=12:nf=-25,loudnorm=I=-16:LRA=11:tp=-1.5,acompressor=threshold=0.05:ratio=3" \
        -c:a libmp3lame -b:a 320k "$output_dir/${filename_no_ext}_enhanced.mp3" \
        -loglevel error
        
    echo "Completed: $filename"
}

export -f process_file
export output_dir

mkdir -p "$output_dir"

# Use GNU parallel for efficient processing
find "$input_dir" -name "*.wav" -o -name "*.flac" -o -name "*.mp3" | \
    parallel -j "$max_jobs" process_file {}

Intelligent Auto-Processing

#!/bin/bash
# Quality-based intelligent processing

process_intelligent() {
    local input="$1"
    local output="$2"
    
    # Detect audio properties
    local bit_rate=$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "$input")
    
    echo "Input bitrate: ${bit_rate}bps"
    
    # Choose processing based on quality
    if [[ $bit_rate -gt 256000 ]]; then
        # High quality - preserve with lossless processing
        ffmpeg -i "$input" -af "loudnorm=I=-16:LRA=11:tp=-1.5" -c:a flac "$output"
    elif [[ $bit_rate -gt 128000 ]]; then
        # Medium quality - enhance and convert to high-quality MP3
        ffmpeg -i "$input" -af "dynaudnorm=p=0.9" -c:a libmp3lame -b:a 320k "$output"
    else
        # Low quality - apply aggressive enhancement
        ffmpeg -i "$input" -af "afftdn=nr=15,dynaudnorm=p=0.95,acompressor=threshold=0.1:ratio=4" -c:a libmp3lame -b:a 256k "$output"
    fi
}

Performance Optimization and Hardware Acceleration

Hardware Acceleration Setup

NVIDIA NVENC/NVDEC (2025 Best Practices)

# Basic NVENC encoding
ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:v h264_nvenc -b:v 5M output.mp4

# High-quality NVENC with lookahead
ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
  -c:v h264_nvenc -preset p6 -tune hq -b:v 5M -bufsize 5M -maxrate 10M \
  -qmin 0 -g 250 -bf 3 -temporal-aq 1 -rc-lookahead 20 output.mp4

# AV1 encoding (latest GPUs)
ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:v av1_nvenc -b:v 5M output.mp4

Intel Quick Sync Video (QSV)

# QSV encoding
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.mp4 -c:v h264_qsv -b:v 5M output.mp4

# With GPU scaling
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.mp4 -vf scale_qsv=1280:720 -c:v h264_qsv output.mp4

AMD Hardware Acceleration

# AMD AMF encoding
ffmpeg -i input.mp4 -c:v h264_amf -b:v 5M output.mp4

# With VAAPI support
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 -vf format=nv12,hwupload -c:v h264_vaapi output.mp4

CPU Optimization

Threading Configuration

# Auto-detect optimal threads (recommended)
ffmpeg -threads 0 -i input.mp4 output.mp4

# Manual thread control
ffmpeg -threads 8 -i input.mp4 -c:v libx264 -preset medium output.mp4

# Thread type control
ffmpeg -i input.mp4 -c:v libx264 -threads 8 -thread_type frame+slice output.mp4

Memory Optimization

# Minimize memory footprint
ffmpeg -i input.mp4 -c:v libx264 -bufsize 512k -maxrate 1M -threads 2 output.mp4

# Control buffer sizes
ffmpeg -thread_queue_size 512 -i input.mp4 -c copy output.mp4

Quality vs Speed Optimization

Preset Selection (H.264/H.265)

# Speed-optimized (fastest)
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast -crf 23 output.mp4

# Quality-optimized (slowest, best compression)
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 18 output.mp4

# Balanced approach
ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 21 output.mp4

Two-Pass Encoding (Maximum Quality)

# Two-pass H.264 for precise bitrate control
ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -an -f null /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 -c:a aac -b:a 128k output.mp4

# Two-pass H.265
ffmpeg -y -i input.mp4 -c:v libx265 -b:v 1.5M -x265-params pass=1 -an -f null /dev/null
ffmpeg -i input.mp4 -c:v libx265 -b:v 1.5M -x265-params pass=2 -c:a aac output.mp4

Troubleshooting Common Issues

Installation and Setup Issues

Windows: "ffmpeg is not recognized"

Solutions:

# Check PATH
where ffmpeg

# Manually add to current session
set PATH=%PATH%;C:\ffmpeg\bin

# Verify installation
ffmpeg -version

macOS: Permission denied

# Fix permissions
sudo chown -R $(whoami) $(brew --prefix)
brew doctor
brew reinstall ffmpeg

Linux: Codec not found

# Check available codecs
ffmpeg -codecs | grep h264

# Install additional codecs (Ubuntu)
sudo apt install ubuntu-restricted-extras
sudo apt install ffmpeg-full

# Compile with additional codecs
sudo apt install libx264-dev libx265-dev libvpx-dev

Performance Issues

Slow Encoding

Diagnostics:

# Monitor CPU usage
top -p $(pgrep ffmpeg)

# Check GPU utilization (NVIDIA)
nvidia-smi dmon -s u

# Enable detailed logging
ffmpeg -loglevel debug -i input.mp4 output.mp4

Solutions:

# Use hardware acceleration
ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4

# Optimize threading
ffmpeg -threads 0 -i input.mp4 -preset fast output.mp4

# Reduce quality temporarily
ffmpeg -i input.mp4 -crf 28 -preset ultrafast output.mp4

Memory Issues

# Reduce memory usage
ffmpeg -i large_file.mp4 -threads 2 -bufsize 1M -maxrate 5M output.mp4

# Process in chunks
ffmpeg -ss 0 -t 300 -i input.mp4 part1.mp4
ffmpeg -ss 300 -t 300 -i input.mp4 part2.mp4

Audio/Video Sync Issues

Fix Sync Problems

# Fix negative timestamps
ffmpeg -i input.mp4 -c:v copy -c:a copy -avoid_negative_ts make_zero output.mp4

# Manually adjust audio delay (3.5 seconds)
ffmpeg -i input.mp4 -itsoffset 3.5 -i input.mp4 -map 0:v -map 1:a -c copy output.mp4

# Re-sync with PTS adjustment
ffmpeg -i input.mp4 -c:v copy -c:a copy -fflags +genpts output.mp4

Codec and Container Issues

Unsupported Format

# Check file information
ffprobe -i problematic_file.mp4

# Convert to compatible format
ffmpeg -i input.mkv -c:v libx264 -profile:v main -level:v 4.0 -c:a aac output.mp4

# Force container change
ffmpeg -i input.mov -c copy -f mp4 output.mp4

Corrupted File Recovery

# Attempt to fix corrupted file
ffmpeg -err_detect ignore_err -i corrupted.mp4 -c copy fixed.mp4

# Re-encode problematic stream
ffmpeg -i corrupted.mp4 -c:v libx264 -c:a copy recovered.mp4

Network and Streaming Issues

Streaming Connection Problems

# Test RTMP connection
ffmpeg -f lavfi -i testsrc2=duration=10:size=640x480:rate=30 -f flv rtmp://test.server/live/test

# Increase timeout values
ffmpeg -rtmp_live_timeout 30000 -i rtmp://source -c copy output.mp4

# Add reconnection attempts
ffmpeg -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 2 -i rtmp://source output.mp4

Complete Command Reference

Essential Global Options

# File Operations
-y                      # Overwrite output files
-n                      # Never overwrite output files
-hide_banner           # Suppress printing banner
-v quiet|error|warning|info|verbose|debug  # Logging level

# Performance
-threads N             # Number of threads (0 = auto)
-thread_queue_size N   # Maximum packets in queue
-filter_threads N      # Number of threads for filtering

Input/Output Options

# Input
-i filename            # Input file
-ss time              # Start time offset
-t duration           # Duration limit
-to time             # Stop time
-itsoffset offset     # Input timestamp offset

# Output
-c codec             # Set codec (copy, libx264, etc.)
-c:v codec           # Video codec
-c:a codec           # Audio codec
-f format            # Force format

Video Options

# Quality and Encoding
-crf N                # Constant Rate Factor (0-51)
-b:v bitrate         # Video bitrate (1M, 500k)
-maxrate bitrate     # Maximum bitrate
-bufsize size        # Rate control buffer size
-preset preset       # Encoding speed preset
-profile:v profile   # Encoding profile

# Resolution and Frame Rate
-s WxH               # Frame size
-vf filter           # Video filter
-r fps               # Frame rate
-g GOP               # GOP size (keyframe interval)

# Advanced
-pix_fmt format      # Pixel format (yuv420p, etc.)
-aspect ratio        # Display aspect ratio
-vsync method        # Video sync method

Audio Options

# Quality and Encoding
-b:a bitrate         # Audio bitrate (128k, 320k)
-ar samplerate       # Sample rate (44100, 48000)
-ac channels         # Channel count (1=mono, 2=stereo)
-af filter           # Audio filter

# Advanced
-acodec codec        # Audio codec (deprecated, use -c:a)
-vol volume          # Volume (deprecated, use -af volume)

Stream Mapping

# Basic Mapping
-map input:stream    # Map specific stream
-map 0:v            # All video streams from input 0
-map 0:a:0          # First audio stream from input 0

# Advanced Mapping  
-map_metadata input  # Copy metadata
-map_chapters input  # Copy chapters
-disposition:s:0 default  # Set subtitle disposition

Filter Options

# Video Filters
-vf "filter1,filter2"              # Simple filter chain
-filter_complex "complex_filter"   # Complex filter graph

# Common Video Filters
scale=W:H                          # Scale video
crop=W:H:X:Y                       # Crop video
transpose=1                        # Rotate 90° clockwise
hflip                             # Horizontal flip
vflip                             # Vertical flip
fps=N                             # Change frame rate

Hardware Acceleration

# General
-hwaccel method      # auto, cuda, qsv, vaapi
-hwaccel_device N    # Hardware device index

# NVIDIA
-c:v h264_nvenc     # NVENC H.264 encoder
-c:v h264_cuvid     # CUVID H.264 decoder
-preset p1-p7       # NVENC preset (p1=fastest, p7=slowest)

# Intel QSV
-c:v h264_qsv       # QSV H.264 encoder
-look_ahead 1       # Enable lookahead

# AMD
-c:v h264_amf       # AMF H.264 encoder

Real-World Use Cases and Projects

Content Creation Workflows

Podcast Production Pipeline

#!/bin/bash
# Complete podcast processing workflow

# 1. Noise reduction and normalization
ffmpeg -i raw_podcast.wav \
    -af "highpass=f=80,lowpass=f=15000,afftdn=nr=10,loudnorm=I=-16:LRA=11:tp=-1.5" \
    clean_podcast.wav

# 2. Chapter marking (if chapters.txt exists)
if [[ -f chapters.txt ]]; then
    ffmpeg -i clean_podcast.wav -i chapters.txt -map_metadata 1 -c copy podcast_with_chapters.mp3
fi

# 3. Multiple format export
ffmpeg -i clean_podcast.wav \
    -c:a libmp3lame -b:a 128k podcast_web.mp3 \
    -c:a libopus -b:a 64k podcast_mobile.opus \
    -c:a aac -b:a 128k podcast_iTunes.m4a

YouTube Video Processing

#!/bin/bash
# YouTube-optimized video processing

input="$1"
title="$2"

# Main upload version (1080p, optimized)
ffmpeg -i "$input" \
    -c:v libx264 -profile:v high -level:v 4.2 -crf 21 -preset slower \
    -s 1920x1080 -r 30 -g 60 \
    -c:a aac -b:a 192k -ar 48000 \
    -movflags +faststart \
    -metadata title="$title" \
    youtube_main.mp4

# Thumbnail extraction (middle frame)
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$input")
middle_time=$(echo "$duration / 2" | bc -l)
ffmpeg -ss $middle_time -i "$input" -vframes 1 -q:v 2 -s 1280x720 thumbnail.jpg

# Preview clips for social media (15-second clips)
ffmpeg -i "$input" -ss 30 -t 15 -c:v libx264 -crf 23 -s 720x720 -c:a aac -b:a 128k instagram_preview.mp4

Live Streaming Production

Multi-Camera Live Stream Setup

#!/bin/bash
# Professional multi-camera streaming setup

# Camera inputs (adjust device paths as needed)
CAM1="/dev/video0"
CAM2="/dev/video2"
AUDIO_DEVICE="default"
STREAM_KEY="your_stream_key"
RTMP_URL="rtmp://a.rtmp.youtube.com/live2"

# Multi-camera with picture-in-picture
ffmpeg \
    -f v4l2 -i $CAM1 -f v4l2 -i $CAM2 -f alsa -i $AUDIO_DEVICE \
    -filter_complex "
        [0:v]scale=1920:1080[main];
        [1:v]scale=480:270[pip];
        [main][pip]overlay=1420:790[output]
    " \
    -map "[output]" -map 2:a \
    -c:v libx264 -preset fast -tune zerolatency \
    -b:v 4000k -maxrate 4000k -bufsize 8000k -g 60 \
    -c:a aac -b:a 128k -ar 48000 \
    -f flv $RTMP_URL/$STREAM_KEY

Automated Stream Monitoring

#!/bin/bash
# Stream health monitoring script

RTMP_URL="rtmp://your-server/live/stream"
LOG_FILE="/var/log/stream_monitor.log"

monitor_stream() {
    while true; do
        # Check stream health
        if ! ffprobe -v quiet -show_streams "$RTMP_URL" 2>/dev/null; then
            echo "$(date): Stream offline, attempting restart" >> $LOG_FILE
            
            # Restart stream from backup source
            ffmpeg -re -i /path/to/backup/playlist.m3u8 \
                -c copy -f flv "$RTMP_URL" &
            
            STREAM_PID=$!
            echo "$(date): Backup stream started (PID: $STREAM_PID)" >> $LOG_FILE
        fi
        
        sleep 30
    done
}

monitor_stream

Enterprise Media Processing

Automated Transcoding Service

#!/bin/bash
# Enterprise transcoding service with multiple outputs

input_dir="/media/input"
output_dir="/media/output"
archive_dir="/media/archive"

process_video() {
    local input="$1"
    local basename=$(basename "$input" | sed 's/\.[^.]*$//')
    local output_path="$output_dir/$basename"
    
    mkdir -p "$output_path"
    
    # Multiple quality encodes in parallel
    (
        # 4K version
        ffmpeg -i "$input" -c:v libx264 -crf 18 -preset slower -s 3840x2160 \
            -c:a aac -b:a 256k -movflags +faststart "$output_path/${basename}_4k.mp4"
    ) &
    
    (
        # 1080p version
        ffmpeg -i "$input" -c:v libx264 -crf 21 -preset medium -s 1920x1080 \
            -c:a aac -b:a 192k -movflags +faststart "$output_path/${basename}_1080p.mp4"
    ) &
    
    (
        # 720p version
        ffmpeg -i "$input" -c:v libx264 -crf 23 -preset fast -s 1280x720 \
            -c:a aac -b:a 128k -movflags +faststart "$output_path/${basename}_720p.mp4"
    ) &
    
    # Wait for all encodes to complete
    wait
    
    # Generate HLS playlist
    ffmpeg -i "$output_path/${basename}_1080p.mp4" \
        -c copy -f hls -hls_time 4 -hls_playlist_type vod \
        "$output_path/${basename}.m3u8"
    
    # Move original to archive
    mv "$input" "$archive_dir/"
    
    echo "Processing complete: $basename"
}

# Monitor input directory
inotifywait -m "$input_dir" -e create -e moved_to --format '%w%f' |
while read file; do
    if [[ "$file" == *.mp4 ]] || [[ "$file" == *.mov ]] || [[ "$file" == *.avi ]]; then
        echo "New file detected: $file"
        process_video "$file"
    fi
done

Quality Assurance and Analysis

Video Quality Analysis Suite

#!/bin/bash
# Comprehensive video quality analysis

analyze_video() {
    local input="$1"
    local output_report="${input%.*}_analysis.txt"
    
    echo "=== Video Analysis Report ===" > "$output_report"
    echo "File: $input" >> "$output_report"
    echo "Date: $(date)" >> "$output_report"
    echo "" >> "$output_report"
    
    # Basic file information
    echo "=== File Information ===" >> "$output_report"
    ffprobe -v quiet -print_format json -show_format -show_streams "$input" >> "$output_report"
    echo "" >> "$output_report"
    
    # Audio levels analysis
    echo "=== Audio Analysis ===" >> "$output_report"
    ffmpeg -i "$input" -af "volumedetect,astats" -f null - 2>&1 | \
        grep -E "(mean_volume|max_volume|RMS|Peak)" >> "$output_report"
    echo "" >> "$output_report"
    
    # Scene detection
    echo "=== Scene Changes ===" >> "$output_report"
    ffprobe -f lavfi -i "movie=$input,select=gt(scene\,0.3)" -show_entries frame=pkt_pts_time -v quiet -of csv=p=0 | \
        head -20 >> "$output_report"
    echo "" >> "$output_report"
    
    # Generate thumbnail grid
    local thumbnail_grid="${input%.*}_thumbnails.jpg"
    ffmpeg -i "$input" -vf "thumbnail,scale=320:240,tile=4x3" -frames:v 1 "$thumbnail_grid"
    
    echo "Analysis complete. Report: $output_report"
    echo "Thumbnail grid: $thumbnail_grid"
}

# Usage: ./analyze_video.sh video.mp4
analyze_video "$1"

This comprehensive FFmpeg tutorial and reference manual provides everything needed to master FFmpeg from basic installation through advanced professional workflows. Each section includes practical, cross-platform examples that work on Windows, macOS, and Linux, with current best practices for 2025 and beyond.

Read next