Bash: цикл команда ffmpeg через наборы подпапок и направляет его в файлы в папках для обработки - PullRequest
0 голосов
/ 07 декабря 2018

Я играю с встраиванием подписей в видеофайлы mp4 и хочу найти способ сделать это в больших наборах каталогов с файлами .mp4 и .srt в них.Каждая пара файлов .mp4 и .srt будет вложена в отдельную папку, и между ними должно быть одинаковое базовое имя.Пример:

Video1
  Video1.mp4
  Video1.srt
Video2
  Video2.mp4
  Video2.srt

Я пробовал несколько вещей, но я новичок в этом и пишу только очень простые скрипты bash для гораздо более простых процессов.Для этого мне нужно выяснить, как написать скрипт bash для запуска команды ffmpeg в каждой подпапке, которая будет захватывать файлы mp4 и srt и выводить новый mp4 объединенных данных.Основная команда ffmpeg для этого:

ffmpeg -i filename.mp4 -i filename.srt -c copy -c:s mov_text output.mp4

Я пытался добавить:

for dir in ./*/; do ffmpeg -i *.mp4 -i *.srt -c copy -c:s move_text “$file”.mp4

… и несколько вариантов этого, но ffmpeg всегда останавливается на «*.mp4: нет такого файла или каталога »ошибка.Затем я попытался добавить «for file in ...» после оператора «for dir in», но безрезультатно.Следующее является наиболее близким к тому, что мне нужно - оно, по крайней мере, идет в каждую папку и обрабатывает файлы - но оно делает их независимо и не объединяет исходные файлы mp4 и srt, как должна делать команда ffmpeg.Он выводит video.mp4.mp4 и video.srt.mp4 и не может объединить их в любом случае.

for dir in ./**/*;
do ffmpeg -i "$dir" -i "$dir" -c copy -c:s mov_text "$dir".mp4

Я пробовал "$ dir" .mp4 и "$ dir" .srt, но этопросто приводит к ошибке.Я пытался получить только имена каталогов:

for dir in ./**/*;
do ffmpeg -i "$(basename $dir)" -i "$(basename $dir)" -c copy -c:s mov_text "$dir".mp4

, и мои попытки использовать «$ (basename $ dir) .extension» привели к ошибкам - он ищет video.mp4.mp4 или video.srt.mp4,Будем весьма благодарны за любые советы о том, что добавить, чтобы заставить этот процесс работать или совсем другой подход.Я полагаю, что это простая штуковина, о которой я просто не знаю, но, конечно, нужно научиться делать!Спасибо!

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

В качестве настройки превосходного ответа ogizismail ниже приведен подход, который работает с версиями bash, слишком старыми для поддержки globstar:

while IFS= read -r -d '' v; do
  s=${v%.mp4}.srt
  [[ -e $s ]] && ffmpeg -i "$v" -i "$s" -c copy -c:s mov_text "${v##*/}"
done < <(find . -mindepth 2 -name '*.mp4' -printf '%P\0')

Общая техникаобсуждается в Использование Find .Использование -mindepth 2 останавливает его нахождение уже выведенных выходных файлов.

0 голосов
/ 07 декабря 2018

Запустите это в директории, содержащей Video1/, Video2/ ...

#!/bin/bash -e
shopt -s globstar
for v in ./**/*.mp4; do
    s=${v%.*}.srt
    if [ -f "$s" ]; then
        ffmpeg -i "$v" -i "$s" -c copy -c:s mov_text "${v##*/}"
    fi
done
  • ./**/*.mp4 расширяется до ./Video1/Video1.mp4 ./Video1/Video2.mp4 ...,
  • ${v%.*} удаляетрасширение (./Video1/Video1.mp4> ./Video1/Video1),
  • [ -f "$s" ] проверяет, существует ли $s (то есть ./Video1/Video1.srt),
  • ${v##*/} извлекает базовое имя $v(./Video1/Video1.mp4> Video1.mp4).

Таким образом, окончательная структура . будет иметь вид:

Video1.mp4    # subbed
Video1
  Video1.mp4
  Video1.srt
Video2.mp4    # subbed
Video2
  Video2.mp4
  Video2.srt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...