2025-04-18

以 ffmpeg 批次降低影片 bitrate

運動攝影機錄影擋預設流量 (bitrate) 很高,但其實我覺得看不太出來高低流量畫質的差異
所以根據網路查的一些建議用 ffmpeg 批次處理降低流量
先用 
ffprobe.exe 取得影片屬性,再根據影片屬性進行處理

以下 Powershell 中,VideoRotation 是影片方向的資訊,在降低流量的處理中實際上不需要
這裡只是當作筆記用,未來有需要的時候才找得到
 (找很久才找到這個語法)

#設定要降低的 bitrate 值 Start
$ProcessMethod = @();
$ProcessMethod += New-Object -TypeName PSObject -Property @{
     Width = 2688;
     FrameRate = 30;
     BitRate = 16;
};
$ProcessMethod += New-Object -TypeName PSObject -Property @{
     Width = 2688;
     FrameRate = 60;
     BitRate = 24;
};
$ProcessMethod += New-Object -TypeName PSObject -Property @{
     Width = 3840;
     FrameRate = 30;
     BitRate = 45;
};
$ProcessMethod += New-Object -TypeName PSObject -Property @{
     Width = 3840;
     FrameRate = 60;
     BitRate = 55;
};
$ProcessMethod += New-Object -TypeName PSObject -Property @{
     Width = 3840;
     FrameRate = 120;
     BitRate = 65;
};
#設定要降低的 bitrate 值End

write-host ('Start')
$VideoFiles = @();
$Files = Get-ChildItem -Path "D:\Video" -File -Recurse;
$FilesCount = $Files.Count;
write-host ('Got ' + $FilesCount + ' Files');
for ($i=0;$i -lt $FilesCount;$i++) {
     write-host ('Get Attributes of ' + $Files[$i].FullName);
     $VideoAttributes = & "D:\ffmpeg\bin\ffprobe.exe" -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,bit_rate,rotation -of default=noprint_wrappers=1:nokey=1 ('"' + $Files[$i].FullName + '"')
     #$VideoRotation = & "D:\ffmpeg\bin\ffprobe.exe" -v error -select_streams v:0 -show_entries stream_side_data=rotation -of default=noprint_wrappers=1:nokey=1 $Files[$i].FullName
     $VideoFiles += New-Object -TypeName PSObject -Property @{
          File = $Files[$i];
          Width = $VideoAttributes[0];
          Height = $VideoAttributes[1];
           #Rotation = $VideoRotation;
          FrameRate = [Math]::Round((Invoke-Expression $VideoAttributes[2]),0);
          BitRate = $VideoAttributes[3]/1000000;
     };
};

exit;

# Processing Order By File 按照檔案順序處理
     foreach ($ProcessFile in $VideoFiles) {
          $ProcessFile.File.Name
          $Hit = $False;
          foreach ($Method in $ProcessMethod) {
               if (($ProcessFile.Width -eq $Method.Width) -and ($ProcessFile.FrameRate -eq $Method.FrameRate) -and ($ProcessFile.BitRate -gt ($Method.BitRate + 1))) {
                    $Hit = $True;
                    break;
               };
          };
          if ($Hit -eq $True) {
               write-host ('Processing ' + $ProcessFile.File.FullName);
               ([String]$Method.Width + ' ' + [String]$Method.FrameRate + ' ' + [String]$Method.BitRate + '/' + [String]$ProcessFile.BitRate);
               & "D:\ffmpeg\bin\ffmpeg.exe" -i $ProcessFile.File.FullName -b:v ([String]$Method.BitRate + 'M') ($ProcessFile.File.FullName -Replace $ProcessFile.File.BaseName,($ProcessFile.File.BaseName + ' ' + $Method.BitRate + 'M'));
          };
     };

exit;

# Processing Order By Method 
按照解析度順序處理
     foreach ($Method in $ProcessMethod) {
          $ProcessFiles = ($VideoFiles | Where {($_.Width -eq $Method.Width) -and ($_.FrameRate -eq $Method.FrameRate) -and ($_.BitRate -gt ($Method.BitRate + 1))});
          foreach ($ProcessFile in $ProcessFiles) {
               write-host ('Processing ' + $ProcessFile.File.FullName);
               if ((Test-Path -Path ($ProcessFile.File.FullName -Replace $ProcessFile.File.BaseName,($ProcessFile.File.BaseName + ' ' + $Method.BitRate + 'M'))) -ne $True) {
                    & "D:\ffmpeg\bin\ffmpeg.exe" -i $ProcessFile.File.FullName -b:v ([String]$Method.BitRate + 'M') ($ProcessFile.File.FullName -Replace $ProcessFile.File.BaseName,($ProcessFile.File.BaseName + ' ' + $Method.BitRate + 'M'));
               };
          };
     };

exit;
處理過程中 ffmpeg 會將 CPU 吃滿
我開另一個 Powershell 執行以下 Script 檢查將 ffmpeg.exe 的 Priority 降低
避免影響其他程式運作 (Sleep 單位為秒,可以依需求自己改處理間隔時間)
Do {
$ffmpegProcess = (Get-CimInstance Win32_Process -Filter 'name = "ffmpeg.exe"')
foreach ($Process in $ffmpegProcess) {
$Process | select Name,Priority
$Process | Invoke-CimMethod -Name SetPriority -Arguments @{Priority=64}
};
Sleep 60
};

沒有留言:

張貼留言