LINUX.ORG.RU

Презентация на ffmpeg

 ,


0

3

Здравствуйте.

Задача состоит в следующем:

  1. имеется набор картинок (слайдов);
  2. для каждой картинки определен файл со звуком (например, mp3);
  3. продолжительность звучания каждого звукового файла известна;
  4. картинка должна экспонироваться на видео столько же, сколько проигрывается звуковой файл (можно больше);
  5. картинки могут быть разного размера, поэтому их надо растянуть до размера кадра (можно непропорционально, можно с обрезкой, можно с черными полями);
  6. имена файлов можно сделать любыми;
  7. желательно, все реализовать одной командой.

Собственно сам процесс создания видеофайла из одной картинки и одного звукового файла у меня получился так:

ffmpeg -loop 1 -i 01.png -i 1697614834.mp3 -t 12 -r 5 -vf scale=1365:768 slide01.mp4

После чего можно собрать все слайды в одно видео, но хотелось бы все это реализовать одной командой.

Для примера можно использовать следующие данные:

  • слайд 1: 01.png, 01.mp3, 7 сек.
  • слайд 2: 02.png, 02.mp3, 5 сек.
  • слайд 3: 03.png, 03.mp3, 9 сек.


Последнее исправление: JoeMaputo (всего исправлений: 2)

Откуда эта одна команда должна знать имя mp3-файла, соответствующего картинке?

Если их переименовать их так, чтобы они были тоже пронумерованы, то всё просто:

for f in $(seq 99); do ffmpeg -i "$i.png" -i "$i.mp3" -c:a copy -r 5 scale=1365:768 slide$i.mp4; done

99 — количество файлов картинок.

Ну и потом собираешь в один, как нужно

CrX ★★★
()
Ответ на: комментарий от JoeMaputo

Одной командой ffmpeg если и можно (в чём я не уверен), то как-то очень геморно будет, особенно если файлов много. Откуда-то ему ведь нужно знать, какую картинку с каким звуком совмещать… Циклом тупо проще.

Можно список в txt собрать и потом использовать -concat. Но создание списка — это уже дополнительная команда всё равно.

CrX ★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Просто, не хотелось бы создавать промежуточные файлы, поэтому хочется все одной командой.

Имена файлов и длительности слайдов будут подставляться при сборке строки команды в скрипте.

Вот в этой статье видел похожий пример, но там все слайды одинаковой длительности и автор ничего не поясняет: https://azzrael.ru/ffmpeg-5-video-from-pics-texts-music#comment-84475

JoeMaputo
() автор топика
Ответ на: комментарий от JoeMaputo

надо все одной командой ffmpeg

Анекдот_про_первую_команду_установки_gentoo.txt

не хотелось бы создавать промежуточные файлы, поэтому хочется все одной командой

Это не связанные вещи.

То, что тебе нужно, делается циклом, как выше предложили. Не усложняй на ровном месте, это глупо.

alex1101
()
Ответ на: комментарий от alex1101

Вопрос «зачем в одну команду?» не стоит на повестке.

Меня, в принципе, устроило объяснение конструкции -filter_complex в команде из статьи, указанной в предыдущем моем коментарии. Вот сама команда, которая собирает презентацию из 3х картинок и одного музыкального файла (+ добавляет текст на картинки):

ffmpeg -f lavfi -i color=c=gray:s=1080x720 ^
 -i C:\Drive\Programming\Azzrael_YT\ffmpeg\data\music.mp3 
 -loop 1 -i C:\Drive\Programming\Azzrael_YT\ffmpeg\data\kup1.jpg ^
 -loop 1 -i C:\Drive\Programming\Azzrael_YT\ffmpeg\data\kup2.jpg ^
 -loop 1 -i C:\Drive\Programming\Azzrael_YT\ffmpeg\data\kup3.jpg ^
 -t 27 ^
 -filter_complex "[2]scale=-1:'if(between(t, 0, 3), 2160 - (t - 1)*720, 1)':eval=frame[i12],[2]scale=-1:'if(between(t, 3, 6), 720,1)':eval=frame[i22],[2]scale=-1:'if(between(t, 6, 9), 720 + 960.0*(t-6) , 1)':eval=frame[i32],[3]scale=-1:'if(between(t, 9, 12), 2160 - (t - 10)*720, 1)':eval=frame[i13],[3]scale=-1:'if(between(t, 12, 15), 720,1)':eval=frame[i23],[3]scale=-1:'if(between(t, 15, 18), 720 + 960.0*(t-15) , 1)':eval=frame[i33],[4]scale=-1:'if(between(t, 18, 21), 2160 - (t - 19)*720, 1)':eval=frame[i14],[4]scale=-1:'if(between(t, 21, 24), 720,1)':eval=frame[i24],[4]scale=-1:'if(between(t, 24, 27), 720 + 960.0*(t-24) , 1)':eval=frame[i34],[0][i12]overlay=(W-w)/2:(H-h)/2[x21],[x21][i22]overlay=(W-w)/2:(H-h)/2[x22],[x22][i32]overlay=(W-w)/2:(H-h)/2[b2],[b2][i13]overlay=(W-w)/2:(H-h)/2[x31],[x31][i23]overlay=(W-w)/2:(H-h)/2[x32],[x32][i33]overlay=(W-w)/2:(H-h)/2[b3],[b3][i14]overlay=(W-w)/2:(H-h)/2[x41],[x41][i24]overlay=(W-w)/2:(H-h)/2[x42],[x42][i34]overlay=(W-w)/2:(H-h)/2,drawtext=text='2020 сексуальные женские бикини':font=Arial:fontsize=40:fontcolor=#DD0000:borderw=2:bordercolor=white:y=H - 5*50:x='if(between(t, 0, 6), (W - (t - 0)*( (w - 100)/6)), 100)':enable='between(t, 0, 27)',drawtext=text='687 руб.':font=Arial:fontsize=40:fontcolor=#DD0000:borderw=2:bordercolor=white:y=H - 4*50:x='if(between(t, 6, 12), (W - (t - 6)*( (w - 100)/6)), 100)':enable='between(t, 6, 27)',drawtext=text='бесплатная доставка':font=Arial:fontsize=40:fontcolor=#DD0000:borderw=2:bordercolor=white:y=H - 3*50:x='if(between(t, 12, 18), (W - (t - 12)*( (w - 100)/6)), 100)':enable='between(t, 12, 27)',drawtext=text='https\://aliexpress.ru/item/4000334756839.html':font=Arial:fontsize=40:fontcolor=#DD0000:borderw=2:bordercolor=white:y=H - 2*50:x='if(between(t, 18, 24), (W - (t - 18)*( (w - 100)/6)), 100)':enable='between(t, 18, 27)'[end]" ^
 -map [end]:v -map 1:a -shortest -y c:\_tmp\out.mp4
JoeMaputo
() автор топика
Ответ на: комментарий от JoeMaputo

Промежуточные файлы можно не создавать, если перенаправить вывод ffmpeg в стандартный вывод, а затем стандартный вывод скормить в стандартный ввод склеющего ffmpeg или даже сразу в файл, если выбрать контейнер видео поддерживающий склейку на уровне файлов.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 1)

У ffmpeg крайне замороченный механизм склеивания фрагментов ffmpeg -i "concat:video1.ts|video2.ts|", причём нужен формат .ts без каких то меток длительности. Есть альтернативная операция с предварительным созданием файла со списком фрагментов. Свести всё в одну команду будет очень заморочено.

Рекомендую какой нибудь kdenlive (думаю он сумеет использовать картинку вместо видео). Если найти и осилить настройки - можно будет всё быстро накидывать налинейку, а сборку он сам одним проходом сделает.

kirill_rrr ★★★★★
()