Created
January 3, 2023 00:52
-
-
Save Delivator/08e3f85cf33eda7c0dc91db436de857c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Param( | |
[Parameter(Mandatory=$True)] | |
[string]$Path, | |
[string]$Quality = "36", | |
[string]$Preset = "p4", | |
[string]$Tune = "hq", | |
[string]$Format = "webm", | |
[bool]$CopyAudio = $False, | |
[switch]$Keep | |
) | |
# Write-Progress style | |
$PSStyle.Progress.MaxWidth = 240 | |
$InFile = Get-ChildItem $Path | |
$OutFile = "$($InFile.DirectoryName)\$($InFile.BaseName).$Format" | |
# $OutFile = "$($InFile.BaseName).$Format" | |
Write-Host $InFile $OutFile | |
$TempFile = "$env:TEMP/ffmpeg-output.txt" | |
$TotalFrames = ffprobe.exe "-v" "error" "-select_streams" "v:0" "-count_packets" "-show_entries" "stream=nb_read_packets" "-of" "csv=p=0" $InFile | |
$CurrentFrame = -1 | |
$FfmpegArgs = @( | |
# "-v", "error" # Only log errors | |
"-y", # Overwrite if already existing | |
"-hwaccel_output_format", "cuda", | |
"-c:v", "h264_cuvid", # Use nvidia h264 decoder | |
"-i", "`"$InFile`"", # Input file | |
"-fps_mode", "passthrough", | |
"-map", "0:v", "-map", "0:a", # Map video and audio tracks | |
"-map", "0:s?", # Map subtitle track | |
"-c:v", "av1_nvenc", # Use nvidia av1 encoder | |
"-cq", "$Quality", "-preset", "$Preset", "-tune", "$Tune", # Nvenc av1 qualit and bitrate settings | |
"-c:s", "copy" # Don't re-encode subtitle tracks, copy codec | |
) | |
if ($CopyAudio) { | |
$Format = "mkv" | |
$FfmpegArgs.Add("-c:a","copy") | |
} | |
$FfmpegArgs += "`"$OutFile`"" | |
# Get current frame from ffmpeg stdout/stderr file | |
function Get-Frame { | |
if (-not(Test-Path -Path $TempFile -PathType Leaf)) { | |
try { | |
$null = New-Item -ItemType File -Path $TempFile -Force -ErrorAction Stop | |
} | |
catch { | |
throw $_.Exception.Message | |
} | |
} | |
$HasFrame = Select-String -Path $TempFile -Pattern "(frame=\s*)(\d*)" -Quiet | |
if (-Not $HasFrame) { | |
Return -1 | |
} | |
$Match = Select-String -Path $TempFile -Pattern "(frame=\s*)(\d*)" | |
Return [int]$Match.Matches[-1].Groups[2].Value | |
} | |
Write-Host -NoNewline "Transcoding... " | |
Start-Process -FilePath "ffmpeg.exe" -NoNewWindow -ArgumentList $FfmpegArgs -RedirectStandardError $TempFile | Out-Null | |
$StartTime = $(get-date) | |
# Get current frame from ffmpeg stdout/stderr file | |
while ($CurrentFrame -lt $TotalFrames) { | |
# $elapsedTime = $(get-date) - $StartTime | |
$elapsed = (Get-Date) - $StartTime | |
$NewCurrentFrame = Get-Frame | |
if ($CurrentFrame -eq $NewCurrentFrame) { | |
Continue | |
} | |
$Percent = [Math]::Round((($CurrentFrame/$TotalFrames) * 100.0), 2) | |
if ($Percent -le 0) { | |
$eta = 0 | |
} else { | |
$elapsed = (Get-Date) - $StartTime | |
$totalTime = ($elapsed.TotalSeconds) / ($Percent / 100.0) | |
$remain = $totalTime - $elapsed.TotalSeconds | |
$eta = "$([Math]::Floor($remain)) Seconds remaining" | |
} | |
$CurrentFrame = Get-Frame | |
Write-Progress -Activity "Processing video" -Status "Frame $CurrentFrame/$TotalFrames ($Percent%) ETA $eta" -PercentComplete $Percent | |
Start-Sleep -Milliseconds 100 | |
} | |
# Clean up temp file | |
Remove-Item $TempFile | |
Write-Host "Done" | |
Compare-Size -Original $InFile -Compare $OutFile | |
# Prompt user if the original file should be removed | |
$reply = $Keep ? "n" : (Read-Host -Prompt "Remove original file? [y/N]") | |
if ( $reply -eq 'y' ) { | |
Remove-Item $InFile | |
Write-Host "Original file removed" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment