About us Guides Projects Contacts
Админка
please wait

FFmpeg is the Swiss Army knife of media processing, capable of transcoding, streaming, filtering, and manipulating virtually any audio/video format. This guide covers practical FFmpeg usage patterns from a senior developer's perspective.

Why FFmpeg

FFmpeg powers most video platforms:

  1. Universal Format Support: Handles virtually every codec and container
  2. Powerful Filters: Resize, crop, overlay, color-correct, and more
  3. Streaming Capable: RTMP, HLS, DASH output
  4. Subtitle Support: Embed, extract, and render subtitles
  5. Batch Processing: Script any media workflow

Installation

# Ubuntu/Debian
sudo apt install ffmpeg
# CentOS/RHEL
sudo dnf install ffmpeg
# macOS
brew install ffmpeg
# Verify installation
ffmpeg -version

Basic Concepts

FFmpeg Command Structure

ffmpeg [global_options] [input_options] -i input [output_options] output

Container vs Codec

  • Container: File format (MP4, MKV, AVI)
  • Video Codec: Video compression (H.264, H.265, VP9)
  • Audio Codec: Audio compression (AAC, MP3, Opus)

Check file information:

ffprobe -v error -show_format -show_streams input.mp4

Common Transcoding Tasks

Convert Between Formats

# MKV to MP4 (re-encode)
ffmpeg -i input.mkv -c:v libx264 -c:a aac output.mp4
# MKV to MP4 (copy streams, no re-encoding)
ffmpeg -i input.mkv -c copy output.mp4
# AVI to WebM
ffmpeg -i input.avi -c:v libvpx-vp9 -c:a libopus output.webm

Change Video Quality

# Constant Rate Factor (CRF): Lower = better quality
# H.264: 18-28 is a good range; 23 is the default
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
# H.265 (HEVC): Better compression
ffmpeg -i input.mp4 -c:v libx265 -crf 28 output.mp4
# Target bitrate
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M output.mp4
# Two-pass encoding (best quality for target size)
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -f null /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 output.mp4

Resize Video

# Scale to a specific resolution
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4
# Scale while maintaining aspect ratio
ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4 # Height auto
ffmpeg -i input.mp4 -vf "scale=-1:720" output.mp4 # Width auto
# Scale to fit within dimensions (padding if needed)
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Working with Subtitles

Convert YouTube Subtitles to SRT

Convert YouTube's VTT format to SRT:

ffmpeg -i subtitles.vtt subtitles.srt

Embed Subtitles (Soft Subs)

Subtitles as a separate stream (can be toggled):

# Add SRT as a subtitle stream
ffmpeg -i video.mp4 -i subtitles.srt -c copy -c:s mov_text output.mp4
# Add VTT subtitles
ffmpeg -i video.mp4 -i subtitles.vtt -c copy -c:s webvtt output.mkv
# Multiple subtitle tracks
ffmpeg -i video.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

Burn Subtitles into Video (Hard Subs)

Subtitles rendered onto video (permanent):

# Burn SRT subtitles
ffmpeg -i video.mp4 -vf "subtitles=subtitles.srt" output.mp4
# Customize subtitle style
ffmpeg -i video.mp4 -vf "subtitles=subtitles.srt:force_style='FontSize=24,PrimaryColour=&H00FFFF&'" output.mp4
# Burn ASS/SSA subtitles (preserves styling)
ffmpeg -i video.mp4 -vf "ass=subtitles.ass" output.mp4

Extract Subtitles

# Extract the first subtitle stream
ffmpeg -i video.mkv -map 0:s:0 subtitles.srt
# Extract all subtitle streams
ffmpeg -i video.mkv -map 0:s subtitles_%d.srt

Audio Processing

Extract Audio

# Extract as MP3
ffmpeg -i video.mp4 -vn -c:a libmp3lame -q:a 2 audio.mp3
# Extract in the original format
ffmpeg -i video.mp4 -vn -c:a copy audio.aac

Change Audio

# Change audio codec
ffmpeg -i input.mp4 -c:v copy -c:a aac output.mp4
# Adjust volume
ffmpeg -i input.mp4 -filter:a "volume=1.5" output.mp4
# Normalize audio
ffmpeg -i input.mp4 -filter:a loudnorm output.mp4
# Remove audio
ffmpeg -i input.mp4 -an output.mp4

Replace Audio Track

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

Cutting and Joining

Cut Video Segments

# Cut from 00:01:00 for 30 seconds
ffmpeg -i input.mp4 -ss 00:01:00 -t 30 -c copy output.mp4
# Cut from 00:01:00 to 00:02:30
ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:30 -c copy output.mp4
# Fast seek (put -ss before -i for large files)
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c copy output.mp4

Concatenate Videos

Create file list videos.txt:

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

Join files:

# Same codec (no re-encoding)
ffmpeg -f concat -safe 0 -i videos.txt -c copy output.mp4
# Different codecs (re-encode)
ffmpeg -f concat -safe 0 -i videos.txt -c:v libx264 -c:a aac output.mp4

Video Filters

Common Filter Examples

# Crop video (width:height:x:y)
ffmpeg -i input.mp4 -vf "crop=640:480:100:50" output.mp4
# Rotate video
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4 # 90° clockwise
ffmpeg -i input.mp4 -vf "transpose=2" output.mp4 # 90° counterclockwise
ffmpeg -i input.mp4 -vf "hflip" output.mp4 # Horizontal flip
ffmpeg -i input.mp4 -vf "vflip" output.mp4 # Vertical flip
# Speed up/slow down
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" output.mp4 # 2x speed
ffmpeg -i input.mp4 -vf "setpts=2.0*PTS" -af "atempo=0.5" output.mp4 # 0.5x speed
# Add fade-in/out
ffmpeg -i input.mp4 -vf "fade=t=in:st=0:d=2,fade=t=out:st=58:d=2" output.mp4

Add Watermark/Overlay

# Image watermark in corner
ffmpeg -i video.mp4 -i watermark.png \
-filter_complex "overlay=W-w-10:H-h-10" \
output.mp4
# Text overlay
ffmpeg -i video.mp4 \
-vf "drawtext=text='Copyright 2024':fontsize=24:fontcolor=white:x=10:y=H-th-10" \
output.mp4
# Timestamp
ffmpeg -i video.mp4 \
-vf "drawtext=text='%{pts\:hms}':fontsize=24:fontcolor=white:x=10:y=10" \
output.mp4

Creating Thumbnails and GIFs

Extract Thumbnails

# Single frame at a specific time
ffmpeg -i video.mp4 -ss 00:00:10 -vframes 1 thumbnail.jpg
# Multiple thumbnails (every 10 seconds)
ffmpeg -i video.mp4 -vf "fps=1/10" thumbnail_%04d.jpg
# Thumbnail grid/sprite
ffmpeg -i video.mp4 -vf "fps=1/5,scale=160:-1,tile=5x5" sprite.jpg

Create GIF

# Basic GIF (large file)
ffmpeg -i video.mp4 -t 5 output.gif
# Optimized GIF with palette
ffmpeg -i video.mp4 -t 5 -vf "fps=15,scale=480:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i video.mp4 -i palette.png -t 5 -filter_complex "fps=15,scale=480:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif

Streaming

Generate HLS for Adaptive Streaming

ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-hls_time 10 \
-hls_list_size 0 \
-hls_segment_filename "segment_%03d.ts" \
playlist.m3u8

Multiple Quality HLS

ffmpeg -i input.mp4 \
-filter_complex "[0:v]split=3[v1][v2][v3]; \
[v1]scale=1920:1080[v1out]; \
[v2]scale=1280:720[v2out]; \
[v3]scale=854:480[v3out]" \
-map "[v1out]" -map 0:a -c:v:0 libx264 -b:v:0 5M -c:a aac -b:a:0 192k \
-hls_time 10 -hls_playlist_type vod 1080p.m3u8 \
-map "[v2out]" -map 0:a -c:v:1 libx264 -b:v:1 2.5M -c:a aac -b:a:1 128k \
-hls_time 10 -hls_playlist_type vod 720p.m3u8 \
-map "[v3out]" -map 0:a -c:v:2 libx264 -b:v:2 1M -c:a aac -b:a:2 96k \
-hls_time 10 -hls_playlist_type vod 480p.m3u8

Batch Processing with Scripts

Bash Script Example

##!/bin/bash
INPUT_DIR="./raw"
OUTPUT_DIR="./processed"
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file" .mp4)
echo "Processing: $filename"
ffmpeg -i "$file" \
-c:v libx264 -crf 23 \
-c:a aac -b:a 128k \
-vf "scale=1280:-1" \
"$OUTPUT_DIR/${filename}_720p.mp4"
done
echo "Done!"

Node.js Integration

const { spawn } = require('child_process');
function transcodeVideo(input, output, options = {}) {
return new Promise((resolve, reject) => {
const args = [
'-i', input,
'-c:v', 'libx264',
'-crf', options.crf || '23',
'-c:a', 'aac',
'-y', // Overwrite output
output
];
const ffmpeg = spawn('ffmpeg', args);
ffmpeg.stderr.on('data', (data) => {
console.log(`FFmpeg: ${data}`);
});
ffmpeg.on('close', (code) => {
if (code === 0) {
resolve(output);
} else {
reject(new Error(`FFmpeg exited with code ${code}`));
}
});
});
}
// Usage
transcodeVideo('input.mp4', 'output.mp4', { crf: '28' })
.then(output => console.log('Created:', output))
.catch(err => console.error('Error:', err));

Key Takeaways

  1. Use -c copy when possible: Avoid re-encoding for speed
  2. CRF for quality control: Lower values = higher quality
  3. Two-pass for target size: Best quality at a specific bitrate
  4. Palette for GIFs: Essential for good quality
  5. -ss before -i: Faster seeking in large files
  6. Test on short clips: Prototype filters before full renders

FFmpeg's depth is vast—these patterns cover most common needs, but the documentation reveals countless more capabilities for specialized workflows.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
ZK Interactive