Вопрос или проблема
Возможно ли использовать ffmpeg
для создания видео из набора последовательностей, где номер не начинается с нуля?
Например, у меня есть несколько изображений [test_100.jpg
, test_101.jpg
, test_102.jpg
, …, test_200.jpg
], и я хочу преобразовать их в видео. Я попробовал следующую команду, но она не сработала (похоже, номер должен начинаться с нуля):
ffmpeg -i test_%d.jpg -vcodec mpeg4 test.avi
Есть ли какие-нибудь советы?
Нет необходимости переименовывать файлы, если использовать параметр -start_number
таким образом:
ffmpeg -start_number n -i test_%d.jpg -vcodec mpeg4 test.avi
где n
— это начало последовательности изображений.
Обратите внимание, что это будет работать, пока последовательность не прерывается. Если есть пробелы, и вы хотите включить все изображения, то может потребоваться переименование, чтобы заполнить пробелы.
Есть и некоторые другие параметры, которые могут быть полезны.
Я использую следующий однострочный скрипт, чтобы получить более низкую частоту кадров и сжать изображения, чтобы получить более компактное видео:
ffmpeg.exe -f image2 -framerate 25 -pattern_type sequence -start_number 1234 -r 3 -i Imgp%04d.jpg -s 720x480 test.avi
Опция -r 3
устанавливает частоту кадров полученного видео в 3 кадра в секунду, так что я могу видеть каждое изображение короткое время. Опция -s
изменяет масштаб изображений до желаемого разрешения, чтобы управлять размером полученного видео.
(В командной строке Windows замените -i Imgp%04d.jpg
на -i "Imgp%%04d.jpg"
. За это спасибо Майку Фицпатрику https://superuser.com/a/344178/153054)
Вы можете использовать следующий код:
cat *.jpg | ffmpeg -f image2pipe -r 1 -vcodec mjpeg -i - -vcodec libx264 out.mp4
Использование шаблона glob
ffmpeg также поддерживает глобальные шаблоны в стиле bash (* представляет любое количество любых символов).
Это полезно, если ваши изображения являются последовательными, но не обязательно в числовом порядке, как в предыдущих примерах.
ffmpeg -r 1 -pattern_type glob -i 'test_*.jpg' -c:v libx264 out.mp4
Таким образом, пока ваши файлы отсортированы, использование параметра -pattern_type glob
должно сработать.
Обратите внимание, что кавычки вокруг шаблона важны в случае использования glob.
Вы можете найти пример скрипта в документации ffmpeg:
3.2 Как я могу кодировать одиночные фотографии в фильмы?
Если у вас много изображений для переименования, вы можете использовать следующую команду, чтобы облегчить задачу. Команда, используя синтаксис bourne shell, символически связывает все файлы в текущем каталоге, которые соответствуют *jpg, с каталогом
/tmp
в последовательностиimg001.jpg
,img002.jpg
и так далее.
x=1; for i in *jpg; do counter=$(printf %03d $x); ln "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done
Затем выполните:
ffmpeg -f image2 -i /tmp/img%03d.jpg /tmp/a.mpg
-pattern_type glob
конкретные примеры с аудио
Эта опция была упомянута на: https://superuser.com/a/782520/128124, но здесь приведены несколько конкретных примеров её использования, включая добавление аудио в выходное видео.
Слайд-шоу видео с одним изображением в секунду
ffmpeg -framerate 1 -pattern_type glob -i '*.png' \
-c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
Добавьте к этому музыку, обрезая её, когда, предположительно, более длинный аудиотрек заканчивается:
ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
-c:a copy -shortest -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
Вот два демо на YouTube:
Будьте как хиппи и используйте формат видео Theora без патентов в контейнере OGG:
ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
-c:a copy -shortest -c:v libtheora -r 30 -pix_fmt yuv420p out.ogv
Ваши изображения должны, конечно, быть отсортированы в алфавитном порядке, обычно как:
0001-first-thing.jpg
0002-second-thing.jpg
0003-and-third.jpg
и так далее.
Я бы также сначала убедился, что все изображения, которые будут использованы, имеют одинаковое соотношение сторон, возможно, предварительно обрезав их с помощью imagemagick
или nomacs, так чтобы ffmpeg не пришлось принимать трудные решения. В частности, ширина должна быть четной, иначе преобразование завершится с ошибкой: “ширина не делится на 2”.
Полное реальное исследование случая слайд-шоу шаг за шагом
Создание слайд-шоу требует больше усилий, чем просто выполнение одной команды ffmpeg, поэтому вот более интересный подробный пример, вдохновленный этой хронологией.
Получите входные медиа:
mkdir -p orig
cd orig
wget -O 1.png https://upload.wikimedia.org/wikipedia/commons/2/22/Australopithecus_afarensis.png
wget -O 2.jpg https://upload.wikimedia.org/wikipedia/commons/6/61/Homo_habilis-2.JPG
wget -O 3.jpg https://upload.wikimedia.org/wikipedia/commons/c/cb/Homo_erectus_new.JPG
wget -O 4.png https://upload.wikimedia.org/wikipedia/commons/1/1f/Homo_heidelbergensis_-_forensic_facial_reconstruction-crop.png
wget -O 5.jpg https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Sabaa_Nissan_Militiaman.jpg/450px-Sabaa_Nissan_Militiaman.jpg
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/7/74/Alnitaque_%26_Moon_Shot_-_EURO_%28Extended_Mix%29.ogg
cd ..
# Преобразовать все в PNG для согласованности.
# https://unix.stackexchange.com/questions/29869/converting-multiple-image-files-from-jpeg-to-pdf-format
# Жесткая ссылка на те, которые уже являются PNG.
mkdir -p png
mogrify -format png -path png orig/*.jpg
ln -P orig/*.png png
Теперь мы быстро посмотрим на все размеры изображений, чтобы решить, какое соотношение сторон будет финальным:
identify png/*
что выводит:
png/1.png PNG 557x495 557x495+0+0 8-bit sRGB 653KB 0.000u 0:00.000
png/2.png PNG 664x800 664x800+0+0 8-bit sRGB 853KB 0.000u 0:00.000
png/3.png PNG 544x680 544x680+0+0 8-bit sRGB 442KB 0.000u 0:00.000
png/4.png PNG 207x238 207x238+0+0 8-bit sRGB 76.8KB 0.000u 0:00.000
png/5.png PNG 450x600 450x600+0+0 8-bit sRGB 627KB 0.000u 0:00.000
поэтому классическое соотношение 480p (640×480 == 4/3) кажется подходящим.
Выполните одно преобразование с минимальным изменением размера, чтобы сделать ширину равной (TODO автоматизировать для любой ширины, здесь я просто вручную посмотрел на вывод identify
и уменьшил ширину и высоту на один):
mkdir -p raw
convert png/1.png -resize 556x494 raw/1.png
ln -P png/2.png png/3.png png/4.png png/5.png raw
ffmpeg -framerate 1 -pattern_type glob -i 'raw/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p raw.mp4
Это дает ужасный результат, потому что как видно из:
ffprobe raw.mp4
ffmpeg просто берет размер первого изображения, 556×494, а затем преобразует все остальные в этот точный размер, нарушая их соотношение сторон.
Теперь давайте автоматически преобразуем изображения в целевое соотношение сторон 480p, обрезая, как это указано в https://stackoverflow.com/questions/21262466/imagemagick-how-to-minimally-crop-an-image-to-a-certain-aspect-ratio
mkdir -p auto
mogrify -path auto -geometry 640x480^ -gravity center -crop 640x480+0+0 png/*.png
ffmpeg -framerate 1 -pattern_type glob -i 'auto/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p auto.mp4
Теперь соотношение сторон хорошее, но неизбежно произошло некоторое обрезание, что, конечно, разрушило интересные части изображений.
Другой вариант — это обложка черным фоном, чтобы иметь то же самое соотношение сторон, как показано на: https://stackoverflow.com/questions/18514083/resize-to-fit-in-a-box-and-set-background-to-black-on-empty-part/18514327
mkdir -p black
mogrify -path black -thumbnail 640x480 -background black -gravity center -extent 640x480 png/*.png
ffmpeg -framerate 1 -pattern_type glob -i 'black/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p black.mp4
Говоря в общем, вы, как правило, будете в идеале выбирать изображения с одинаковым или похожим соотношением сторон, чтобы избежать этих проблем с самого начала.
О параметрах командной строки
Обратите внимание, однако, что несмотря на название, -glob
это не так уж и универсально, как шаблоны оболочки. Например: -i '*'
не срабатывает: https://trac.ffmpeg.org/ticket/3620 (похоже, потому что тип файла определяется по расширению).
-r 30
устанавливает видео с -framerate 1
на 30 FPS, чтобы преодолеть ошибки в плеерах, таких как VLC, для низкой частоты кадров: https://stackoverflow.com/questions/19267443/playback-issues-in-vlc-with-low-fps-video-from-images-using-ffmpeg/41797724#41797724. Таким образом, он повторяет каждый кадр 30 раз, чтобы сохранить желаемый эффект одной картинки в секунду.
Следующие шаги
Вам также потребуется:
-
вырезать часть аудиодорожки, которую вы хотите, перед объединением: https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg
ffmpeg -i in.mp3 -ss 03:10 -to 03:30 -c copy out.mp3
В качестве альтернативы, вы также можете обрезать это прямо в команде преобразования, добавив
-ss
сразу перед аудио-i
:ffmpeg -framerate 1 -pattern_type glob -i 'raw/*.png' -ss 0:36 -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p raw.mp4
TODO: научиться обрезать и конкатенировать несколько аудиофайлов в видео без промежуточных файлов, я почти уверен, что это возможно:
- https://stackoverflow.com/questions/42250223/ffmpeg-cut-and-concat-single-command-line
- https://video.stackexchange.com/questions/21315/concatenating-split-media-files-using-concat-protocol
- Конкатенировать несколько WAV файлов, используя одну команду, без дополнительных файлов
Видео нормальной скорости с одним изображением на кадр при 30 FPS
ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
-c:v libx264 -pix_fmt yuv420p out.mp4
Вот как это выглядит:
GIF, сгенерированный с помощью: https://askubuntu.com/questions/648603/how-to-create-an-animated-gif-from-mp4-video-via-command-line/837574
Добавьте к этому аудио:
ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
-i audio.ogg -c:a copy -shortest -c:v libx264 -pix_fmt yuv420p out.mp4
Результат: https://www.youtube.com/watch?v=HG7c7lldhM4
Преобразовать один аудиофайл в видео с фиксированным изображением для загрузки на YouTube
Ответ на: Как преобразовать MP3 в видеоформат, разрешенный YouTube?
Получить некоторые синтетические тестовые входные изображения
Это тестовые изображения, которые я использовал в этом ответе:
wget -O opengl-rotating-triangle.zip https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.zip?raw=true
unzip opengl-rotating-triangle.zip
cd opengl-rotating-triangle
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/7/74/Alnitaque_%26_Moon_Shot_-_EURO_%28Extended_Mix%29.ogg
Изображения созданы с помощью: https://stackoverflow.com/questions/3191978/how-to-use-glut-opengl-to-render-to-a-file/14324292#14324292
Интересно наблюдать, насколько хорошо видео сжимает последовательность изображений гораздо лучше, чем ZIP, так как оно способно сжимать между кадрами с помощью специализированных алгоритмов:
opengl-rotating-triangle.mp4
: 340Kopengl-rotating-triangle.zip
: 7.3M
О параметрах командной строки
Обратите внимание, однако, что несмотря на название, -glob
, это не так уж общий, как шаблоны оболочки. Например: -i '*'
не срабатывает: https://trac.ffmpeg.org/ticket/3620 (похоже, потому что тип файла определяется по расширению).
-r 30
устанавливает видео с -framerate 1
на 30 FPS, чтобы преодолеть ошибки в проигрывателях, таких как VLC, для низких частот кадров: https://stackoverflow.com/questions/19267443/playback-issues-in-vlc-with-low-fps-video-from-images-using-ffmpeg/41797724#41797724. Таким образом, он повторяет каждый кадр 30 раз, чтобы сохранить желаемый эффект одной картинки в секунду.
Следующие шаги
Вам также потребуется:
-
вырезать часть аудиотрека, чтобы он соответствовал длине видео: https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg
ffmpeg -i in.mp3 -ss 03:10 -to 03:30 -c copy out.mp3
-
добавить обрезанный аудиотрек: Как объединить аудио и видеофайл в ffmpeg
ffmpeg -i video.mp4 -i audio.mp3 -c copy output.mkv
TODO: научиться обрезать и конкатенировать несколько аудиофайлов в видео через командную строку:
- https://stackoverflow.com/questions/42250223/ffmpeg-cut-and-concat-single-command-line
- https://video.stackexchange.com/questions/21315/concatenating-split-media-files-using-concat-protocol
- Конкатенировать несколько WAV файлов, используя одну команду, без дополнительного файла
Проверено на
ffmpeg 3.4.4, vlc 3.0.3, Ubuntu 18.04.
Библиография
- http://trac.ffmpeg.org/wiki/Slideshow официальная вики
Насколько мне известно, вы не можете начать последовательность с произвольных чисел (не помню, нужно ли начинать с 0 или 1), кроме того, она не может иметь пробелов, если есть пробелы, ffmpeg предположит, что последовательность завершена, и прекратит добавление изображений.
Также, как указано в комментариях к моему ответу, помните, что вам нужно указать ширину вашего индекса. Например:
image%03d.jpg
И если вы используете тип индекса %03d, вам нужно дополнить имена файлов нулями, например :
image001.jpg
image002.jpg
image003.jpg
и так далее.
Я согласен с Франциско, но в качестве обходного пути вы могли бы просто написать быстрый скрипт, чтобы переместить или создать символические ссылки на файлы с последовательными номерами, которые нужны ffmpeg. Затем скрипт мог бы вызвать ffmpeg и затем удалить ссылки или вернуть файлы на свои места.
Я знаю, что это старый вопрос, но я наткнулся на него в Google, когда искал тот же ответ. Ни один из ответов здесь не удовлетворил меня полностью, поэтому я сделал дополнительные поиски и чтение, и это команда, которую я разработал для своей проблемы.
cat {0032..1501}*.png | ffmpeg -f image2pipe -framerate 5 -i - -s 720x480 test2.avi
Причина, по которой я использовал подобную команду, заключается в том, что…
- Cat и -f image2pipe дают вам более тонкий контроль над тем, какие изображения вы используете. Например, это позволяет использовать функции bash, такие как расширение скобок, и другие команды, такие как grep, для тонкой настройки ваших результатов, если вы решите.
- Меньше параметров для запоминания.
- Я рекомендую не использовать -r, а просто использовать -framerate. По моему опыту, -r чаще приводит к потере кадров.
- Меньше сложностей, никаких ненужных параметров, и он будет работать как есть. Вы можете добавить больше сложности (например, указав кодировщик) и настроить его под свои нужды.
посмотрите
x=1; for i in *jpg; do counter=$(printf %03d $x); ln "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done
Я использовал кодировщик flv, так как моё видео шло в flash-плеер (Jwplayer)
ffmpeg -i %d.jpg -vcodec flv test.flv
Согласно документации, вы можете просто использовать *
Для создания видео из имен файлов, соответствующих шаблону glob foo-*.jpeg:
ffmpeg -f image2 -pattern_type glob -framerate 12 -i 'foo-*.jpeg' -s WxH foo.avi
Как заметка, для повышения качества может быть важна частота кадров (например, сначала укажем очень низкую/высокую частоту кадров, а затем перейдем во второй фильтр, который сделает замедленное видео нормальным?)
В моем случае это было немного сложнее из-за номеров в файлах. Вот как выглядят мои изображения:
$ ls | head -5
2014_aq_unprocessed 001.jpg
2014_aq_unprocessed 002.jpg
2014_aq_unprocessed 003.jpg
2014_aq_unprocessed 004.jpg
2014_aq_unprocessed 005.jpg
а вот команда, которую я использовал:
ffmpeg -i 2014_aq_unprocessed\ %3d.jpg -vcodec mpeg4 test.avi
Вы можете сделать это с помощью convert -morph
:
convert *.jpg -delay 10 -morph 10 %05d.jpg
Если вы хотите использовать ffmpeg
, я использовал
ffmpeg -pattern_type glob -i '*.jpg' -vf "setpts=10*PTS" movie.mp4
где 10*PTS
указывает ffmpeg замедлить его в 10 раз. Вы также можете использовать дробные значения для ускорения.
Ответ или решение
Создание видео из изображений с помощью FFmpeg является достаточно просто. В данной инструкции мы обсудим несколько различных подходов, которые можно использовать, чтобы успешно скомпилировать набор изображений в видеоролик, даже если индексы изображений не начинаются с нуля.
Основные варианты
-
Использование параметра -start_number
Если ваши изображения имеют последовательно увеличивающиеся индексы, но не начинаются с нуля, вы можете использовать параметр
-start_number
, чтобы указать, с какого числа начинаются ваши изображения. Например, если ваши изображения называютсяtest_100.jpg
,test_101.jpg
и т.д., вы можете выполнить следующее:ffmpeg -start_number 100 -i test_%d.jpg -vcodec mpeg4 test.avi
Этот способ работает, если последовательность изображений непрерывна.
-
Использование шаблонов glob
Если ваши изображения могут не следовать строгой нумерации или состоят в произвольном порядке, FFmpeg поддерживает использование шаблонов glob. Например, если ваши файлы называются
test_100.jpg
,test_101.jpg
и т.д., можно использовать:ffmpeg -r 1 -pattern_type glob -i 'test_*.jpg' -c:v libx264 -pix_fmt yuv420p out.mp4
Здесь
-r
задает частоту кадров, а-pix_fmt
определяет используемый пиксельный формат. -
Использование
image2pipe
для тонкой настройкиЕще один способ создать видео — это использовать
image2pipe
. Это позволяет вам более точно контролировать, какие изображения вы будете использовать. Например:cat *.jpg | ffmpeg -f image2pipe -r 1 -vcodec mjpeg -i - -vcodec libx264 out.mp4
Это даёт вам возможность использовать функционал Shell для фильтрации изображений перед обработкой.
Дополнительные параметры
-
Частота кадров: Используйте
-framerate
для указания частоты кадров, как показано выше. -
Изменение размера: При необходимости, используйте
-s
для задания размера выходного видео, например:ffmpeg -framerate 1 -pattern_type glob -i 'test_*.jpg' -s 1280x720 -c:v libx264 out.mp4
-
Добавление аудио: Вы также можете добавить аудиотрек в ваше видео:
ffmpeg -framerate 1 -pattern_type glob -i 'test_*.jpg' -i audio.mp3 -c:v libx264 -c:a aac -shortest out.mp4
Обработка изображений перед созданием видео
Убедитесь, что все изображения имеют одинаковое разрешение и соотношение сторон, чтобы избежать искажений при создании видеоролика. Вы можете использовать такие инструменты, как ImageMagick, чтобы предварительно обработать изображения:
mogrify -resize 1280x720 *.jpg
Примечание
- Убедитесь, что у вас установлена последняя версия FFmpeg для доступа ко всем функциям.
- При использовании шаблонов glob важно оборачивать ваш шаблон в одинарные кавычки, чтобы избежать интерпретации оболочкой.
Эти рекомендации помогут вам создать видео из набора изображений с использованием FFmpeg, даже если числа в названиях файлов не начинаются с нуля. Если у вас возникнут дополнительные вопросы, не стесняйтесь обращаться за помощью.