Update ConvertTo-mkvh265-GPU.ps1

This commit is contained in:
2026-01-18 19:46:58 +00:00
parent 6d3ff47898
commit de91c5c55b
+160
View File
@@ -0,0 +1,160 @@
# ================= CONFIG =================
$SourcePath = ""
$LogPath = "C:\ffmpeg_encode.log"
$CQ = 24
$Preset = "slow"
$DryRun = $false
# =========================================
$videoExts = ".mp4",".mkv",".avi",".mov",".ts",".m2ts",".wmv",".flv",".webm"
if (!(Test-Path $LogPath)) {
New-Item -ItemType File -Path $LogPath | Out-Null
}
function Write-Log {
param ([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp - $Message" | Tee-Object -FilePath $LogPath -Append
}
function Format-Time {
param ([double]$Seconds)
if ($Seconds -lt 0) { return "00:00:00" }
[TimeSpan]::FromSeconds([math]::Round($Seconds)).ToString("hh\:mm\:ss")
}
Write-Log "==== FFmpeg H.265 batch encode started ===="
$files = Get-ChildItem $SourcePath -Recurse -File |
Where-Object { $_.Extension -in $videoExts }
$total = $files.Count
$counter = 0
$totalSaved = 0
# Stats
$encoded = 0
$remuxed = 0
$skipped = 0
$failed = 0
$encodeTimes = @()
foreach ($file in $files) {
$counter++
Write-Progress -Id 1 `
-Activity "Overall Progress" `
-Status "File $counter of $total"
$input = $file.FullName
$output = Join-Path $file.DirectoryName ($file.BaseName + ".mkv")
$tmp = Join-Path $file.DirectoryName ($file.BaseName + ".tmp.mkv")
$codec = & ffprobe -v error -select_streams v:0 `
-show_entries stream=codec_name `
-of default=noprint_wrappers=1:nokey=1 "$input"
# Skip H.265 MKV
if (($codec -eq "hevc") -and ($file.Extension -eq ".mkv")) {
Write-Progress -Id 2 -ParentId 1 `
-Activity "Current File" `
-Status "SKIPPED (H.265 MKV): $($file.Name)" `
-PercentComplete 100
Write-Log "SKIPPED: $input"
$skipped++
continue
}
if ($DryRun) {
Write-Log "DRY-RUN: $input -> $output"
continue
}
$origSize = (Get-Item $input).Length
$duration = & ffprobe -v error -show_entries format=duration `
-of default=noprint_wrappers=1:nokey=1 "$input"
$duration = [double]$duration
$startTime = Get-Date
$args = "-y -i `"$input`" -c:v hevc_nvenc -preset $Preset -rc vbr_hq -cq $CQ -c:a copy `"$tmp`" -progress pipe:1 -nostats"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = "ffmpeg"
$psi.Arguments = $args
$psi.RedirectStandardOutput = $true
$psi.UseShellExecute = $false
$psi.CreateNoWindow = $true
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $psi
$p.Start() | Out-Null
while (-not $p.HasExited) {
$line = $p.StandardOutput.ReadLine()
if ($line -match "^out_time_ms=(\d+)$") {
$doneSec = $matches[1] / 1000000
$percent = [math]::Min([math]::Round(($doneSec / $duration) * 100), 100)
$elapsed = (Get-Date) - $startTime
$rate = if ($doneSec -gt 0) { $elapsed.TotalSeconds / $doneSec } else { 0 }
$etaFile = ($duration - $doneSec) * $rate
$avgEncode = if ($encodeTimes.Count -gt 0) {
($encodeTimes | Measure-Object -Average).Average
} else { 0 }
$etaQueue = ($total - $counter) * $avgEncode
Write-Progress -Id 2 -ParentId 1 `
-Activity "Current File" `
-Status "Encoding: $($file.Name) ($percent%) | File ETA: $(Format-Time $etaFile) | Queue ETA: $(Format-Time $etaQueue)" `
-PercentComplete $percent
}
}
if (Test-Path $tmp) {
try {
Remove-Item $input -Force
Rename-Item $tmp $output -Force
$newSize = (Get-Item $output).Length
$saved = $origSize - $newSize
$totalSaved += $saved
$encodeTime = ((Get-Date) - $startTime).TotalSeconds
$encodeTimes += $encodeTime
$encoded++
Write-Log "ENCODED: $input | Saved $([math]::Round($saved/1MB,2)) MB"
}
catch {
Write-Log "FAILED TO REPLACE: $input"
$failed++
}
}
else {
Write-Log "FAILED: $input"
$failed++
}
}
Write-Progress -Id 2 -Completed
Write-Progress -Id 1 -Completed
$totalSavedMB = [math]::Round($totalSaved / 1MB, 2)
Write-Host ""
Write-Host "===== SUMMARY ====="
Write-Host "Total files : $total"
Write-Host "Encoded : $encoded"
Write-Host "Skipped : $skipped"
Write-Host "Failed : $failed"
Write-Host "Space saved : $totalSavedMB MB"
Write-Host "==================="
Write-Log "==== FFmpeg H.265 batch encode finished ===="