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:
1 parent
cf41fb0ce5
commit
1227c6e153
13 files changed
+100
-86
No files matched your search
+11
-15
@@ -1,13 +1,14 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Extracts a specific frame of a video file to a PNG image using Get-LastFrame.ps1, requiring -Video and -Frame parameters from that script.
|
||||
Extracts a specific frame of a video file to a PNG image. The extraction is done by Get-LastFrame.ps1, which this script calls with an image path derived from -Video and -Frame.
|
||||
The image filename used for the -Image parameter is automatically derived from the -Video filename, with a "-" followed by the "-Frame" value padded with zeros (at least 4 digits, wider numbers are not truncated) inserted before the image file extension (e.g., P01.mp4 for frame 10 becomes P01-0010.png).
|
||||
.PARAMETER Video
|
||||
Path to the input video file. Can be absolute or relative to current directory.
|
||||
.PARAMETER Frame
|
||||
0-based frame index to extract. Negative values count from the end:
|
||||
-1 extracts the last frame (default), -2 extracts second-to-last, etc.
|
||||
The resulting frame index is clamped to the valid range (0 to total frames - 1).
|
||||
-1 extracts the last frame, -2 extracts second-to-last, etc.
|
||||
The resulting frame index is clamped to the valid range (0 to total frames - 1): a positive value past the last frame
|
||||
gives the last frame, and a negative value before the first frame gives frame 0.
|
||||
#>
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
@@ -35,8 +36,7 @@ $totalFramesOutput = & ffprobe -v error -select_streams v:0 -count_frames -show_
|
||||
$ffprobeExit = $LASTEXITCODE
|
||||
|
||||
if ($ffprobeExit -ne 0) {
|
||||
$totalFramesOutput | ForEach-Object { Write-Error $_ }
|
||||
Write-Error ('ffprobe failed to read video file: {0}' -f $VideoPath)
|
||||
Write-Error ('ffprobe failed to read video file: {0}{1}{2}' -f $VideoPath, [Environment]::NewLine, ($totalFramesOutput -join [Environment]::NewLine))
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -48,19 +48,15 @@ if (-not $totalFrames -or ([string]$totalFrames).Trim() -notmatch '^\d+$') {
|
||||
}
|
||||
|
||||
$totalFramesInt = [int]([string]$totalFrames).Trim()
|
||||
if ($totalFramesInt -lt 1) {
|
||||
Write-Error ('Video has no frames: {0}' -f $VideoPath)
|
||||
exit 1
|
||||
}
|
||||
$maxFrameIndex = $totalFramesInt - 1
|
||||
|
||||
# Resolve frame index (handles negative values that count from the end)
|
||||
$frameToExtract = if ($Frame -lt 0) {
|
||||
$calculatedFrame = $totalFramesInt + $Frame
|
||||
[Math]::Max(0, [Math]::Min($calculatedFrame, $maxFrameIndex))
|
||||
} else {
|
||||
if ($Frame -gt $maxFrameIndex) {
|
||||
Write-Error ('Frame index {0} is out of range. Valid range: 0 to {1}' -f $Frame, $maxFrameIndex)
|
||||
exit 1
|
||||
}
|
||||
$Frame
|
||||
}
|
||||
$requestedFrame = if ($Frame -lt 0) { $totalFramesInt + $Frame } else { $Frame }
|
||||
$frameToExtract = [Math]::Max(0, [Math]::Min($requestedFrame, $maxFrameIndex))
|
||||
|
||||
# Derive the output image path: insert "-XXXX" (zero-padded resolved frame index) before .png extension
|
||||
$videoBase = [System.IO.Path]::GetFileNameWithoutExtension($VideoPath)
|
||||
|
||||
Reference in new issue
Block a user