Двойное расширение файла с FFmpeg

Я пытаюсь заставить FFmpeg проходить все файлы и подпапки под путем, в котором я выполняю команду, для преобразования любого файла MKV в контейнер MP4 вместо этого.

Я имею ниже работы команды, но новый файл MP4, который создается все еще, имеет расширение MKV в дополнение к новому расширению MP4.

find ./ -iname '*.avi' -o -iname '*.mkv' -exec bash -c 'ffmpeg -i "{}" -vcodec copy -acodec copy "{}".mp4' \;

Например:

abcd.mkv (original file)  
abcd.mkv.mp4 (new file)

Как я корректирую команду для избавлений от исходного расширения файла?

3
задан 1 October 2018 в 12:26

4 ответа

Существует более легкий способ сделать это путем помещения Вашего ffmpeg команда в a bash сценарий и использование bash инструменты. Вместо:

find ./ -iname '*.avi' -o -iname '*.mkv' -exec \
    bash -c 'ffmpeg -i "{}" -vcodec copy -acodec copy "{}".mp4' \;

Использовать find и xargs передать список имен файлов (включая имена файлов с пробелами) к, например, $HOME/bin/fixthem (читайте man find;man xargs):

find . -type f -iname '*.avi' -o -iname '*.mkv' -print0  |\
    xargs -0 -r $HOME/bin/fixthem

С $HOME/bin/fixthem будучи чем-то как (и chmod +x'd):

Примечание: непротестированный, но пробегает /usr/bin/shellcheck.

#!/bin/bash
# convert the *.mkv and *.avi files to .mp4

# determine my name
me=$0
me=${me##*/}

# -h or --help 
help () {
    cat >&2 <<EOF
${me} [-h|--help] [-d|--debug] [-v|--verbose] [-n|--noaction] file file ...
${me}: -h or --help      This message
${me}: -d or --debug     List the commands we execute, as we process
${me}:                   the files.
${me}: -v or --verbose   List the filenames we process, as we process
${me}:                   the files.
${me}: -n or --noaction  Don't actually execute the commands. Used in
${me}:                   connection with --debug for testing.
${me}: -r or --remove    Remove the input file unless --debug is set.
EOF
    exit 2
}

declare -i debug=0 verbose=0 noaction=0 remove=0

# from /usr/share/doc/util-linux/examples/getopt-parse.bash 2015-Sep-06

TEMP=$(getopt -o dhvnr --long debug,help,verbose,noaction,remove \
     -n 'fixthem.bash' -- "$@")

if [[ $? != 0 ]] ; then echo "${me} --help for help." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -d|--debug) debug=1; shift;;
        -h|--help) help; shift;;
        -v|--verbose) verbose=1; shift;;
        -n|--noaction) noaction=1; shift;;
        -r|--remove) remove=1; shift;;
        --) shift; break;;
        *) echo "Internal error! ${me} --help for help";exit 1;;
    esac
done

# actual processing begins here
while [[ $# -gt 0 ]] ; do
      infile="$1"
      shift
      nameonly="${infile%.*}"
      outfile="${nameonly}.mp4"
      [[ "$verbose" -ne 0 ]] && echo "$infile -> $outfile" >&2
      command="ffmpeg -i \"$infile\" -vcodec copy -acodec copy \"$outfile\""
      [[ "$debug" -ne 0 ]] && echo "command" >&2
      [[ "$noaction" -ne 0 ]] || eval "$command"
      if [[ "$remove" -ne 0 ]] ; then
      v=""
      [[ "$verbose " -ne 0 ]] && v="-v"
      if [[ "$debug" -ne 0 ]] ; then
          echo "rm \"$infile\"" >&2
      else
          rm $v "$infile"
      fi
      fi
done

exit 0
0
ответ дан 1 December 2019 в 16:51

Если Вы стремитесь сохранить свой существующий синтаксис (который, вероятно, имеет смысл Вам, как это), следующая небольшая модификация должна сохранить это значение, также выполняя необходимое переименование имени файла:

find -iname '*.avi' -o -iname '*.mkv' -exec \
    bash -c 'ffmpeg -i "{}" -codec copy \
    $(echo "{}" | sed -r 's/.{3}$/mp4/')' \;

Обратите внимание, что я также упростил Ваш copy синтаксис с FFmpeg...

2
ответ дан 1 December 2019 в 16:51

Другой способ, если в ваших именах файлов нет пробелов, новых строк или других странных символов:

for file in $(find -iname '*.avi' -o -iname '*.mkv')

do
ffmpeg -i $file -codec copy ${file%%.*}.mp4
done

Это удаляет любое расширение после последней точки (.), А затем добавляет . mp4 . Если в именах файлов могут быть пробелы, используйте это вместо:

find . -iname '*.avi' -o -iname '*.mkv' -print0 | while read -d $'\0' file;

do
  ffmpeg -nostdin -i "$file" -codec copy ${file%%.*}.mp4
done
0
ответ дан 19 December 2019 в 18:36

Поскольку возиться с большим количеством кода было непросто, я просто добавил команду переименования перед началом кодирования и удалил . расширение mp4.

ren Troc*.mp4 Troc*.
for %%a in ("Troc*.") do "F:\Dropbox\PortableApps\ffmpeg" -i "%%a" -c:v libx264  -crf 22 -c:a aac -b:a 128k "%%a(ff).mp4"

Вот скриншот из моей папки:

thumbnails appear correct for files with adjusted names

0
ответ дан 5 June 2020 в 08:32

Другие вопросы по тегам:

Похожие вопросы: