ffmpeg - CRF variable basado en Bitare

ffmpeg - CRF variable basado en Bitare

Utilizo ffmpeg para codificar algunos videos que descargué de varios sitios de transmisión en HEVC. En Windows utilizo un archivo por lotes para convertir todos estos archivos en un directorio.

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

La tasa de bits general de estos videos varía entre 300 kb/s y 1500 kb/s. En mis pruebas, el uso del mismo CRF para todos estos videos produjo un archivo de salida más grande en el caso de videos con alta tasa de bits o video de baja calidad en el caso de baja tasa de bits. Entonces cambio manualmente el CRF para un montón de videos con velocidad de bits similar. ¿Cómo puedo lograr esto usando un archivo por lotes? Por ejemplo, si la tasa de bits general es superior a 950 = crf 26 si la tasa de bits general está entre 750 y 949 = crf 24 si la tasa de bits general está entre 500 y 749 = crf 22 si la tasa de bits general es inferior a 499 = crf 18

Respuesta1

@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 )
  • El mecánico detrás fory 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

Obs.: 1Haydos espaciosentre^=^,^⟵⟶%%ien: delims^=^,^spacespace%%i

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


1.- Tu trabajo en casa: Reemplaza las variables a continuación de una manera compatible con tu escenario, también ve a tu carpeta 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.Este lote utiliza múltiples for loop, para que funcione deberá habilitarlo Deleyed Expansionpara que las variables reciban los valores actualizados/expandidos en tiempo de ejecución:

Setlocal EnableDelayedExpansion

3.Defina una variable delimitada por una coma, y ​​que contenga entre el delimitador, los valores a utilizar en el ifinterior del forbucle, de modo que pueda trabajar con valor máximo, valor mínimo y crf compatible:

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.Utilice un forbucle simple y uno para enumerar sus.mp4archivos y además, utilizar un contador (set /a "_c+=1+0")para obtener un total al final de la ejecución:

for %%# in (*.mp4)do echo; && set /a "_c+=1+0"
  • Observaciones: 2Elecho;se utiliza únicamente para romper la línea e intentar facilitar la visualización en la ejecución, creando una línea separadora en el bucle.

5.Utilice un adicional para hacer uso de esta variable de bucle (en ) donde obtuvo la ruta/nombre completo ( ) del archivo mp4, y pase este bucle como entrada a la definición que ya está definida (explicada enfor /f1st/for/var==%%#%%~f#ffprobeartículo 5.), los tokens y delimitadores que se tomarán en ese comando.

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

6.ElffprobeEl comando utilizado en el bucle es:for /f

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

7.Comenzando con la redirección StdErra StdOutla ffprobesalida a filtrar findstrusando el interruptor con el/End of a lineregexnúmeros ([0-9]) concatenado con la cadena .kb/sy usando el escape adecuado enforbucle:

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

8.El comando expandido anterior y sin los escapes da como resultado:

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

9.La salida del comando anterior tratada por el findstrfiltro da como resultado:

Duración: 00:01:00.08, inicio: -0.007000, tasa de bits: 350 kb/s

10.La salida del comando anterior tratada por el findstrfiltro da como resultado:

Duración: 00:01:00.08, inicio: -0.007000, tasa de bits: 350 kb/s

11.Al utilizar múltiples delimitadores, las cadenas en%%iy%%jla salida será00:01:00.08y350: es para la salida del último comando, será00:01:00.08y350:

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

ingrese la descripción de la imagen aquí

12.

Suponiendo que su valor límite es350(inclusivo) para Bite Rate, necesitarás usar alguna ifopción en la parte de trabajo:

 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.El resultado deifestrueofalse, y realizará acciones según el caso, a efectos didácticos, consideraremos el expediente actual como untruecaso:

 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"
  • Obs.:2Los caracteres:space^, están al final de la línea, justo en el salto de línea, donde durante la ejecución, el intérprete de comandos lo tratará como una sola línea, escapando del salto de línea aplicado.

// Lo siento, la explicación continuará mañana...

información relacionada