ffmpeg - переменная CRF на основе Bitare

ffmpeg - переменная CRF на основе Bitare

Я использую ffmpeg для кодирования некоторых видео, которые я скачал с разных потоковых сайтов, в HEVC. В Windows я использую пакетный файл для конвертации всех этих файлов в каталоге.

ffmpeg -n -i input.mp4 -c:v libx265 -crf 22 -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio output.mkv

Общий битрейт этих видео варьируется от 300 кбит/с до 1500 кбит/с. В моем тестировании с использованием одного и того же CRF для всех этих видео был получен либо больший выходной файл в случае видео с высоким битрейтом, либо видео низкого качества в случае низкого битрейта. Поэтому я вручную изменяю CRF для группы видео с похожим битрейтом. Как мне добиться этого с помощью пакетного файла. Например, если общий битрейт выше 950 = crf 26, если общий битрейт между 750 и 949 = crf 24, если общий битрейт между 500 и 749 = crf 22, если общий битрейт ниже 499 = crf 18

решение1

@echo off & color 0A & cls 

cd /d "%~dp0" && setlocal enabledelayedexpansion
set "_ffmpeg=F:\2020-SU\Q1569837\ffmpeg\bin\ffmpeg.exe"
set "_ffprobe=F:\2020-SU\Q1569837\ffmpeg\bin\ffprobe.exe"
set "_range_crf=99999-950-26,949-750-24,749-500-22,499-0-18"

for %%# in (*.mp4)do echo; && set /a "_c+=1+0" && for /f tokens^=2^,6^delims^=^,^  %%i in ('
2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#"^|%__APPDIR__%findstr.exe /e [0-9].kb/s
')do echo\Check File: "%%~nx#" ^| Bite Rate: %%~j kb/s && call :^) "!_range_crf!" "%%~j" "%%~n#" "%%~f#" 

echo\ & <con: rem./ && echo\Total Files: 000!_c! && %__APPDIR__%timeout.exe /t -1 & endlocal && goto=:EOF

:^) 
echo\ && for %%i in (%~1)do for /f "tokens=1-3delims=-" %%a in ('echo\%%~i
')do if %~2 leq %%~a if %~2 geq %%~b title<nul & title .:^| File Name:"..\%~nx4" ^| Bite Rate: %~2 kb/s ^|:. && (
       "!_ffmpeg!" -y -i "%~4" -hide_banner -v error -stats -c:v libx265 -crf %%~c -c:a libopus -b:a 48k -vbr on ^
          -compression_level 10 -frame_duration 60 -application audio "%~3.mkv" && exit /b 0 )
  • Механик позади forи ifs...
       %2       %%a         %2      %%b              %%c         
:: if 951 leq 99999 and if 951 GEQ  950 = True  crf = 26 then Exit /loop :label
:: if 951 leq   949 and if 951 GEQ  750         crf = 24 then      /loop :label 
:: if 951 leq   749 and if 951 GEQ  500         crf = 22 then      /loop :label 
:: if 951 leq   499 and if 951 GEQ    0         crf = 18 then      /loop :label 
::
:: if 800 leq   999 and if 800 GEQ  950 = False crf = 26 then Keep /loop :label
:: if 800 leq   949 and if 800 GEQ  750 = True  crf = 24 then Exit /loop :label
:: if 800 leq   749 and if 800 GEQ  500         crf = 22 then      /loop :label 
:: if 800 leq   499 and if 500 GEQ    0         crf = 18 then      /loop :label 
::
:: if 600 leq   999 and if 600 GEQ  950 = False crf = 26 then Keep /loop :label
:: if 600 leq   949 and if 600 GEQ  750 = False crf = 24 then Keep /loop :label
:: if 600 leq   749 and if 600 GEQ  500 = True  crf = 22 then Exit /loop :label 
:: if 600 leq   499 and if 600 GEQ    0         crf = 18 then      /loop :label 
::
:: if 501 leq   999 and if 501 GEQ  950 = False crf = 26 then Keep /loop :label
:: if 501 leq   949 and if 501 GEQ  750 = False crf = 24 then Keep /loop :label
:: if 501 leq   749 and if 501 GEQ  500 = True  crf = 22 then Exit /loop :label
:: if 501 leq   499 and if 501 GEQ    0         crf = 18 then      /loop :label 
:: 
:: if 498 leq   999 and if 498 GEQ  950 = False crf = 26 then Keep /loop :label
:: if 498 leq   949 and if 498 GEQ  750 = False crf = 24 then Keep /loop :label
:: if 498 leq   749 and if 498 GEQ  500 = False crf = 22 then Keep /loop :label
:: if 498 leq   499 and if 498 GEQ    0 = True  crf = 18 then Exit /loop :label

Наблюд.: 1Естьдва пробеламежду^=^,^⟵⟶%%iв: delims^=^,^spacespace%%i

for %%# in (*.mp4)do for /f tokens^=2^,6^delims^=^,^spacespace%%i in (...


1.- Ваше домашнее задание: замените переменные ниже способом, совместимым с вашим сценарием, также перейдите в папку bat:

set "_ffmpeg=F:\2020-SU\Q1569837\ffmpeg\bin\ffmpeg.exe"
set "_ffprobe=F:\2020-SU\Q1569837\ffmpeg\bin\ffprobe.exe"

cd /d "%~dp0"

rem :: if your *.pm4 files are not in the same directory 
rem :: as your bat file, use the full path to drive/folder 
rem :: Example for drive D: folder/subfolder \Media\MP4\Convert 

cd /d "D:\Midia\MP4\Convet"

2.В этом пакете используется несколько for loop, для его работы вам необходимо включить Deleyed Expansion, чтобы переменные получали обновленные/расширенные значения во время выполнения:

Setlocal EnableDelayedExpansion

3.Определите переменную, разделенную запятой и содержащую между разделителем значения, которые будут использоваться в ifцикле for, чтобы можно было работать с максимальным значением, минимальным значением и совместимыми crf:

set "_range_crf= max-min-crf,max-min-24,max-500-22,499-0-18"
set "_range_crf=99999-950-26,949-750-24,749-500-22,499-0-18"

4.Используйте простой forцикл и один для перечисления ваших.mp4файлы и, кроме того, использовать счетчик (set /a "_c+=1+0")чтобы получить общую сумму в конце прогона:

for %%# in (*.mp4)do echo; && set /a "_c+=1+0"
  • Наблюдения: 2Theecho;используется только для разрыва строки и упрощения визуализации в исполнении, создавая разделительную линию в цикле.

5.Используйте дополнительный параметр, чтобы использовать эту переменную цикла (в ), где вы получили полный путь/имя ( ) файла mp4, и передайте этот цикл в качестве входных данных для уже определенного (объясняется наfor /f1st/for/var==%%#%%~f#ffprobeпункт 5.), токены и разделители, которые следует использовать в этой команде.

for /f tokens^=2^,6^delims^=^,^  %%i in (ffmprobe ...  %%~f# ... 

6.TheffprobeКоманда, используемая в цикле:for /f

..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mp4"

7.Начиная с перенаправления StdErrвывода StdOut, ffprobeкоторый будет отфильтрован, findstrс помощью переключателя с/End of a lineregexчисла ([0-9]) объединены со строкой .kb/sи используют правильное выделение вforпетля:

2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#" ^| "%__APPDIR__%findstr.exe" /e [0-9].kb/s

8.Приведенная выше расширенная команда без экранированных символов приводит к следующему результату:

2>&1 ..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mkv" | "%__APPDIR__%findstr.exe" /e [0-9].kb/s

9.Вывод вышеуказанной команды, обработанный фильтром, findstrприводит к следующему:

Продолжительность: 00:01:00.08, начало: -0.007000, битрейт: 350 кб/с

10.Вывод вышеуказанной команды, обработанный фильтром, findstrприводит к следующему:

Продолжительность: 00:01:00.08, начало: -0.007000, битрейт: 350 кб/с

11.Используя несколько разделителей, строки в%%iи%%jвыход будет00:01:00.08и350: для вывода последней команды, будет00:01:00.08и350:

... for /f tokens^=2^,6^delims^=^,^space %%i in (...
Duration: 00:01:00.08, start: -0.007000, bitrate: 350 kb/s

введите описание изображения здесь

12.

Предположим, что ваше предельное значение равно350(включительно) для Bite Rate вам нужно будет использовать некоторую ifопцию в рабочей части:

 if %%~j > Bit_Rate      ∕∕ the same:  if %%~j > 349  (349 exclusive) 
 if %%~j  Bit_Rate      ∕∕ the same:  if %%~j  350  (350 inclusive) 

 set "_bit_rate=349"
 if %%~j > %_bit_rate%   ∕∕ the same:  if %%~j > 349  (349 exclusive) 

 set "_bit_rate=350"
 if %%~j  %_bit_rate%   ∕∕ the same:  if %%~j  350  (350 inclusive) 


 if LSS - Less Than                if [integer or int(var)]  < [integer or int(var)]
 if GTR - Greater Than             if [integer or int(var)]  > [integer or int(var)]
 if LEQ - Less Than or Equals      if [integer or int(var)]   [integer or int(var)]
 if GEQ - Greater Than or Equals   if [integer or int(var)]   [integer or int(var)]

13.Результатifявляетсяtrueилиfalse, и будет выполнять действия в зависимости от случая, в дидактических целях мы будем рассматривать текущий файл какtrueслучай:

 if %%~j GTR 349 (
      case true
      ffmpeg transcode file mp4
    ) else (
      case false
      skip this file .mp4
      save the full path name 
    )
  •  if %%~j gtr 349 2>&1 ("!_ffmpeg!" -y -i "%%~f#" -hide_banner -v error -stats -c:v libx265 -crf 22 ^
       -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~n#.mkv"
  • Наблюд.:2Персонажи:space^, находятся в конце строки, прямо на переносе строки, где при выполнении интерпретатор команд будет рассматривать его как одну строку, избегая примененного переноса строки.

// Извините, объяснения продолжатся завтра...

Связанный контент