Я все еще новичок в ffmpeg. Я могу сделать основы с 1-проходной кодировкой crf, но, рискуя использовать 2-проходную кодировку, я сталкиваюсь с ошибкой, которую не могу устранить. Любая помощь приветствуется.

Короче говоря, когда я запускаю следующий скрипт в Ubuntu,

IFS=$'\n'

for i in `ls  *.{ts,mkv,mpeg,mpg,mov,avi,mp4,m2t,mts}`
    do
        #Output naming scheme
        extension=`echo "$i" | egrep -o '\.(ts|mkv|mpeg|mpg|mov|avi|mp4|mts)$'`     
        extensionFreeFileName=$(echo "$i" | awk -F `echo ${extension}` '{print $1}')        
        newFileName="$extensionFreeFileName"

        #Extract proper frame rate from source video
        testFrameFormat='/'
        testFramsString=`mediainfo "$i" | grep "Frame rate  "`

        if [[ "$testFramsString" =~ "$testFrameFormat" ]]; then
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F '[()]' '{print $2}' | head -1`
        else
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F "\: " '{print $2}' | awk -F " " '{print $1}' | awk -F " " '{print $1}' | head -1`
        fi

        #Video bit rate lookup and calculations
        videoBitRate=`mediainfo "$i" | grep "Bit rate  " | head -1 | tail -1 | awk -F' : ' '{print $2}' | awk -F' kb/s' '{print $1}' | sed 's| ||g'`
        videoBitRate=$((videoBitRate * 1024))

        avc35BitRate=$((videoBitRate * 35 / 100))
        avc25BitRate=$((videoBitRate * 25 / 100))
        hevc30BitRate=$((videoBitRate * 30 / 100))
        hevc27BitRate=$((videoBitRate * 27 / 100))
        hevc24BitRate=$((videoBitRate * 24 / 100))
        hevc21BitRate=$((videoBitRate * 21 / 100))
        hevc17BitRate=$((videoBitRate * 17 / 100))

        #check to ensure calculations are being performed as expected
        echo -e "\n\n\n\n"
        echo -e "$i"
        echo -e "$frameRate"
        echo -e "$videoBitRate"
        echo -e "$avc35BitRate"
        echo -e "$avc25BitRate"
        echo -e "$hevc30BitRate"
        echo -e "$hevc27BitRate"
        echo -e "$hevc24BitRate"
        echo -e "$hevc21BitRate"
        echo -e "$hevc17BitRate"
        echo -e "\n\n\n"

        #Encoding command (two-pass, multiple outputs)
        ~/bin/ffmpeg -analyzeduration 500000000 -probesize 500000000 -i "$i" -preset veryslow \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc30BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc30" -an -f matroska /dev/null \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc27BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc27" -an -f matroska /dev/null \        
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc24BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc24" -an -f matroska /dev/null \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc21BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc21" -an -f matroska /dev/null \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc17BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc17" -an -f matroska /dev/null \
            -vf yadif -r "$frameRate" -map 0:v -c:v libx265 -b:V "$avc35BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName avc35" -an -f matroska /dev/null \
            -vf yadif -r "$frameRate" -map 0:v -c:v libx265 -b:V "$avc25BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName avc25" -an -f matroska /dev/null &&
        ~/bin/ffmpeg -analyzeduration 500000000 -probesize 500000000 -i "$i" -preset veryslow \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc30BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc30" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 30pct).mkv" \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc27BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc27" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 27pct).mkv" \     
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc24BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc24" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 24pct).mkv" \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc21BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc21" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 21pct).mkv" \
            -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc17BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc17" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 17pct).mkv" \
            -vf yadif -r "$frameRate" -map 0:v -c:v libx265 -b:V "$avc35BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName avc35" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (AVC 35pct).mkv" \
            -vf yadif -r "$frameRate" -map 0:v -c:v libx265 -b:V "$avc25BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName avc25" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (AVC 25pct).mkv"
done;

Я получаю следующие ошибки:

TwoPassConvert_A-Z.sh: line 50: -vf: command not found
TwoPassConvert_A-Z.sh: line 58: -vf: command not found

которые ссылаются на следующие строки в скрипте, соответственно:

-vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc24BitRate" -x265-params pass=1 -passlogfile "$extensionFreeFileName hevc24" -an -f matroska /dev/null \
-vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -b:V "$hevc24BitRate" -x265-params pass=2 -passlogfile "$extensionFreeFileName hevc24" -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 24pct).mkv" \

Мы будем благодарны за любую помощь, которую вы можете оказать в исправлении этой ошибки.


Кроме того, когда скрипт запускается, я получаю следующее приглашение:

File '/dev/null' already exists. Overwrite ? [y/N]

Есть ли способ, которым я всегда могу ответить «да» при запуске скрипта?


PS Также приветствуются любые предложения о том, как написать часть сценария ffmpeg более эффективно / читабельно (без потери предполагаемой функциональности).

Спасибо!


PPS

Я могу без проблем запустить следующий, похожий, однопроходный скрипт 'crf':

IFS=$'\n'

for i in `ls  *.{ts,mkv,mpeg,mpg,mov,avi,mp4,m2t,mts}`
    do

        extension=`echo "$i" | egrep -o '\.(ts|mkv|mpeg|mpg|mov|avi|mp4|mts)$'`     
        extensionFreeFileName=$(echo "$i" | awk -F `echo ${extension}` '{print $1}')        
        newFileName="$extensionFreeFileName"

        testFrameFormat='/'
        testFramsString=`mediainfo "$i" | grep "Frame rate  "`

        if [[ "$testFramsString" =~ "$testFrameFormat" ]]; then
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F '[()]' '{print $2}' | head -1`
        else
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F "\: " '{print $2}' | awk -F " " '{print $1}' | awk -F " " '{print $1}' | head -1`
        fi

         echo -e "\n\n\n\n\n$frameRate\n\n\n\n\n\n"

                ~/bin/ffmpeg -analyzeduration 500000000 -probesize 500000000 -i "$i" -preset veryslow \
                    -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -crf 24 -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 24).mkv" \
                    -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -crf 26 -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 26).mkv" \
                    -vf bwdif=0:0:0 -r "$frameRate" -map 0:v -c:v libx265 -crf 30 -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (HEVC 30).mkv" \
                    -vf yadif -r "$frameRate" -map 0:v -c:v libx264 -crf 28 -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (AVC 28).mkv" \
                    -vf yadif -r "$frameRate" -map 0:v -c:v libx264 -crf 26 -map 0:a -c:a copy -map 0:s? -c:s copy "./$newFileName (AVC 26).mkv"
done;

ОБНОВЛЕНИЕ 3/3/2018

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

ВНИМАНИЕ: Используйте на свой страх и риск. Я не даю никаких гарантий, что этот скрипт будет работать для ваших конкретных потребностей в вашей вычислительной среде. Обязательно сделайте резервную копию файлов, которые вы кодируете, и выполните это в безопасной среде, чтобы убедиться, что это работает правильно для вас, прежде чем адаптировать его к своим производственным потребностям.

примечание: следующее будет легче читать, если его скопировать и вставить в предпочитаемый вами редактор bash-скриптов (лично мне нравится gedit, который предлагает хорошее цветовое кодирование, если он сохранен с расширением .sh)

IFS=$'\n'

#Script is designed to accept zero or one argument when executing.
#The argument is the path that contains the files you want to encode; syntax: user#bash script.sh [argument-path]
#The following commands ensure that if an argument is entered, it has a trailing '/'
#If no argument is present, it executes from the path your are currently in.

path=$1
pathLength=`echo $path | wc -c`
if [[ "$path" == "" ]]; then 
    path="./" 
    elif [[ "${path:$((pathLength - 2)):1}" == "/" ]]; then
        path="$path"
    else
        path="$path/"
fi

pathLength=`echo $path | wc -c`

#for i in `ls *.{ts,mkv,mpeg,mpg,mov,avi,mp4,m2t,mts}` #alternative to loop through multiple file extensions

for i in `ls "$path"*.mts`
    do

        #move file to local machine (useful if original file) exists on network)
        cp "$i" /tmp && echo "success"
        #format $i variable to work correctly with commands below
        i="${i:$((pathLength - 1))}"
        #assign $j variable to work with the file cp to /tmp to avoid unwanted actions on original file
        j="/tmp/$i"

        #determines file extension, base file name (without extenion), and creates newFileName variable as base file name
        extension=`echo "$i" | egrep -o '\.(ts|mkv|mpeg|mpg|mov|avi|mp4|mts)$'`     
        extensionFreeFileName=$(echo "$i" | awk -F `echo ${extension}` '{print $1}')        
        newFileName="$extensionFreeFileName"

        #get frame rate of original video in order to match frame rate when encoding (designed to work with only one video stream))
        #requires 'mediainfo' to be installed
        testFrameFormat='/'
        testFramsString=`mediainfo "$i" | grep "Frame rate  "`

        if [[ "$testFramsString" =~ "$testFrameFormat" ]]; then
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F '[()]' '{print $2}' | head -1`
        else
            frameRate=`mediainfo "$i" | grep "Frame rate  " | awk -F "\: " '{print $2}' | awk -F " " '{print $1}' | awk -F " " '{print $1}' | head -1`
        fi

        #Visual confirmation that frame rate extracted from original video makes sense (either fractional 30000/1001 or decimal 29.970 format)
        echo -e "\n\n\n\n\n$frameRate\n\n\n\n\n\n"

            #Video bit rate lookup and calculations for desire output bitrate (5 percent in this instance)
            videoBitRate=`mediainfo "$i" | grep "Bit rate  " | head -1 | tail -1 | awk -F' : ' '{print $2}' | awk -F' kb/s' '{print $1}' | awk -F' Mb/s' '{print $1}' | sed 's| ||g'`
            videoBitRate=`echo "$videoBitRate *1024 * 1024" | bc | awk -F'.' '{print $1}'`

            #Note: 5 percent of original video bit rate won't work in most situations
            #My video is highly static (virtually no movement) and does not require a high bit rate for quality output
            #For encoding MPEG-2 original with moderate level of movement, I recomment a minimum of 50% for AVC and 25% for HEVC
            #For enciding AVC original with moderate movement to HEVC, I recommend a minimum of 50%
            #Ideally, you should experiment with a smaller extracted portion of video with highest motion using:
            # user# ffmpeg -ss [start time in 00:00:00.000 format] -i source -t [duration in seconds] \
            #           [video codecs like those shown below]
            #After determining what is acceptable to you, modify the target bitrates in the next two lines

            hevc05BitRate=`echo "$videoBitRate * 5 / 100" | bc | awk -F'.' '{print $1}'`
            avc05BitRate=`echo "$videoBitRate * 5 / 100" | bc | awk -F'.' '{print $1}'`

            # ffmpeg command and options

            ~/bin/ffmpeg -y -analyzeduration 500000000 -probesize 500000000 -i "$j" -preset slow \
                -map 0:v -c:v libx265 -b:v "$hevc05BitRate" -x265-params pass=1:stats=/tmp/passA -an -f matroska /dev/null \
                -map 0:v -c:v libx264 -b:v "$avc05BitRate" -x264-params pass=1:stats=/tmp/passB -an -f matroska /dev/null && \
            ~/bin/ffmpeg -y -analyzeduration 500000000 -probesize 500000000 -i "$j" -preset slow \
                -vf bwdif=0:0:0 -map 0:v -c:v libx265 -b:v "$hevc05BitRate" -x265-params pass=2:stats=/tmp/passA -map 0:a -c:a copy -map 0:s? -c:s copy "/tmp/$newFileName (HEVC 05pct).mkv" \
                -vf yadif -map 0:v -c:v libx264 -b:v "$avc05BitRate" -x264-params pass=2:stats=/tmp/passB -map 0:a -c:a copy -map 0:s? -c:s copy "/tmp/$newFileName (AVC 05pct).mkv"

            # When two-pass is complete, move the newly encoded files to their target destination
            mv "/tmp/*AVC*" "/media/WinE/School Videos/"
            mv "/tmp/*HEVC*" "/media/WinE/School Videos/"
            # Remove temporary source file (NOTE: original file should still be untouched)
            rm "$j"
done;

1 ответ1

0

Удалите завершающие пробелы после \ в строках 49 и 57.

Обратная косая черта - это экранирование, которое следует за следующей строкой (не посторонние пробелы).

Чтобы перезаписать файл, предположите yes, чтобы перезаписать с -y (например, ffmpeg -y ...).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .