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
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).
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.
.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.
@@ -47,17 +48,60 @@ if (-not (Test-Path -LiteralPath $sourcePath)) {
$sourceExt = [System.IO.Path]::GetExtension($sourcePath)
$sourceBase = [System.IO.Path]::GetFileNameWithoutExtension($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 }
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$cloneVideoScript = Join-Path $scriptDir 'Clone-Video.ps1'
# Forward extra args plus common parameters to Clone-Video.ps1
$passThrough = @()
if ($ExtraArgs) { $passThrough += $ExtraArgs }
if ($PSBoundParameters.ContainsKey('WhatIf')) { $passThrough += '-WhatIf' }
if ($PSBoundParameters.ContainsKey('Confirm')) { $passThrough += '-Confirm' }
# Forward extra args plus common parameters to Clone-Video.ps1.
# The remaining arguments are turned into a hashtable and splatted by name: PowerShell
# passes the elements of a splatted *array* as positional arguments, so forwarding
# @('-Size', '720p') that way would bind '-Size' to Clone-Video.ps1's [int]$StartFrame
# 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