Add -Upscale parameter to Clone-Image.ps1 for AI upscaling with upscayl-bin before ffmpeg processing, add -Model and -Keep parameters for model selection and output preservation, and update Stich-InBetween.ps1 to use RIFE_HOME and NCNN_GPU_ID environment variables for TNTwise fork compatibility
This commit is contained in:
+169
-1
@@ -27,6 +27,23 @@
|
||||
(0-6, higher means smaller files but slower encoding). Ignored for jpeg, avif, bmp and tiff.
|
||||
.PARAMETER Metadata
|
||||
When present, copies available metadata from the source image file to the target image file.
|
||||
.PARAMETER Upscale
|
||||
Optional upscaling factor (2, 3 or 4) applied to the source image with upscayl-bin.exe
|
||||
before ffmpeg runs. The upscaled image is written to a Windows temp PNG and used as the
|
||||
ffmpeg input, so any -Size / -LTX cover-scale-then-crop is applied to the upscaled image.
|
||||
Requires upscayl-bin.exe in PATH, the UPSCAYL_HOME environment variable pointing to the
|
||||
upscayl-bin install directory, and the NCNN_GPU_ID environment variable set to the desired
|
||||
GPU device ID (-1 for CPU, 0/1/2/... for GPU).
|
||||
.PARAMETER Model
|
||||
Upscayl model name (without extension) to use when -Upscale is specified. Defaults to
|
||||
'4xNomos8kSC'. The model files (<Model>.bin and <Model>.param) must exist under
|
||||
%UPSCAYL_HOME%\models. Ignored when -Upscale is not specified.
|
||||
.PARAMETER Keep
|
||||
Optional path to save a copy of the upscayl-bin output (i.e. the upscaled image, before
|
||||
ffmpeg's cover-scale-then-crop). The file extension determines the format; if it differs
|
||||
from .png (the upscayl output format) the temp PNG is converted with ffmpeg using the
|
||||
appropriate per-format encoder. If the extension is missing or unrecognised, .png is
|
||||
appended. Only valid when -Upscale is specified.
|
||||
.PARAMETER LTX
|
||||
When present, overrides the dimensions selected by -Size with the closest LTX-2 (Wan2GP by DeepBeepMeep)
|
||||
canonical resolution for the source's aspect ratio. Only valid when -Size is one of HD, 1080p, 720p or 480p.
|
||||
@@ -61,7 +78,17 @@ param(
|
||||
[switch]$Metadata,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$LTX
|
||||
[switch]$LTX,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet(0, 2, 3, 4)]
|
||||
[int]$Upscale = 0,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$Model = '4xNomos8kSC',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$Keep = $null
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
@@ -259,6 +286,142 @@ switch ($targetFormat) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Optional upscayl-bin upscaling step (runs before ffmpeg). ---
|
||||
# When -Upscale is given (2/3/4) the source image is upscaled with upscayl-bin
|
||||
# into a temp PNG; that temp PNG then becomes the ffmpeg input so any -Size /
|
||||
# -LTX cover-scale-then-crop is applied to the already-upscaled image.
|
||||
$upscaledTempPath = $null
|
||||
if ($Upscale -gt 0) {
|
||||
$upscaylExe = Get-Command -Name 'upscayl-bin.exe' -ErrorAction SilentlyContinue
|
||||
if (-not $upscaylExe) {
|
||||
Write-Error 'upscayl-bin.exe not found in PATH. Install upscayl-bin and add it to the system PATH (see mkdocs/Upscalers.md).'
|
||||
exit 1
|
||||
}
|
||||
$upscaylExePath = $upscaylExe.Source
|
||||
|
||||
$upscaylHome = $env:UPSCAYL_HOME
|
||||
if (-not $upscaylHome) {
|
||||
Write-Error 'UPSCAYL_HOME environment variable is not set. Set it to the upscayl-bin install directory.'
|
||||
exit 1
|
||||
}
|
||||
$upscaylHome = $upscaylHome.TrimEnd('\', '/')
|
||||
if (-not (Test-Path -LiteralPath $upscaylHome -PathType Container)) {
|
||||
Write-Error ('UPSCAYL_HOME directory does not exist: {0}' -f $upscaylHome)
|
||||
exit 1
|
||||
}
|
||||
|
||||
$modelsDir = Join-Path $upscaylHome 'models'
|
||||
if (-not (Test-Path -LiteralPath $modelsDir -PathType Container)) {
|
||||
Write-Error ('Upscayl models directory not found: {0}' -f $modelsDir)
|
||||
exit 1
|
||||
}
|
||||
$modelBin = Join-Path $modelsDir ('{0}.bin' -f $Model)
|
||||
$modelParam = Join-Path $modelsDir ('{0}.param' -f $Model)
|
||||
if (-not (Test-Path -LiteralPath $modelBin -PathType Leaf) -or -not (Test-Path -LiteralPath $modelParam -PathType Leaf)) {
|
||||
Write-Error ('Upscayl model files not found for model ''{0}'' under {1} (expected {0}.bin and {0}.param).' -f $Model, $modelsDir)
|
||||
exit 1
|
||||
}
|
||||
|
||||
$gpuId = $env:NCNN_GPU_ID
|
||||
if (-not $gpuId) {
|
||||
Write-Error 'NCNN_GPU_ID environment variable is not set. Set it to -1 (CPU) or 0/1/2/... (GPU device index).'
|
||||
exit 1
|
||||
}
|
||||
if ($gpuId -notmatch '^-?\d+$') {
|
||||
Write-Error ('NCNN_GPU_ID must be an integer (-1 for CPU, 0+ for GPU). Current value: {0}' -f $gpuId)
|
||||
exit 1
|
||||
}
|
||||
|
||||
$upscaledTempPath = Join-Path ([System.IO.Path]::GetTempPath()) (('upscayl-{0}.png') -f ([System.Guid]::NewGuid().ToString()))
|
||||
|
||||
Write-Host ('Upscaling source with upscayl-bin (x{0}, model={1}, gpu={2})...' -f $Upscale, $Model, $gpuId)
|
||||
Write-Host (' Upscayl temp file: {0}' -f $upscaledTempPath)
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($SourcePath, ('Upscale x{0} with upscayl-bin into temp file' -f $Upscale))) {
|
||||
$upscaylOutput = & $upscaylExePath -i $SourcePath -o $upscaledTempPath -s $Upscale.ToString() -n $Model -m $modelsDir -g $gpuId 2>&1
|
||||
$upscaylExit = $LASTEXITCODE
|
||||
if ($upscaylExit -ne 0) {
|
||||
Write-Host 'upscayl-bin error output:' -ForegroundColor Red
|
||||
$upscaylOutput | ForEach-Object { Write-Host $_ }
|
||||
Write-Error ('upscayl-bin failed with exit code: {0}' -f $upscaylExit)
|
||||
if (Test-Path -LiteralPath $upscaledTempPath) { Remove-Item -LiteralPath $upscaledTempPath -Force -ErrorAction SilentlyContinue }
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Switch ffmpeg's input to the upscaled image.
|
||||
$SourcePath = $upscaledTempPath
|
||||
|
||||
# Refresh informational source dimensions from the upscaled file.
|
||||
$ffprobeDimOutput2 = & ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0:s=x -- $SourcePath 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$dimLine2 = $ffprobeDimOutput2 | Select-Object -First 1
|
||||
if ($dimLine2) {
|
||||
$sourceDimensions = ([string]$dimLine2).Trim() + (' (upscaled x{0})' -f $Upscale)
|
||||
}
|
||||
}
|
||||
|
||||
# --- Optional -Keep: save a copy of the upscaled image. ---
|
||||
if (-not [string]::IsNullOrWhiteSpace($Keep)) {
|
||||
$KeepPath = $Keep
|
||||
$keepExt = [System.IO.Path]::GetExtension($KeepPath).ToLowerInvariant()
|
||||
if ($supportedTargetExts -notcontains $keepExt) {
|
||||
$KeepPath += '.png'
|
||||
$keepExt = '.png'
|
||||
}
|
||||
$KeepDir = Split-Path -Parent $KeepPath
|
||||
if ($KeepDir -and -not (Test-Path -LiteralPath $KeepDir)) {
|
||||
Write-Error ('Keep target directory does not exist: {0}' -f $KeepDir)
|
||||
if (Test-Path -LiteralPath $upscaledTempPath) { Remove-Item -LiteralPath $upscaledTempPath -Force -ErrorAction SilentlyContinue }
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($keepExt -eq '.png') {
|
||||
# Upscayl already wrote a PNG; just copy.
|
||||
if ($PSCmdlet.ShouldProcess($KeepPath, 'Copy upscaled image (PNG)')) {
|
||||
Copy-Item -LiteralPath $upscaledTempPath -Destination $KeepPath -Force
|
||||
Write-Host ('Upscaled image saved to: {0}' -f $KeepPath)
|
||||
}
|
||||
} else {
|
||||
# Convert PNG -> requested format with ffmpeg, using sane defaults.
|
||||
switch ($keepExt) {
|
||||
'.jpg' { $keepFormat = 'jpeg' }
|
||||
'.jpeg' { $keepFormat = 'jpeg' }
|
||||
'.tif' { $keepFormat = 'tiff' }
|
||||
'.tiff' { $keepFormat = 'tiff' }
|
||||
default { $keepFormat = $keepExt.TrimStart('.') }
|
||||
}
|
||||
$keepEncoderArgs = @()
|
||||
switch ($keepFormat) {
|
||||
'jpeg' { $keepEncoderArgs += @('-c:v', 'mjpeg', '-pix_fmt', 'yuvj420p', '-q:v', '2') }
|
||||
'webp' { $keepEncoderArgs += @('-c:v', 'libwebp', '-quality', '90') }
|
||||
'avif' { $keepEncoderArgs += @('-c:v', 'libaom-av1', '-still-picture', '1', '-cpu-used', '4', '-crf', '25') }
|
||||
'bmp' { $keepEncoderArgs += @('-c:v', 'bmp') }
|
||||
'tiff' { $keepEncoderArgs += @('-c:v', 'tiff') }
|
||||
'png' { $keepEncoderArgs += @('-c:v', 'png') }
|
||||
}
|
||||
Write-Host ('Converting upscaled image to {0}: {1}' -f $keepFormat, $KeepPath)
|
||||
if ($PSCmdlet.ShouldProcess($KeepPath, ('Save upscaled image as {0}' -f $keepFormat))) {
|
||||
$keepFfmpegArgs = @('-y', '-i', $upscaledTempPath) + $keepEncoderArgs + @('-frames:v', '1', '-map_metadata', '-1', '--', $KeepPath)
|
||||
$keepFfmpegOutput = & ffmpeg @keepFfmpegArgs 2>&1
|
||||
$keepFfmpegExit = $LASTEXITCODE
|
||||
if ($keepFfmpegExit -ne 0) {
|
||||
Write-Host 'ffmpeg error output (Keep step):' -ForegroundColor Red
|
||||
$keepFfmpegOutput | ForEach-Object { Write-Host $_ }
|
||||
Write-Error ('ffmpeg failed to save upscaled image (-Keep) with exit code: {0}' -f $keepFfmpegExit)
|
||||
if (Test-Path -LiteralPath $upscaledTempPath) { Remove-Item -LiteralPath $upscaledTempPath -Force -ErrorAction SilentlyContinue }
|
||||
exit 1
|
||||
}
|
||||
Write-Host ('Upscaled image saved to: {0}' -f $KeepPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($Keep) -and $Upscale -le 0) {
|
||||
Write-Warning '-Keep was specified without -Upscale; ignoring (nothing to save).'
|
||||
}
|
||||
|
||||
Write-Host ('Cloning image: {0}' -f $SourcePath)
|
||||
Write-Host (' Target format: {0}' -f $targetFormat)
|
||||
if ($sourceDimensions) {
|
||||
@@ -316,3 +479,8 @@ if ($PSCmdlet.ShouldProcess($TargetPath, 'Clone image file')) {
|
||||
|
||||
Write-Host ('Image cloned successfully to: {0}' -f $TargetPath)
|
||||
}
|
||||
|
||||
# --- Clean up the upscayl temp file (if any). ---
|
||||
if ($upscaledTempPath -and (Test-Path -LiteralPath $upscaledTempPath)) {
|
||||
Remove-Item -LiteralPath $upscaledTempPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user