Add .skip marker preservation to Create-Clip.ps1 by detecting and extracting '.skip' suffix from source basename before inserting "-Clip" so marker stays immediately before container extension (e.g. P01.skip.mp4 -> P01-Clip.skip.mp4), and refactor extra parameter forwarding from array to hashtable splatting to pass arguments by name instead of position, parsing -Name value pairs and standalone switches while validating parameter syntax, preventing positional binding issues like '-Size 720p' being interpreted as positional

This commit is contained in:
guru committed 2026-10-26 22:32:28 -04:00
1 parent 45f1396769
commit c8c5a5d75c
1 file changed
+51 -7
+51 -7
View File
@@ -2,6 +2,7 @@
.SYNOPSIS .SYNOPSIS
Creates a new clipped video file using Clone-Video.ps1, requiring the -Source and -Frames parameters from that script. Creates a new clipped video file using Clone-Video.ps1, requiring the -Source and -Frames parameters from that script.
The filename used for the -Target parameter is automatically derived from the -Source filename, with "-Clip" inserted before the video file extension (e.g., P01.mp4 becomes P01-Clip.mp4). The filename used for the -Target parameter is automatically derived from the -Source filename, with "-Clip" inserted before the video file extension (e.g., P01.mp4 becomes P01-Clip.mp4).
When the source name carries a '.skip' marker before its extension, "-Clip" is inserted before that marker so it stays last (e.g., P01.skip.mp4 becomes P01-Clip.skip.mp4).
Any extra parameters will be pass directly to Clone-Video.ps1, except for parameters -Source, -Frames and -Target. Any extra parameters will be pass directly to Clone-Video.ps1, except for parameters -Source, -Frames and -Target.
.PARAMETER Source .PARAMETER Source
Path to the input video file. Can be absolute or relative to current directory. If the path has no extension, .mp4, .webm and .mkv are tried in turn. Path to the input video file. Can be absolute or relative to current directory. If the path has no extension, .mp4, .webm and .mkv are tried in turn.
@@ -47,17 +48,60 @@ if (-not (Test-Path -LiteralPath $sourcePath)) {
$sourceExt = [System.IO.Path]::GetExtension($sourcePath) $sourceExt = [System.IO.Path]::GetExtension($sourcePath)
$sourceBase = [System.IO.Path]::GetFileNameWithoutExtension($sourcePath) $sourceBase = [System.IO.Path]::GetFileNameWithoutExtension($sourcePath)
$sourceDir = [System.IO.Path]::GetDirectoryName($sourcePath) $sourceDir = [System.IO.Path]::GetDirectoryName($sourcePath)
$targetName = "$sourceBase-Clip$sourceExt"
# A '.skip' marker must stay immediately before the container extension, so "-Clip" is
# inserted before it rather than after (e.g., P01.skip.mp4 -> P01-Clip.skip.mp4).
# The marker's original casing is preserved.
$skipMarker = ''
if ($sourceBase -match '^(.*)(\.skip)$') {
$sourceBase = $Matches[1]
$skipMarker = $Matches[2]
}
$targetName = "$sourceBase-Clip$skipMarker$sourceExt"
$targetPath = if ([string]::IsNullOrEmpty($sourceDir)) { $targetName } else { Join-Path $sourceDir $targetName } $targetPath = if ([string]::IsNullOrEmpty($sourceDir)) { $targetName } else { Join-Path $sourceDir $targetName }
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$cloneVideoScript = Join-Path $scriptDir 'Clone-Video.ps1' $cloneVideoScript = Join-Path $scriptDir 'Clone-Video.ps1'
# Forward extra args plus common parameters to Clone-Video.ps1 # Forward extra args plus common parameters to Clone-Video.ps1.
$passThrough = @() # The remaining arguments are turned into a hashtable and splatted by name: PowerShell
if ($ExtraArgs) { $passThrough += $ExtraArgs } # passes the elements of a splatted *array* as positional arguments, so forwarding
if ($PSBoundParameters.ContainsKey('WhatIf')) { $passThrough += '-WhatIf' } # @('-Size', '720p') that way would bind '-Size' to Clone-Video.ps1's [int]$StartFrame
if ($PSBoundParameters.ContainsKey('Confirm')) { $passThrough += '-Confirm' } # instead of naming its -Size parameter.
# Assigned in two steps: an empty array returned from an if-statement block is enumerated
# away by PowerShell, which would leave $extra as $null.
$extra = @()
if ($ExtraArgs) { $extra = @($ExtraArgs) }
& $cloneVideoScript -Source $sourcePath -Frames $Frames -Target $targetPath @passThrough $forwarded = @{}
$index = 0
while ($index -lt $extra.Count) {
$token = [string]$extra[$index]
if ($token -notmatch '^-{1,2}([A-Za-z]\w*)$') {
Write-Error ("Unexpected argument '{0}'. Extra parameters must be passed by name (e.g. -Size 720p)." -f $token)
exit 1
}
$name = $Matches[1]
$next = if (($index + 1) -lt $extra.Count) { [string]$extra[$index + 1] } else { $null }
# The next token is this parameter's value unless it is itself a parameter name.
# A '-' followed by a digit is a value, not a name (e.g. -CRF -1).
if ($null -ne $next -and (($next -notmatch '^-{1,2}[A-Za-z]') -or ($next -match '^-\d'))) {
$forwarded[$name] = $extra[$index + 1]
$index += 2
}
else {
# No value follows, so this is a switch (e.g. -NoAudio, -Reverse, -LTX).
$forwarded[$name] = $true
$index++
}
}
if ($PSBoundParameters.ContainsKey('WhatIf')) { $forwarded['WhatIf'] = [bool]$PSBoundParameters['WhatIf'] }
if ($PSBoundParameters.ContainsKey('Confirm')) { $forwarded['Confirm'] = [bool]$PSBoundParameters['Confirm'] }
& $cloneVideoScript -Source $sourcePath -Frames $Frames -Target $targetPath @forwarded
exit $LASTEXITCODE exit $LASTEXITCODE