FFmpeg | Объединение файлов, слайдшоу (concat)

от
FFmpeg    concat, объединение, склеить видео, склеить аудио, слайдшоу

Часто приходится объединить несколько видео в одно или склеить множество изображений в одной видео.

Содержание:
  - Объединение из списка файлов
  - Создание списка файлов из командной строки
  - Объединение фильтром concat
  - Слайдшоу

Объединение из списка файловДопустим, есть 5 видео файлов: 1.mp4, 2.mp4, 3.mp4, 4.mp4 и 5.mp4
Если все они имеют одинаковые кодеки, частоту кадров и разрешение, то их можно будет объединить очень быстро с поддержкой копирования потоков.
Для этого необходимо создать текстовый файл, в котором перечислить все видео в нужном порядке:
list.txt
  1. file '1.mp4'
  2. file '2.mp4'
  3. file '3.mp4'
  4. file '4.mp4'
  5. file '5.mp4'
После чего выполнить объединение:
  1. ffmpeg -f concat -safe 0 -i list.txt -c copy result.mp4

Этот способ очень быстр, но, к сожалению, зависим от параметров видео. Если какие-то видео отличаются в частоте кадров или прочих параметрах, то объединённое видео может неправильно воспроизводиться. Поэтому, при таком способе обязательно проверяйте результат.

Если возникли проблемы с быстрым объединением, тогда можно убрать копирование потоков:
  1. ffmpeg -f concat -safe 0 -i list.txt result.mp4
В таком случае объединение будет происходить дольше из-за перекодирования, но зато результат будет правильно воспроизводиться.

⚠️ Некоторые форматы видео поддерживают файловое копирование. Например, в случае ts (mpegts) новое видео можно просто дописывать в конец другого без перекодирования (и даже без участия ffmpeg).
Windows:
  1. copy /b video1.ts + video2.ts result.ts
Linux:
  1. cat video1.ts video2.ts > result.ts

Этот способ работает не только с видео, но и с аудио:
  1. file '1.mp3'
  2. file '2.mp3'
  3. file '3.mp3'
  1. ffmpeg -f concat -safe 0 -i list.txt result.mp3

И даже с изображениями.

⚠️ Файлы можно указывать несколько раз. Например, если есть заставка, которая должна быть в начале и в конце видео, можно создать такой файл:
  1. file 'splash.mp4'
  2. file 'video1.mp4'
  3. file 'video2.mp4'
  4. file 'splash.mp4'


Создание списка файлов из командной строки
Чтобы вручную не вписывать названия файлов, особенно, если их много, на Windows можно выполнить команду:
  1. (for %i in (*.mp4) do @echo file '%i') > list.txt
Либо для вложенных папок:
  1. (for /r %i in (*.mp4) do @echo file '%i') > list.txt

Для Linux:
  1. (for f in *.mp4; do echo "file '$f'"; done) > list.txt
Или для вложенных папок:
  1. find . -type f -iname "*.mp4" -printf "file '%p'\n" > list.txt


Объединение фильтром concatЕсли нужно объединить несколько видео с разным форматом или отличающимися кодеками, можно воспользоваться фильтром concat
Параметры:
  n — количество частей (по умолчанию 2)
  v — количество выходных видеопотоков (и видеопотоков в каждой части). По умолчанию, 1.
  a — количество выходных аудиопотоков (и аудиопотоков в каждой части). По умолчанию, 0.

Объединить три видео в один файл (в каждом 1 видеопоток и 1 аудиопоток):
  1. ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 ^
  2.   -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" ^
  3.   -map "[outv]" -map "[outa]" result.mp4
Вначале перечисляем пары (видеопоток + аудиопоток) для каждого входного файла, после чего указываем, что объединять будем 3 части (n=3), а на выходе ожидаем один видеопоток (v=1) и один аудиопоток (a=1).

Перед началом обработки, FFmpeg выведет информацию о потоках, можно проверить, что всё нормально:
  1. Stream mapping:
  2.   Stream #0:0 (h264) -> concat:in0:v0
  3.  Stream #0:1 (aac) -> concat:in0:a0
  4.  Stream #1:0 (h264) -> concat:in1:v0
  5.  Stream #1:1 (aac) -> concat:in1:a0
  6.  Stream #2:0 (h264) -> concat:in2:v0
  7.  Stream #2:1 (aac) -> concat:in2:a0
  8.  concat:out:v0 -> Stream #0:0 (libx264)
  9.  concat:out:a0 -> Stream #0:1 (aac)

Объединить аудиопотоки у трёх видеофайлов и сохранить в result.mp3:
  1. ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 ^
  2.   -filter_complex "[0:a][1:a][2:a]concat=n=3:v=0:a=1[outa]" ^
  3.   -map "[outa]" result.mp3


СлайдшоуПри объединении изображений из списка файлов, можно указывать длительность показа изображения в секундах:
  1. file 'cat.jpg'
  2. duration 2
  3. file 'dog.jpg'
  4. duration 4
  5. file 'cat and dog.jpg'
  6. duration 2
  7. file 'cat and dog 2.jpg'
  8. duration 2
  1. ffmpeg -f concat -safe 0 -i list.txt slideshow.mp4

Если же изображений очень много и их нужно объединить с определённой частотой кадров, можно указать шаблон.
Допустим, есть 500 картинок с именами frame_001.jpg, frame_002.jpg, ..., frame_500.jpg. Чтобы объединить их в видео с частотой 60 кадров в секунду:
  1. ffmpeg -framerate 60 -i frame_%03d.jpg -pix_fmt yuv420p output.mp4
%03d — специальный формат шаблона, означающий, что под порядковый номер отводится 3 цифры и есть лидирующий ноль.

Если объединять файлы "img (1).jpg", "img (2).jpg", .., "img (2000).jpg", то шаблон будет таким:
  1. ffmpeg -framerate 30 -i "img (%4d).jpg" -pix_fmt yuv420p output.mp4

Смотрите также ответы к Собрать видео из множества фотографии, там инструкция и скрипт объединения картинок.

  • +4
  • views 9859