FFmpeg | Пакетная обработка. Рекурсивное наложение логотипа

от
FFmpeg    batch processing, batch converting, массовая обработка, пакетное конвертирование, вложенные папки, рекурсивно, recursive

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


ЗадачаВ папке находится файл logo.png, а также несколько вложенных папок, в которых есть видео в формате mp4:
  1. folder/
  2.  - logo.png
  3.  - video1.mp4
  4. folder2/
  5.  - видео 2.mp4
  6. Новая папка/
  7.  - видео3.mp4
  8.  - videos/
  9.    - video 4.mp4
Для каждого такого видео нужно наложить логотип в правый нижний угол и сохранить с именем, в котором будет суффикс -logo. Например, было видео3.mp4, а станет видео3-logo.mp4

Содержание:
  - Рекурсивное наложение логотипа (Windows)
  - Рекурсивное наложение логотипа (Linux)

Рекурсивное наложение логотипа (Windows)Воспользуемся скриптом, который мы написали в прошлой статье и сразу же заменим в нём webm на mp4, так как теперь работать будем именно с этими файлами.
Создаём текстовый файл add-logo.bat или add-logo.cmd:
  1. @echo off
  2. for %%i in (*.mp4) do (
  3.   echo ffmpeg -i "%%i" "%%~ni.mp4"
  4. )

Сейчас он находит только файлы в текущей папке. Чтобы добавить поиск по вложенным папкам, необходимо после for прописать ключ /r
  1. @echo off
  2. for /r %%i in (*.mp4) do (
  3.   echo ffmpeg -i "%%i" "%%~ni.mp4"
  4. )
Запускаем скрипт:
  1. ffmpeg -i "R:\vid\folder\video1.mp4" "video1.mp4"
  2. ffmpeg -i "R:\vid\folder2\видео 2.mp4" "видео 2.mp4"
  3. ffmpeg -i "R:\vid\Новая папка\видео3.mp4" "видео3.mp4"
  4. ffmpeg -i "R:\vid\Новая папка\videos\video 4.mp4" "video 4.mp4"

Половина дела сделана. Теперь добавим уже знакомый нам фильтр overlay:
  1. @echo off
  2. for /r %%i in (*.mp4) do (
  3.   echo ffmpeg -y -i "%%i" -i logo.png ^
  4.       -filter_complex "[0:v][1:v]overlay=W-w-20:H-h-20" ^
  5.       "%%~dpni-logo.mp4"
  6. )
Логотип будет накладываться с отступом в 20 пикселей от правого нижнего края.
%%~dpni получает путь к файлу без расширения
d - drive (буква диска), p - path (основной путь), n - имя файла без расширения.

Скрипт уже можно считать рабочим. Но хотелось бы вынести параметры куда-нибудь повыше, чтобы не искать их в скрипте (особенно, если он будет большим).
Можно вынести имя файла логотипа в отдельную переменную. Чтобы объявить переменную, используем:
  1. set logo=logo.png
чтобы указать переменную в скрипте, используем:
  1. %logo%
Можно вынести ещё и позицию логотипа:
  1. @echo off
  2. set logo=logo.png
  3. set logo_x=W-w-20
  4. set logo_y=H-h-20
  5. for /r %%i in (*.mp4) do (
  6.   echo ffmpeg -y -i "%%i" -i %logo% ^
  7.       -filter_complex "[0:v][1:v]overlay=%logo_x%:%logo_y%" ^
  8.       "%%~dpni-logo.mp4"
  9. )

Запускаем и проверяем, что все данные правильно подставились. Вообще, запускайте как можно чаще при небольших изменениях, это даст понять, что на предыдущем шаге что-то пошло не так.

Напоследок, давайте добавим возможность указывать файл логотипа параметром к скрипту. Если скрипт запущен без параметров, то пусть используется logo.png.
  1. set logo=%1
  2. if "%logo%" == "" (
  3.   set logo=logo.png
  4. )
%1 — первый параметр, который пришёл скрипту.
if "%logo%" == "" — проверяет, является ли значение логотипа пустым или нет. Если является, то выполняется строка в скобках, которая устанавливает переменной logo значение logo.png
При таком подходе можно будет либо перетягивать файл логотипа на файл скрипта и получать готовые видео, либо указывать файл из командной строки:
  1. add-logo.cmd 123.png

Готовый скрипт:
  1. @echo off
  2. set logo=%1
  3. if "%logo%" == "" (
  4.   set logo=logo.png
  5. )
  6. set logo_x=W-w-20
  7. set logo_y=H-h-20
  8.  
  9. for /r %%i in (*.mp4) do (
  10.   ffmpeg -y -hide_banner -i "%%i" -i %logo% ^
  11.       -filter_complex "[0:v][1:v]overlay=%logo_x%:%logo_y%" ^
  12.       "%%~dpni-logo.mp4"
  13. )
-hide_banner убирает информацию о версии ffmpeg.


Рекурсивное наложение логотипа (Linux)Воспользуемся скриптом, который мы написали в прошлой статье и сразу же заменим в нём webm на mp4, так как теперь работать будем именно с этими файлами.
Создаём текстовый файл add-logo.sh:
  1. #!/bin/bash
  2. for file in *.mp4; do
  3.   echo ffmpeg -i "$file" "${file%.mp4}.mp4"
  4. done

Сейчас он находит только файлы в текущей папке. Чтобы добавить поиск по вложенным папкам, необходимо воспользоваться утилитой find:
  1. #!/bin/bash
  2. find . -type f -iname "*.mp4" -print0 | while read -d $'\0' file; do
  3.   echo ffmpeg -i "$file" "${file%.mp4}.mp4"
  4. done
Запускаем скрипт:
  1. ffmpeg -i ./folder/video1.mp4 ./folder/video1.mp4
  2. ffmpeg -i ./folder2/видео 2.mp4 ./folder2/видео 2.mp4
  3. ffmpeg -i ./Новая папка/videos/video 4.mp4 ./Новая папка/videos/video 4.mp4
  4. ffmpeg -i ./Новая папка/видео3.mp4 ./Новая папка/видео3.mp4

Половина дела сделана. Теперь добавим уже знакомый нам фильтр overlay:
  1. #!/bin/bash
  2. find . -type f -iname "*.mp4" -print0 | while read -d $'\0' file; do
  3.   echo ffmpeg -y -i "$file" -i logo.png \
  4.       -filter_complex "[0:v][1:v]overlay=W-w-20:H-h-20" \
  5.       "${file%.mp4}-logo.mp4"
  6. done
Логотип будет накладываться с отступом в 20 пикселей от правого нижнего края.

Скрипт уже можно считать рабочим. Но хотелось бы вынести параметры куда-нибудь повыше, чтобы не искать их в скрипте (особенно, если он будет большим).
Можно вынести имя файла логотипа в отдельную переменную. Чтобы объявить переменную, используем:
  1. logo=logo.png
чтобы указать переменную в скрипте, используем:
  1. $logo
Можно вынести ещё и позицию логотипа:
  1. #!/bin/bash
  2. logo=logo.png
  3. logo_x=W-w-20
  4. logo_y=H-h-20
  5. find . -type f -iname "*.mp4" -print0 | while read -d $'\0' file; do
  6.   echo ffmpeg -y -i "$file" -i $logo \
  7.       -filter_complex "[0:v][1:v]overlay=$logo_x:$logo_y" \
  8.       "${file%.mp4}-logo.mp4"
  9. done

Запускаем и проверяем, что все данные правильно подставились. Вообще, запускайте как можно чаще при небольших изменениях, это даст понять, что на предыдущем шаге что-то пошло не так.
⚠️ Если ffmpeg выдаёт
  1. error parsing debug value
  2. debug=0
нужно после команды ffmpeg добавить < /dev/null
  1. ffmpeg -i $file ... out.mp4 < /dev/null

Напоследок, давайте добавим возможность указывать файл логотипа параметром к скрипту. Если скрипт запущен без параметров, то пусть используется logo.png.
  1. logo=${1:-logo.png}
$1 или ${1} — первый параметр, который пришёл скрипту.
${1:-logo.png} — специальная конструкция Bash, которая устанавливает значение по умолчанию (logo.png) в случае, если первый параметр пуст.
При таком подходе можно будет указывать файл из командной строки:
  1. ./add-logo 123.png

Готовый скрипт:
  1. #!/bin/bash
  2. logo=${1:-logo.png}
  3. logo_x=W-w-20
  4. logo_y=H-h-20
  5. find . -type f -iname "*.mp4" -print0 | while read -d $'\0' file; do
  6.   ffmpeg -y -hide_banner -i "$file" -i $logo \
  7.       -filter_complex "[0:v][1:v]overlay=$logo_x:$logo_y" \
  8.       "${file%.mp4}-logo.mp4" < /dev/null
  9. done
-hide_banner убирает информацию о версии ffmpeg.

  • +2
  • views 3878