FFmpeg без магии: ментальная модель, которой не хватает
Хватит слепо копировать команды FFmpeg. Разберитесь в контейнерах, кодеках, потоках и фильтрах и освойте рецепты, которые реально пригодятся.

Все мы через это проходили. Нужно конвертировать видео, вы гуглите и находите ответ на Stack Overflow с командой, которая выглядит так, будто кто-то со всей силы ударил по клавиатуре: ffmpeg -i input.mov -c:v libx264 -preset slow -crf 22 -c:a aac -b:a 128k -movflags +faststart output.mp4. Запускаете. Работает. Понятия не имеете почему, и в следующий раз, когда понадобится что-то чуть-чуть другое, вы снова на Stack Overflow. Я так делал годами, пока наконец не сел и не разобрался, чего же FFmpeg от меня хочет.
Если честно, FFmpeg не так уж сложен. У него есть последовательная ментальная модель, и как только вы её поймёте, почти любая команда становится понятной. Проблема в том, что модель никто не объясняет, все просто подсовывают команды. Так что давайте это исправим.
Контейнеры и кодеки: что нужно понять в первую очередь
Самый большой источник путаницы с видеофайлами — разница между контейнерами и кодеками. Контейнер — это формат файла: .mp4, .mkv, .webm, .mov. Это коробка, которая что-то хранит. Кодек — это способ сжатия самих видео- и аудиоданных внутри этой коробки: H.264, H.265, VP9, AV1, AAC, Opus.
В файле MP4 может лежать видео H.264 с аудио AAC, либо видео H.265 с аудио Opus, либо десятки других комбинаций. Файл MKV может содержать практически что угодно. Когда кто-то говорит «конвертировать в MP4», обычно имеется в виду «упаковать видео H.264 и аудио AAC в контейнер MP4», но это три отдельных решения.
# See what's actually inside a file
$ ffprobe -hide_banner video.mkv
Input #0, matroska:
Stream #0:0: Video: hevc (Main), 1920x1080, 23.98 fps
Stream #0:1: Audio: opus, 48000 Hz, stereo
Stream #0:2: Subtitle: subrip
# This file is:
# Container: MKV (Matroska)
# Video codec: HEVC (H.265)
# Audio codec: Opus
# Plus a subtitle stream
Прежде чем что-либо делать, используйте ffprobe. Он покажет, с чем именно вы работаете. Примерно в половине случаев нужная вам «конвертация» — это просто ремуксинг, то есть перенос тех же потоков в другой контейнер без перекодирования. Это занимает считаные секунды.
Структура команды FFmpeg
Каждая команда FFmpeg следует одному и тому же шаблону, и как только вы его увидите, уже не сможете не замечать:
ffmpeg [global options] [input options] -i input [output options] output
# The KEY insight: options apply to the NEXT file.
# Options before -i apply to the input.
# Options after -i (before the output filename) apply to the output.
# This matters! These two commands are different:
ffmpeg -ss 00:01:00 -i video.mp4 output.mp4 # Seeks BEFORE decoding (fast)
ffmpeg -i video.mp4 -ss 00:01:00 output.mp4 # Seeks AFTER decoding (slow, precise)
Порядок имеет значение. Именно на этом спотыкаются все. Значение опции может меняться в зависимости от того, стоит она до или после -i. Пример с -ss выше — самый распространённый случай: если поставить её перед -i, FFmpeg перейдёт к нужному месту во входном файле напрямую (быстро, но возможна неточность), а если после — FFmpeg декодирует всё до этой точки и только потом начнёт вывод (медленно, зато точно по кадрам).
Выбор потоков: как сообщить FFmpeg, что вам нужно
Видеофайлы часто содержат несколько потоков: видео, аудио, субтитры, иногда несколько аудиодорожек на разных языках. Чтобы выбрать конкретные потоки, FFmpeg использует синтаксис спецификаторов потоков:
-c:v— кодек для видеопотоков (v = video)-c:a— кодек для аудиопотоков (a = audio)-c:s— кодек для потоков субтитров (s = subtitle)-c copy— копировать ВСЕ потоки без перекодирования-c:v copy -c:a aac— копировать видео как есть, перекодировать аудио в AAC-map 0:a:1— выбрать второй аудиопоток из первого входного файла
Флаг -c copy — самый важный из всех. Он говорит FFmpeg копировать данные потока напрямую, без перекодирования. Это практически мгновенно и без потерь: вы просто переносите данные из одного контейнера в другой. Если не нужно менять кодек, всегда используйте -c copy.
# Remux MKV to MP4 without re-encoding (instant)
ffmpeg -i input.mkv -c copy output.mp4
# Copy video but re-encode audio (fast — only audio is processed)
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k output.mp4
# Extract just the audio stream
ffmpeg -i video.mp4 -vn -c:a copy audio.aac
# -vn means "no video" — drop the video stream entirely
Практические рецепты, которые вы реально будете использовать
Вот команды, которыми я пользуюсь постоянно. Каждая из них объяснена, чтобы вы могли адаптировать её под свои задачи.
Сжатие видео для веба
ffmpeg -i raw_video.mov \
-c:v libx264 \
-preset slow \
-crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
web_video.mp4
# -c:v libx264 → encode video with H.264
# -preset slow → slower encoding = smaller file (options: ultrafast to veryslow)
# -crf 23 → quality level (18=near lossless, 23=default, 28=low quality)
# -c:a aac → encode audio as AAC
# -b:a 128k → audio bitrate 128 kbps
# -movflags +faststart → move metadata to start of file for streaming
Значение CRF (Constant Rate Factor) — самый важный регулятор качества. Чем меньше число, тем выше качество и больше файл. Для большинства веб-видео оптимальный диапазон — CRF 20–25. Я обычно ставлю 22 для всего, что должно хорошо выглядеть, и 26 для фонового или вспомогательного видео, где качество важно меньше.
Обрезка видео без перекодирования
# Extract from 1:30 to 3:45 — no re-encoding, nearly instant
ffmpeg -ss 00:01:30 -to 00:03:45 -i input.mp4 -c copy trimmed.mp4
# If you need frame-accurate cuts (slower):
ffmpeg -i input.mp4 -ss 00:01:30 -to 00:03:45 \
-c:v libx264 -crf 18 -c:a copy trimmed.mp4
Генерация миниатюр
# Single thumbnail at the 10-second mark
ffmpeg -ss 00:00:10 -i video.mp4 -frames:v 1 thumb.jpg
# One thumbnail every 30 seconds
ffmpeg -i video.mp4 -vf "fps=1/30" thumbs/thumb_%04d.jpg
# Resize to 320px wide, maintain aspect ratio
ffmpeg -ss 00:00:10 -i video.mp4 -frames:v 1 \
-vf "scale=320:-1" thumb_small.jpg
Создание GIF из видеоклипа
# Good quality GIF with palette generation (two-pass)
ffmpeg -ss 00:00:05 -t 3 -i video.mp4 \
-vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1]; \
[s0]palettegen[p];[s1][p]paletteuse" \
output.gif
# -t 3 → duration: 3 seconds
# fps=15 → 15 frames per second (keep GIFs small)
# scale=480:-1 → resize to 480px wide
# palettegen/use → generate optimal color palette (much better quality)
Фильтры: главная сила FFmpeg
Именно фильтры превращают FFmpeg из «полезного инструмента» в «невероятно мощный». Флаг -vf (видеофильтр) и флаг -af (аудиофильтр) позволяют объединять цепочки операций обработки. Фильтры разделяются запятыми для последовательной обработки или точками с запятой для сложных графов фильтров.
# Chain multiple filters: resize, then add padding for exact dimensions
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,\
pad=1280:720:(ow-iw)/2:(oh-ih)/2:black" output.mp4
# Normalize audio volume
ffmpeg -i input.mp4 -af "loudnorm" -c:v copy output.mp4
# Speed up a video 2x (with audio pitch correction)
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" fast.mp4
# Add text overlay
ffmpeg -i input.mp4 \
-vf "drawtext=text='DRAFT':fontsize=72:fontcolor=red:x=10:y=10" \
watermarked.mp4
Система фильтров достаточно глубока, чтобы заполнить отдельную статью, но ключевая мысль такая: фильтры работают с декодированными кадрами. Значит, -c copy с фильтрами не использовать: видео нужно декодировать, отфильтровать и перекодировать заново. Если в команде есть -vf, заложите время на полное перекодирование.
Аппаратное ускорение: используйте GPU
Если вы регулярно кодируете видео, аппаратное ускорение может ускорить процесс в 5–10 раз. Современные GPU содержат выделенные блоки кодирования, которые FFmpeg умеет использовать.
# NVIDIA GPU (NVENC)
ffmpeg -i input.mp4 -c:v h264_nvenc -preset p4 -crf 23 output.mp4
# Apple Silicon (VideoToolbox)
ffmpeg -i input.mp4 -c:v h264_videotoolbox -b:v 5M output.mp4
# Intel Quick Sync (QSV)
ffmpeg -i input.mp4 -c:v h264_qsv -preset medium output.mp4
# Check what's available on your system:
ffmpeg -encoders 2>/dev/null | grep -E '(nvenc|videotoolbox|qsv|vaapi)'
Небольшое предостережение: аппаратные кодировщики быстрее, но при той же визуальной картинке обычно дают немного большие файлы, чем программное кодирование (libx264). Для разовых перекодирований, где важно качество, программное кодирование по-прежнему лучше. Для пакетной обработки или стриминга в реальном времени аппаратное ускорение явно выигрывает. Я использую libx264 для финальных продакшн-кодирований, а NVENC — для всего остального.
Частые ошибки и как их избежать
- Перекодирование без необходимости. Если вы просто обрезаете, извлекаете аудио или меняете контейнер, используйте
-c copy. Нет смысла тратить 20 минут на перекодирование видео, от которого вы отрезаете 30 секунд. - Слишком низкое значение CRF. CRF 18 даёт огромные файлы с улучшением качества, которое большинство людей не заметит. Начните с 23 и опускайтесь ниже, только если видите артефакты. Для большинства веб-контента 23–25 более чем достаточно.
- Забытый
-movflags +faststart. Без этого метаданные MP4 лежат в конце файла, и браузер не может начать воспроизведение, пока не загрузится весь файл. Всегда добавляйте этот флаг для веб-видео. - Непроверенный входной файл. Запустите
ffprobeперед написанием команды. Знание входных кодеков, разрешения и структуры потоков делает всё проще. - Ожидание в никуда. Если FFmpeg кажется зависшим, возможно, он ждёт ответа на вопрос (например, перезаписывать ли существующий файл). Добавьте
-y, чтобы перезаписывать автоматически, или-n, чтобы никогда не перезаписывать.
Шпаргалка
Вот что я храню в текстовом файле на рабочем столе. Этого хватает примерно на 90% моих ежедневных задач:
# Probe a file
ffprobe -hide_banner input.mp4
# Remux (change container, no re-encode)
ffmpeg -i input.mkv -c copy output.mp4
# Compress for web
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k -movflags +faststart output.mp4
# Extract audio only
ffmpeg -i video.mp4 -vn -c:a copy audio.m4a
# Trim without re-encoding
ffmpeg -ss 00:01:00 -to 00:02:30 -i input.mp4 -c copy clip.mp4
# Resize to 720p
ffmpeg -i input.mp4 -vf "scale=-1:720" -c:a copy output.mp4
# Convert to GIF
ffmpeg -ss 5 -t 3 -i input.mp4 \
-vf "fps=12,scale=400:-1" output.gif
# Concatenate files (same codec)
echo "file 'part1.mp4'" > list.txt
echo "file 'part2.mp4'" >> list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy combined.mp4
FFmpeg — не инструмент, который осваивается за день. Но как только вы поймёте ментальную модель — контейнеры содержат потоки, у потоков есть кодеки, опции применяются к следующему файлу, фильтры требуют перекодирования — документация начинает складываться в понятную картину. Вы перестаёте слепо копировать команды и начинаете составлять их осознанно. И, честно говоря, переход от «это магия» к «ага, вот что он делает» — один из самых приятных моментов, которые могут случиться с разработчиком.


