ffmpeg - 基於 Bitare 的可變 CRF

ffmpeg - 基於 Bitare 的可變 CRF

我使用 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 kb/s 到 1500 kb/s 之間變化。在我的測試中,對所有這些影片使用相同的 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 )
  • 背後的機械師forifs...
       %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.此批次使用 multiple for loop,為了使其工作,您需要啟用Deleyed Expansion以便變數在執行時接收更新/擴充的值:

Setlocal EnableDelayedExpansion

3.定義一個用逗號分隔的變量,並在分隔符號之間包含要在循環中使用它們的值iffor以便您可以使用最大值、最小值和相容的 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"
  • 觀察數:2echo;僅用於打破行並嘗試使視覺化更容易執行,在循環中創建分隔線。

5.使用附加項來利用此循環變數(在 中),您在其中獲得了 mp4 檔案的完整路徑/名稱 ( ),並將此循環作為輸入傳遞給已經定義的(已在for /f1st/for/var==%%#%%~f#ffprobe第 5 項。)、該指令中要採用的標記和分隔符號。

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

6.ffprobe循環中使用的命令是:for /f

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

7.首先使用具有以下命令的開關重定向StdErr到要過濾的StdOut輸出ffprobefindstr/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 kb/s

10.過濾器處理上述指令的輸出結果findstr為:

持續時間:00:01:00.08,開始:-0.007000,位元速率:350 kb/s

11.透過使用多個分隔符,中的字串%%i%%j輸出將是00:01:00.08350: 用於最後一個命令輸出,將是00:01:00.08350:

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

在此輸入影像描述

12.

假設你的極限值為350包括的)對於比特率,您需要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.的結果iftrue或者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^,位於行的末尾,就在換行符處,在執行時,命令解釋器會將其視為單行,轉義所應用的換行符。

// 抱歉,明天繼續解釋...

相關內容