ffmpeg: omite el archivo si la tasa de bits es inferior a cierta cantidad

ffmpeg: omite el archivo si la tasa de bits es inferior a cierta cantidad

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 estos archivos.

FOR /F "tokens=*" %%G IN ('dir /b *.mp4') DO ffmpeg -n -i "%%G" -c:v libx265 -crf 22 -c:a libopus -b:a 48k -vbr on -compression_level 10 -frame_duration 60 -application audio "%%~nG.mkv"

Algunos de estos archivos tienen una tasa de bits muy baja y no quiero tocarlos. ¿Hay alguna forma en ffmpeg de omitir estos archivos? O cualquier comando que pueda incluir en el archivo por lotes, como usarlo ffprobepara obtener la tasa de bits y omitirlo usando el comando.

Respuesta1

@echo off 

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"

for %%# in (*.mp4)do 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 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" 
     )else set/a "_c+=1+0" && <con: call set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"
      
echo;& (for /f tokens^=2^delims^=^= %%i in ('set _skp_ 2^>nul')do echo\%%~i) & %__APPDIR__%timeout.exe -1 & endlocal
  • Producción:
x265 [info]: HEVC encoder version 3.4+2-73ca1d7be377
x265 [info]: build info [Windows][GCC 9.3.1][64 bit] 8bit+10bit
x265 [info]: using cpu capabilities: MMX2 SSE2Fast LZCNT SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
x265 [info]: Main profile, Level-3.1 (Main tier)
x265 [info]: Thread pool created using 4 threads
x265 [info]: Slices                              : 1
x265 [info]: frame threads / pool features       : 2 / wpp(12 rows)
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
x265 [info]: ME / range / subpel / merge         : hex / 57 / 2 / 3
x265 [info]: Keyframe min / max / scenecut / bias  : 23 / 250 / 40 / 5.00
x265 [info]: Lookahead / bframes / badapt        : 20 / 4 / 2
x265 [info]: b-pyramid / weightp / weightb       : 1 / 1 / 0
x265 [info]: References / ref-limit  cu / depth  : 3 / off / on
x265 [info]: AQ: mode / str / qg-size / cu-tree  : 2 / 1.0 / 32 / 1
x265 [info]: Rate Control / qCompress            : CRF-22.0 / 0.60
x265 [info]: tools: rd=3 psy-rd=2.00 early-skip rskip mode=1 signhide tmvp
x265 [info]: tools: b-intra strong-intra-smoothing lslices=4 deblock sao
frame= 1440 fps= 55 q=29.8 Lsize=    2570kB time=00:01:00.11 bitrate= 350.3kbits/s speed=2.32x
x265 [info]: frame I:      6, Avg QP:22.93  kb/s: 1138.86
x265 [info]: frame P:    705, Avg QP:25.55  kb/s: 498.87
x265 [info]: frame B:    729, Avg QP:28.95  kb/s: 98.52
x265 [info]: Weighted P-Frames: Y:0.9% UV:0.6%
x265 [info]: consecutive B-frames: 58.8% 11.0% 11.4% 6.6% 12.2%

encoded 1440 frames in 25.96s (55.47 fps), 298.86 kb/s, Avg QP:27.26

Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
Skipped File: HVDC Light - ABB 3D.mp4 Duration: 00:03:32.16 Bit Rate: 336

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.Desafortunadamente tu actualfor /f ... dir .mp4 ...no ayuda mucho, así que reemplácelo con un simple forpara obtener todos los.mp4listado en un bucle:

for %%# in (*.mp4)do ....

4.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# ... 

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

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

6.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

7.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

8.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

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.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í

11.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)]

12.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.

13.Para aquellos archivos con tasas de mordida más bajas, es decir,falsecasos en elifcomando, tiene las acciones para guardar los archivos que fueron excluidos delffmpegconversión, y aparecerá al final de la ejecución:

 if %%~j GTR 349 (
      case true
      ffmpeg transcode file mp4
    ) else (
      case false
      skip this file .mp4
      save the full path name
    )
  • Obs.:3ElifTambién funciona en diferentes diseños como:

    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 (case true && ffmpeg transcode file mp4 ) else (
        case false && skip this file .mp4 && save the full path name )
    if %%~j GTR 349 (case true && ffmpeg transcode file mp4
        )else case false && skip this file .mp4 && save the full path name 

14.Usando los valores en el%%~f#,%%~iy%%~jvariables, donde respectivamente son la ruta y el nombre completo del archivo actual, su duración y su tasa de bits, podemos agregar fácilmente un contador ( set/a "_c+=1+0") y en el tiempo de ejecución incrementamos para crear/definir, uno por uno, la información de los archivos excluidos de la conversión:

)else set/a "_c+=1+0" && <con: call set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"

%%~f# == Live_TV_-_Bloomberg.mp4
%%~i  == 00:00:36.42
%%~j  == 315

set "_c+=1+0" && call set "_skp_1=Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315"

15.El comando set también se puede usar para listados de variables y valores, y usar unset user, todas las variables con definiciónuser+(strings)se enumerará así:

>set USER
USERDOMAIN=LAME_SLUG
USERDOMAIN_ROAMINGPROFILE=LAME_SLUG
USERNAME=ecker
USERPROFILE=C:\Users\ecker

dieciséis.En la última línea, donde tenemos unfor /fbucle, se utilizará para hacer eco de cada variable definida con nombre_skip_*, que se definió guardando los archivos que fueron ignorados durante la ejecución, y este bucle tomará todo lo que venga después del signo de=(2do/tokens^=2):

for /f tokens^=2^delims^=^= ... set _skp_1 .... echo\%%~i
 _skp_1=Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
       
tokens^=2Skipped File: Live_TV_-_Bloomberg.mp4 Duration: 00:00:36.42 Bit Rate: 315
echo;& (for /f tokens^=2^delims^=^= %%i in ('set _skp_')do echo\%%~i)...

17.La segunda y última parte de la última en el archivo bat, permitirá que el bucle ocurra (aislado) y solo después de enumerar todos los archivos que se omitieron, se pausará/tiempo de espera indefinido, esperando que se presione alguna tecla, cerrando así/ finalizando el setlocal y finalizando la ejecución:

1st part: (for /f .....)
2nd part: %__APPDIR__%timeout.exe -1 & endlocal 

echo; & (for /f tokens^=2^delims^=^= %%i in ('set _skp_')do echo\%%~i) & %__APPDIR__%timeout.exe -1 & endlocal

18.Para evitar cualquier posible mensaje de error (Environment variable _skip_ not defined), en los casos en los que ningun archivo fue ignorado por if, simplemente agregue2^>nulen'set _skip_*2^>nul', dentro del último buclefor:

(for /f tokens^=2^delims^=^= %%i in ('set _skp_ 2^>nul')do echo\%%~i)do...
  • Obs.4Aquí elecho;es solo para crear una línea separatista antes de enumerar los archivos omitidos.


  • El mismo código en formato convencional/didáctico:
@echo off 

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"

for %%# in (*.mp4) do (

     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 (
         
         if %%~j gtr 3200 (
         
             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" 
             
           ) else (
             
             set /a "_c+=1+0"
             set "_skp_!_c!=Skipped File: %%~nx# Duration: %%~i Bit Rate: %%~j"
                 
           )
      )
    
  )

echo.
for /f "tokens=2 delims==" %%i in ('2^>nul set _skp_')do echo\%%~i

%__APPDIR__%timeout.exe -1 
endlocal

información relacionada