- PVSM.RU - https://www.pvsm.ru -
FFmpeg — мощное ПО со большим набором возможностей. В статье я постараюсь рассказать о немного необычном применении фильтров ffmpeg и о том что можно сделать используя исключительно их. Видео ниже сделано с помощью 1 команды ffmpeg (ни один графический редактор не пострадал).
Я буду использовать последнюю версию ffmpeg, собранную из git [1]. Так что, если вы хотите чтобы мои примеры работали, рекомендую собрать из ветки master. Сборка и установка тривиальна и описана на сайте ffmpeg.org, при ./configure не забудьте указать "--enable-libfreetype".
Для начала нам нужно создать фон для нашего видео и мы будем использовать средства ffmpeg. Дело в том что ffmpeg позволяет использовать в качестве входного источника не только реальные устройства (например, видео-камеры или sdi-карты) и файлы, но и может использовать собственное виртуальное устройство, которое называется lavfi.
FFmpeg содержит в себе несколько готовых фильтров, которые генерируют видеоизображение. Среди них:
Полный список фильтров можно посмотреть командой
ffmpeg -filters
Вот как они выглядят:

Поскольку я указал что буду использовать исключительно ffmpeg, то и это изображение я сгенерировал с помощью 1 команды ffmpeg. Вот она:
ffmpeg
-f lavfi -i "testsrc=s=320x240" #Указываем все входные lavfi источники и ставим им размер в 320x240
-f lavfi -i "cellauto=s=320x240"
-f lavfi -i "life=s=320x240"
-f lavfi -i "mandelbrot=s=320x240"
-f lavfi -i "rgbtestsrc=s=320x240"
-f lavfi -i "smptebars=s=320x240"
-filter_complex
"[0:0]pad=iw*6:ih[a]; #Делаем падинг изображений с помощью фильтра pad
[1:0]pad=iw:ih[b];
[2:0]pad=iw*2:ih[c];
[3:0]pad=iw*3:ih[d];
[4:0]pad=iw*4:ih[e];
[5:0]pad=iw*5:ih[f];
[a][b]overlay=w[x]; # Склеиваем изображения с помощью фильтра overlay
[x][c]overlay=w[y];
[y][d]overlay=w[z];
[z][e]overlay=w[v];
[v][f]overlay=w" -vframes 1 all_filters.jpg
Хотя я сделал картинку, с помощью этой команды можно также объединить 6 видео в ряд или сделать «мозайку», нужно лишь подставить в качестве входных источников видео-файлы и изменить параметры для фильтров pad и overlay. Пробежимся по опциям:
И так, создадим фон для нашего видео:
ffmpeg2 -f lavfi -i "color=lightblue" -t 30 -y blue.ts
Тут все тоже самое что и в примере с картинками, за исключением того, что здесь мы создаем видео и вместо фильтров-генераторов, используем простой фильтр цвета. Помимо количества кадров, вы можете задать продолжительность видео через ключ "-t". По умолчанию ffmpeg задаст fps выходного потока равным 25. Поскольку я указал расширение выходному файлу .ts, то ffmpeg будет использовать контейнер MPEG2TS, а кодек mpeg2video.
Теперь добавим снежинку. Для этого будем использовать фильтр drawtext. Да, да, мы нарисуем снежинку текстом, вернее специальным юникод символом "❄" (U+2744).

Команда, которая это делает:
ffmpeg -f lavfi -i "color=lightblue"
-vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=50:text='❄':fontcolor=white:x=sin(n/10)*30+w/2:y=n"
-t 5 -y snow.gif
Опции фильтра drawtext:
Как можно заметить, вся соль в координатах. Дело в том, что ffmpeg позволяет менять параметры некоторых своих фильтров «на лету», например, в зависимости от номера кадра или таймстемпа. В данном примере, помимо уже знакомых w и h, я использовал очередной внутренний алиас ffmpegа «n» — номер текущего кадра и функцию синуса чтобы придать снежинке движение из стороны в сторону. В фильтрах ffmpeg вы можете использовать тригонометрические и арифметические функции, такие как trunc и random. Полный список функций можно посмотреть вот здесь [3].
Теперь осталось только добавить еще фильтров (нужно больше фильтров!) для создания других снежинок и изменить их размер и движения.
ffmpeg -f lavfi -i "color=lightblue"
-vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=10:text='❄':fontcolor=white:x=sin(n/10)*30:y=3*n,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=16:text='❄':fontcolor=white:x=cos(n/9)*3+w/3:y=n/2-h/16,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=19:text='❄':fontcolor=white:x=sin(n/7)*10+w/9:y=n/3-h/20,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=15:text='❄':fontcolor=white:x=cos(n/25)*20+w/2:y=n-h/9,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=20:text='❄':fontcolor=white:x=sin(n/19)*4+w-w/3:y=n-h/20,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=17:text='❄':fontcolor=white:x=cos(n/10)*9+w/7:y=n/2-h/18,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=16:text='❄':fontcolor=white:x=sin(n/20)*23+w-w/7:y=2*n-h/15,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=19:text='❄':fontcolor=white:x=cos(n/15)*15+w/5:y=n-h/6,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=20:text='❄':fontcolor=white:x=sin(n/15)*50+w-w/9:y=n-h/10,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=12:text='❄':fontcolor=white:x=cos(n/30)+w/2:y=n*2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=16:text='❄':fontcolor=white:x=cos(n/9)*3+w/3:y=n/2-h/6,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=19:text='❄':fontcolor=white:x=sin(n/7)*10+w/9:y=n/4-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=15:text='❄':fontcolor=white:x=cos(n/25)*20+w/2:y=n/5-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=20:text='❄':fontcolor=white:x=sin(n/19)*4+w-w/3:y=n-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=17:text='❄':fontcolor=white:x=cos(n/10)*9+w/7:y=n/2-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=16:text='❄':fontcolor=white:x=sin(n/20)*23+w-w/7:y=2*n-h/3,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=19:text='❄':fontcolor=white:x=cos(n/15)*15+w/5:y=n/6-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=20:text='❄':fontcolor=white:x=sin(n/15)*50+w-w/9:y=2*n-h/2,
drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf:fontsize=12:text='❄':fontcolor=white:x=cos(n/22)+w/2:y=2+h"
-qscale 1 -s 720x560 -t 12 -y snow.mp4
На видео выше результат выполнения этой команды. К сожалению, мне не удалось заставить параметр fontsize принимать в качестве значения результат функции random, скорее всего это пока не поддерживается. Напоследок укажу еще один нюанс с которым я с столкнулся — параметр text тоже не принимает значения вида text=n. Для того чтобы отображать номер кадра используйте конструкцию «text=%{expr\:n}». На этом у меня все, надеюсь вы узнали для себя что нибудь новое.
Автор: ptQa
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ffmpeg/49057
Ссылки в тексте:
[1] git: http://www.ffmpeg.org/download.html
[2] граф фильтров: http://ffmpeg.org/ffmpeg-filters.html#Filtergraph-description
[3] здесь: http://www.ffmpeg.org/ffmpeg-utils.html#Expression-Evaluation
[4] Источник: http://habrahabr.ru/post/203314/
Нажмите здесь для печати.