Fix -Frames negative range calculation to extract last N frames correctly (off-by-one error), add validation to reject invalid '-%' and '-0' formats with exit code 1, change '%' alone to extract single last frame instead of range, remove duplicate last frame from PNG sequence concat list, update Get-LastFrame.ps1 and Get-Frame.ps1 to clamp out-of-range frame indices instead of erroring and improve error messages with inline stderr output, add -y flag and -- separator to ffprobe calls, replace deprecated

This commit is contained in:
guru committed 2026-11-02 06:30:38 -05:00
1 parent cf41fb0ce5
commit 1227c6e153
13 files changed
+100 -86

No files matched your search

+13 -6
View File
@@ -36,7 +36,7 @@
- start-end: Extract frames from start to end (e.g., "100-200")
- positive_number: Extract frames from 0 to that number (e.g., "50")
- -negative_number: Extract last N frames (e.g., "-10")
- %: Represents the last frame index. Can be used alone or in ranges (e.g., "%", "10-%", "-%")
- %: Represents the last frame index. Can be used alone or in ranges (e.g., "%", "10-%")
- all: Extract all frames (same as "0-%")
.PARAMETER Sequence
Path to PNG file for extracted frame. Can be absolute or relative to current directory. .png extension is added if not provided. If EndFrame is -1, extracts the last frame and excludes it from the cloned video. If EndFrame is not -1, extracts the frame at EndFrame index and excludes it from the cloned video.
@@ -228,6 +228,14 @@ if (-not [string]::IsNullOrWhiteSpace($Frames)) {
Write-Error '-Frames cannot be used together with -StartFrame, -EndFrame, or -Sequence'
exit 1
}
if ($Frames -match '^-.*%') {
Write-Error "Invalid Frames format '$Frames': '-%' is not supported. Use '%' for the last frame, or -N for the last N frames."
exit 1
}
if ($Frames -match '^-0+$') {
Write-Error "Invalid Frames format '$Frames': a negative count must be at least 1. Use -1 for the last frame."
exit 1
}
}
$AudioPath = $null
@@ -478,13 +486,13 @@ if (Test-Path -LiteralPath $SourcePath -PathType Container) {
$maxPngIndex = $pngFiles.Count - 1
if (-not [string]::IsNullOrWhiteSpace($Frames)) {
$framesPattern = $Frames -replace '%', $maxPngIndex
$framesPattern = if ($Frames -eq '%') { "$maxPngIndex-$maxPngIndex" } else { $Frames -replace '%', $maxPngIndex }
if ($framesPattern -ieq 'all') { $framesPattern = "0-$maxPngIndex" }
if ($framesPattern -match '^(\d+)-(\d+)$') {
$StartFrame = [int]$Matches[1]
$EndFrame = [int]$Matches[2]
} elseif ($framesPattern -match '^-(\d+)$') {
$StartFrame = [Math]::Max(0, $maxPngIndex - [int]$Matches[1])
$StartFrame = [Math]::Max(0, $maxPngIndex - [int]$Matches[1] + 1)
$EndFrame = $maxPngIndex
} elseif ($framesPattern -match '^\d+$') {
$StartFrame = 0
@@ -601,7 +609,6 @@ if (Test-Path -LiteralPath $SourcePath -PathType Container) {
$concatLines += "file '$pfPath'"
$concatLines += "duration $frameDuration"
}
$concatLines += "file '$($pngFiles[-1].FullName.Replace('\', '/'))'"
[System.IO.File]::WriteAllLines($concatTempFile, $concatLines, [System.Text.UTF8Encoding]::new($false))
$seqFfmpegArgs = @(
@@ -718,13 +725,13 @@ $totalFramesInt = [int]$totalFrames
$maxFrameIndex = $totalFramesInt - 1
if (-not [string]::IsNullOrWhiteSpace($Frames)) {
$framesPattern = $Frames -replace '%', $maxFrameIndex
$framesPattern = if ($Frames -eq '%') { "$maxFrameIndex-$maxFrameIndex" } else { $Frames -replace '%', $maxFrameIndex }
if ($framesPattern -ieq 'all') { $framesPattern = "0-$maxFrameIndex" }
if ($framesPattern -match '^(\d+)-(\d+)$') {
$StartFrame = [int]$Matches[1]
$EndFrame = [int]$Matches[2]
} elseif ($framesPattern -match '^-(\d+)$') {
$StartFrame = [Math]::Max(0, $maxFrameIndex - [int]$Matches[1])
$StartFrame = [Math]::Max(0, $maxFrameIndex - [int]$Matches[1] + 1)
$EndFrame = $maxFrameIndex
} elseif ($framesPattern -match '^\d+$') {
$StartFrame = 0