Собственно говоря данный пример в основном относится к -filter_complex (он же -lavfi) но я также рассмотрю более общие вопросы использования ffmpeg. Собственно, все необходимо я разместил на GitHub.
Итак, что понадобится:
ПО. Сам ffmpeg, imagemagick (делать прозрачный фон и не только), git (если нет), Linux. Для Debian (Ubuntu)
$ sudo apt install -y ffmpeg imagemagick git
Собственно mp3 файл, лучше с метаданными, скрипт может вытаскивать текст и добавлять его в видео.
Картинка, в принципе для данного примера любое изображение диска.
Поставить mktrans. В README.md инструкция для создания прозрачного фона. Изменить размер картинки можно с помощью convert из imagemagick или самого ffmpeg.
Поставить пример git clone https://github.com/zirf0/music_visual.git.
Теперь заглянем внутрь
flr_show-freq-vol - текст фильтра
music_vision.sh - основной скрипт
valk500tr.png - картинка с диском (у меня 500x500 с прозрачным фоном)
wagner.gif - гифка к этой статье. Тоже создана ffmpeg.
wagner_valkyries.mp3 - "Полет Валькирий" Вагнера
Начинаем разбирать фильтр
" [0:a]showfreqs=s=600x240:mode=line:colors=red|blue,pad=1920:1080:0:x=1000:y=350[vf];
[0:a]showvolume=p=1,scale=1280:40[vv]; [1:v]scale=500:500,rotate=a=0.4*t/2:ow=iw/1:oh=ow[disk];
[vf][disk]overlay=(W-w)-1300:(H-h)/2,scale=1920:1080[l1];
[l1][vv]overlay=x=700:y=800,scale=1920:1080[l2]; [l2]drawtext=fontfile=NimbusRoman-BoldItalic.otf:textfile=metadata.txt: fontcolor=white:fontsize=50:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)-500:y=(h-text_h)-800, format=yuv420p[fin] "
Это текстовая строка, она вынесена из скрипта для удобства. Итак первая строка [0:a]...[vf] фильтр showfreqs из аудиопотока создает видео [vf] (video frequency - это я так назвал, чтобы понятнее было). Следующая строка работает аналогично, но выход фильтра showvolume обозначен как [vv]. Дальше [1:v]...[disk] применяет фильтр rotate к нашей картинке (да [1:v] видеопоток), вывод обозначен как [disk]. Теперь накладываем на [vf] [disk] с помощью фильтра overlay (координаты заданы двумя способами или x,y или из относительных значений, и так и так можно), вывод обозначен как [l1] (layer 1). Аналогично работает и следующая строка, накладывая [vv] на [l1]. Последняя пара [l2] ..[fin] накладывает текст, который берет из файла metadata.txt.
Перейдем к скрипту, я разберу только значимые строки, остальные затруднений не должны вызвать.
data=$(ffprobe -i $mp3 2>&1 | egrep "artist|title") # get some data from mp3 metadada
#Uncomment len to get real duration
#len=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mp3 ) #duration of input, sec
len=20 # for test only
В переменную data попадают подстроки из метаданных, они записываются в файл metadata.txt, который был упомянут выше. len это длительность mp3 в секундах, по умолчание основной механизм закомментирован и длина устанавливается в 20 секунд. Кстати метод определение длительности не совсем точный в теории, но работает.
enc="-c:v h264 -crf 23 -preset medium -tune film -b:v 3M -c:a aac -b:a 192k" #executing string
exe=$(echo "ffmpeg -i $mp3 -loop 1 -i $disk -y -lavfi $filter -ss 00:00:00 -to $len $enc -shortest -map '[fin]' -map 0:a $out")
В переменной enc стоят значения по умолчанию для видеокодека H264. Для YouTube можно уточнить тут. В переменной exe командная строка ffmpeg, тут находится и [fin] из фильтра. Важен ключ -loop 1 перед картинкой, понятно почему. Потоки должны всегда быть соединены, то есть каждый выход должен попадать на вход. Зачем столь странная система - сброс переменной в файл и его запуск? По историческим причинам, отлаживать легче.
Теперь самое главное. Вы можете запустить ./music_vision.sh и получить 20 секунд видео. Но прежде, чем создавать видео, ознакомьтесь с нижеследующими материалами:
Журнал "Tester's Life", нужны номера за апрель 2014 и май 2016, там много про ffmpeg русским по белому.
https://github.com/SonicField/sonic-field-video. Море примеров. Например такой вывод.
Много примеров с видео результатов.
Документация ffmpeg.
Google. Рекомендации для видео YouTube.
REPISOT
Я не увидел, какую оконную функцию вы использовали для спектра. Видимо, по-умолчанию. Попробуйте Хемминга (hamming). Пики частот станут более явными.
zirf Автор
Спасибо, учту, да по умолчанию, то есть win_func=hanning подразумевается.