@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 )
- The mechanic behind
for
and 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.: 1 There are two spaces between ^=^,^⟵⟶%%i in: delims^=^,^spacespace%%i
for %%# in (*.mp4)do for /f tokens^=2^,6^delims^=^,^spacespace%%i in (...
1. - You home work: Replace the variables below in a way compatible with your scenario, also go to your bat folder:
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. This batch is using multiple for loop
, for it to work you will need to enable Deleyed Expansion
so that the variables receive the updated/expanded values at run time:
Setlocal EnableDelayedExpansion
3. Define a variable delimited by a comma, and containing between the delimiter, the values to use them in the if
within the for
loop, so that you can work with maximum value, minimum value and compatible 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. Use a simple for
loop and one to list your .mp4
files and in addition, use a counter (set /a "_c+=1+0"
) to get a total at the end of the run:
for %%# in (*.mp4)do echo; && set /a "_c+=1+0"
- Obs: 2 The
echo;
is used only to break the line and try to make the visualization easier in execution, creating a separator line in the loop.
5. Use an additional for /f
to make use of this loop variable (in the 1st/for/var==%%#
) where you got the full path/name (%%~f#
) of the mp4 file, and pass this loop as input to ffprobe
already defining (explained on item 5.), the tokens and delimiters to be taken in that command.
for /f tokens^=2^,6^delims^=^,^ %%i in (ffmprobe ... %%~f# ...
6. The ffprobe
command used in for /f
loop is:
..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mp4"
7. Starting with redirecting StdErr
to StdOut
of the ffprobe
output to be filtered by findstr
by using the switch /End of a line
with the regex
numbers ([0-9]
) concatenated with the string .kb/s
and using proper scaping in for
loop:
2^>^&1 "!_ffprobe!" -show_entries stream^=bit_rate "%%~f#" ^| "%__APPDIR__%findstr.exe" /e [0-9].kb/s
8. The above expanded command and without the escapes, results in:
2>&1 ..\ffprobe.exe -show_entries stream=bit_rate "Google Chrome - Now Everywhere.mkv" | "%__APPDIR__%findstr.exe" /e [0-9].kb/s
9. The output of the above command treated by the findstr
filter results in:
Duration: 00:01:00.08, start: -0.007000, bitrate: 350 kb/s
10. The output of the above command treated by the findstr
filter results in:
Duration: 00:01:00.08, start: -0.007000, bitrate: 350 kb/s
11. By using multiple delimiters, the strings in %%i
and %%j
output will be 00:01:00.08
and 350
:
is for last command output, will be 00:01:00.08
and 350
:
... for /f tokens^=2^,6^delims^=^,^space %%i in (...
Duration: 00:01:00.08, start: -0.007000, bitrate: 350 kb/s
12.
Assuming your limit value is 350
(inclusive) for Bite Rate, you will need to use some if
option in the work part:
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. The result of if
is true
or false
, and will perform actions depending on the case, for didactic purposes, we will consider the current file as a true
case:
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.:2 The characters: space^, are at the end of the line, right at the line break, where in execution, the command interpreter will treat it as a single line, escaping the applied line break.
// Sorry, the explaining goes to continue tomorrow...