Skip to content

Instantly share code, notes, and snippets.

@Delivator
Created January 3, 2023 00:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Delivator/08e3f85cf33eda7c0dc91db436de857c to your computer and use it in GitHub Desktop.
Save Delivator/08e3f85cf33eda7c0dc91db436de857c to your computer and use it in GitHub Desktop.
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