Оглавление
- Когда это нужно
- Подготовка
- Шаг 1. Диагностика файлов
- Шаг 2. Выбор способа склейки
- Шаг 3. Склейка
- Шаг 4. Проверка результата
- Готовые шаблоны команд
- Частые ошибки и что они значат
- Шпаргалка по параметрам
1. Когда это нужно
Типичные сценарии:
- Запись встречи/лекции разбита на несколько файлов (например, при превышении лимита размера или при перезапуске записи).
- Несколько коротких видео нужно собрать в одно.
- Нужно склеить фрагменты записи экрана.
FFmpeg умеет это двумя принципиально разными способами:
- Без перекодирования (
-c copy) — быстро (секунды), но требует идентичных параметров всех файлов. - С перекодированием (фильтр
concat) — медленнее, но работает всегда и даёт предсказуемый результат.
2. Подготовка
Проверить, что FFmpeg установлен
ffmpeg -version
Если команда не найдена:
- Ubuntu/Debian:
sudo apt install ffmpeg - Fedora:
sudo dnf install ffmpeg - macOS (Homebrew):
brew install ffmpeg - Windows: скачать с ffmpeg.org или
winget install ffmpeg
Перейти в папку с файлами
cd ~/Загрузки # Linux/macOS
cd %USERPROFILE%\Downloads # Windows cmd
cd $env:USERPROFILE\Downloads # Windows PowerShell
Полезно: включить автодополнение имён файлов
Если в именах пробелы и кириллица (как в вашем случае) — набирать вручную неудобно. Используйте Tab для автодополнения или пишите имена в кавычках.
3. Шаг 1. Диагностика файлов
Это самый важный шаг. От него зависит, можно ли склеить быстро или нужно перекодировать.
3.1. Посмотреть ключевые параметры
ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,sample_rate,channels -of default=noprint_wrappers=1 "файл1.webm"
Повторите для каждого файла. Сравните значения:
| Параметр | Что означает | Важно для -c copy |
|---|---|---|
codec_name (видео) | Кодек видео | Должен совпадать |
codec_name (аудио) | Кодек аудио | Должен совпадать |
width / height | Разрешение | Должно совпадать |
r_frame_rate | Номинальный fps | Желательно совпадение |
avg_frame_rate | Средний fps | Если 0/0 — VFR, значит -c copy рискован |
sample_rate | Частота дискретизации аудио | Должна совпадать |
channels | Кол-во каналов | Должно совпадать |
3.2. Как интерпретировать
- Все параметры совпадают и
avg_frame_rateне0/0→ можно пробовать-c copy. - Параметры совпадают, но
avg_frame_rate=0/0(VFR) →-c copyможет дать рассинхрон и битый звук. Лучше сразу перекодировать. - Параметры различаются → только перекодирование.
3.3. Быстрая проверка длительности
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1 "файл1.webm"
Пригодится потом для проверки суммы.
4. Шаг 2. Выбор способа склейки
Способ A — быстрое копирование (-c copy)
Плюсы: секунды, без потери качества.
Минусы: работает только при идентичных параметрах. При VFR часто ломается.
Способ B — перекодирование через фильтр concat
Плюсы: работает всегда, даёт стабильный результат.
Минусы: занимает время (зависит от кодека и CPU).
Правило: если сомневаетесь — берите способ B. Время дороже битого файла.
5. Шаг 3. Склейка
Способ A — без перекодирования
Создайте файл со списком (порядок строк = порядок в итоговом видео):
printf "file 'файл1.webm'\nfile 'файл2.webm'\nfile 'файл3.webm'\n" > list.txt
Затем:
ffmpeg -f concat -safe 0 -i list.txt -c copy "результат.webm"
-f concat— использовать concat-демультиплексор.-safe 0— разрешить абсолютные/нестандартные пути.-c copy— не перекодировать, копировать потоки как есть.
Способ B — с перекодированием (универсальный)
B.1. В WebM (VP9 + Opus)
Медленно, но сохраняет формат WebM:
ffmpeg -i "файл1.webm" -i "файл2.webm" \
-filter_complex "\
[0:v]fps=30,setpts=PTS-STARTPTS[v0];\
[1:v]fps=30,setpts=PTS-STARTPTS[v1];\
[0:a]aresample=48000,asetpts=PTS-STARTPTS[a0];\
[1:a]aresample=48000,asetpts=PTS-STARTPTS[a1];\
[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libvpx-vp9 -b:v 2M -cpu-used 5 -row-mt 1 -threads 0 \
-c:a libopus -b:a 128k \
"результат.webm"
B.2. В MP4 (H.264 + AAC) — рекомендуется для встреч/скринкастов
Быстро, совместимо со всем:
ffmpeg -i "файл1.webm" -i "файл2.webm" \
-filter_complex "[0:v]fps=30,setpts=PTS-STARTPTS[v0];[1:v]fps=30,setpts=PTS-STARTPTS[v1];[0:a]asetpts=PTS-STARTPTS[a0];[1:a]asetpts=PTS-STARTPTS[a1];[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libx264 -preset veryfast -crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
"результат.mp4"
B.3. Для трёх и более файлов
Добавьте входы и блоки в filter_complex:
ffmpeg -i "файл1.webm" -i "файл2.webm" -i "файл3.webm" \
-filter_complex "\
[0:v]fps=30,setpts=PTS-STARTPTS[v0];[0:a]asetpts=PTS-STARTPTS[a0];\
[1:v]fps=30,setpts=PTS-STARTPTS[v1];[1:a]asetpts=PTS-STARTPTS[a1];\
[2:v]fps=30,setpts=PTS-STARTPTS[v2];[2:a]asetpts=PTS-STARTPTS[a2];\
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libx264 -preset veryfast -crf 23 \
-c:a aac -b:a 128k -movflags +faststart \
"результат.mp4"
Обратите внимание: concat=n=3 — число файлов, и количество пар [vN][aN] должно совпадать с числом входов.
6. Шаг 4. Проверка результата
4.1. Длительность
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1 "результат.mp4"
Должна быть ≈ сумме длительностей исходников (допустимая погрешность — доли секунды).
4.2. Параметры потоков
ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate,sample_rate,channels -of default=noprint_wrappers=1 "результат.mp4"
4.3. Визуальная проверка стыка (обязательно)
Откройте результат в плеере и проматайте на момент стыка — примерно на длительность первого файла от начала. Проверьте:
- звук не «убегает» от видео;
- картинка не замирает;
- нет резких скачков яркости/размера (если исходники писались в разное время).
4.4. Проверка в конце
Проматайте ближе к концу файла — убедитесь, что синхрон сохраняется на всём протяжении. Если к концу накапливается рассинхрон — значит, в одном из исходников были проблемы, и поможет только покадровая обработка (уже не «просто склейка»).
7. Готовые шаблоны команд
Универсальный шаблон (MP4, H.264)
ffmpeg -i "ЧАСТЬ1" -i "ЧАСТЬ2" \
-filter_complex "[0:v]fps=30,setpts=PTS-STARTPTS[v0];[1:v]fps=30,setpts=PTS-STARTPTS[v1];[0:a]asetpts=PTS-STARTPTS[a0];[1:a]asetpts=PTS-STARTPTS[a1];[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libx264 -preset veryfast -crf 23 \
-c:a aac -b:a 128k -movflags +faststart \
"РЕЗУЛЬТАТ.mp4"
Универсальный шаблон (WebM, VP9)
ffmpeg -i "ЧАСТЬ1" -i "ЧАСТЬ2" \
-filter_complex "[0:v]fps=30,setpts=PTS-STARTPTS[v0];[1:v]fps=30,setpts=PTS-STARTPTS[v1];[0:a]aresample=48000,asetpts=PTS-STARTPTS[a0];[1:a]aresample=48000,asetpts=PTS-STARTPTS[a1];[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libvpx-vp9 -b:v 2M -cpu-used 5 -row-mt 1 -threads 0 \
-c:a libopus -b:a 128k \
"РЕЗУЛЬТАТ.webm"
Быстрый шаблон (только для одинаковых файлов)
printf "file 'ЧАСТЬ1'\nfile 'ЧАСТЬ2'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy "РЕЗУЛЬТАТ"
8. Частые ошибки и что они значат
Non-monotonic DTS; previous: X, current: Y
Таймстемпы второго файла конфликтуют с первым. Причина — разный fps или VFR. Решение: перекодирование с fps=30 и setpts=PTS-STARTPTS.
Error parsing Opus packet header
Повреждён аудиопоток на стыке — следствие той же проблемы. Решение: то же — перекодирование.
Unknown encoder 'libvpx-vp9'
Ваш FFmpeg собран без VP9. Решение: используйте libx264 (MP4) или переустановите FFmpeg с полным набором кодеков.
Unknown encoder 'libx264'
Аналогично — нет H.264. Решение: sudo apt install ffmpeg из официальных репозиториев обычно содержит libx264.
Invalid file index 2 in filtergraph description
В filter_complex указан вход, которого нет (например, [2:v], но задано только 2 файла с индексами 0 и 1). Решение: пересчитайте входы и concat=n=N.
Input link in1:v0 parameters (size X, SAR Y) do not match the corresponding output link
Разные разрешения или пропорции. Решение: добавьте scale в фильтр для каждого входа:
[0:v]fps=30,scale=1920:1080,setsar=1,setpts=PTS-STARTPTS[v0];
moov atom not found при воспроизведении результата
Файл записан некорректно (обычно из-за прерывания FFmpeg). Решение: запустите склейку заново, дождитесь завершения.
9. Шпаргалка по параметрам
Видео
| Параметр | Значение | Комментарий |
|---|---|---|
-c:v libx264 | H.264 (MP4) | Быстро, совместимо |
-c:v libvpx-vp9 | VP9 (WebM) | Медленно, но формат WebM |
-preset veryfast | Скорость x264 | ultrafast…veryslow |
-crf 23 | Качество x264 | Меньше = лучше (18–28) |
-b:v 2M | Битрейт VP9 | 2 Мбит/с для 1080p встреч |
-cpu-used 5 | Скорость VP9 | 0 (медл.)…8 (быстро) |
fps=30 | Частота кадров | Для скринкастов 30, для динамики 60 |
-movflags +faststart | MP4 | Метаданные в начало файла |
Аудио
| Параметр | Значение | Комментарий |
|---|---|---|
-c:a aac | AAC (MP4) | Универсально |
-c:a libopus | Opus (WebM) | Для WebM |
-b:a 128k | Битрейт | 128k достаточно для голоса |
aresample=48000 | Частота | 48000 — стандарт для Opus |
Фильтры
| Фильтр | Зачем |
|---|---|
fps=30 | Приводит видео к постоянной частоте кадров |
setpts=PTS-STARTPTS | Обнуляет таймстемпы видео |
asetpts=PTS-STARTPTS | Обнуляет таймстемпы аудио |
aresample=48000 | Приводит аудио к единой частоте |
scale=1920:1080 | Приводит к единому разрешению |
setsar=1 | Убирает разницу в aspect ratio |
concat=n=N:v=1:a=1 | Собственно склейка N файлов |
Памятка на будущее (короткая версия)
- Сравнить параметры файлов через
ffprobe. - Одинаковые и без VFR →
-c copy(секунды). - Разные или VFR → фильтр
concatсfps=30иsetpts=PTS-STARTPTS. - Формат не важен → MP4/H.264 (
veryfast,crf 23) — быстрее всего. - Обязателен WebM → VP9 + Opus, но долго.
- Всегда проверять стык на готовом файле.
- При ошибках
Non-monotonic DTS/Opus packet header— сразу переходить к перекодированию.
Сохраните этот файл — в следующий раз сэкономите время на диагностику.
