Add Video_Length field to Get-VideoInfo.ini mapping to frames_count for reading actual encoded frame count directly from ffprobe instead of JSON metadata, with duration calculation using real fps

This commit is contained in:
2026-07-03 10:17:50 -04:00
parent 84811de486
commit f69f9b367c
2 changed files with 71 additions and 53 deletions
+1
View File
@@ -2,6 +2,7 @@ Text_Prompt=prompt
Model=type Model=type
Resolution=resolution Resolution=resolution
Number_of_frames=video_length Number_of_frames=video_length
Video_Length=frames_count
Seed=seed Seed=seed
Frames_Positions=frames_positions Frames_Positions=frames_positions
Guidance=guidance_scale Guidance=guidance_scale
+70 -53
View File
@@ -9,7 +9,9 @@
When present, outputs the parsed comment metadata as JSON. When present, outputs the parsed comment metadata as JSON.
.DESCRIPTION .DESCRIPTION
This script uses ffprobe to extract video format metadata, parses the comment tag as JSON, This script uses ffprobe to extract video format metadata, parses the comment tag as JSON,
and outputs the structured information with proper error handling. and outputs the structured information with proper error handling. Fields configured as
'frames_count' in the INI file are read directly from ffprobe (actual encoded frame count)
rather than from the JSON metadata.
#> #>
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
@@ -148,63 +150,78 @@ try {
$displayNameFormatted = $displayName -replace '_', ' ' $displayNameFormatted = $displayName -replace '_', ' '
$fieldExists = $parsedComment.PSObject.Properties.Name -contains $jsonFieldName if ($jsonFieldName -eq 'frames_count') {
# frames_count is read directly from ffprobe (actual encoded frame count)
if (-not $fieldExists) { # rather than from the JSON comment metadata.
$valueDisplay = 'Not found' $fps = if ($actualFps) { $actualFps } else { 24.0 }
} $ffFrames = & ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of csv=p=0 -- "$VideoPath" 2>&1 | Select-Object -First 1
else { if ($ffFrames -and $ffFrames -match '^\d+$') {
$fieldValue = $parsedComment.$jsonFieldName $frames = [int]$ffFrames
if ($null -eq $fieldValue) {
$valueDisplay = 'Not found'
}
elseif ($jsonFieldName -eq 'generation_time') {
$totalSeconds = [int]$fieldValue
$minutes = [Math]::Floor($totalSeconds / 60)
$seconds = $totalSeconds % 60
$valueDisplay = ('{0}s ({1}m {2}s)' -f $totalSeconds, $minutes, $seconds)
}
elseif ($jsonFieldName -eq 'creation_date') {
try {
$dateTime = [DateTime]::Parse($fieldValue)
$valueDisplay = $dateTime.ToString('yyyy-MM-dd HH:mm:ss')
}
catch {
$valueDisplay = $fieldValue -replace 'T', ' '
}
}
elseif ($jsonFieldName -eq 'video_length') {
# Always use the real frame rate reported by ffprobe for the
# duration calculation. The JSON metadata's force_fps may be a
# non-numeric mode marker (e.g. "control") or simply not match
# the actual encoded frame rate.
$fps = if ($actualFps) { $actualFps } else { 24.0 }
$frames = [int]$fieldValue
$durationSeconds = [Math]::Round($frames / $fps, 1) $durationSeconds = [Math]::Round($frames / $fps, 1)
$valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $durationSeconds, $fps) $valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $durationSeconds, $fps)
} else {
$valueDisplay = 'Not found'
} }
elseif ($fieldValue -is [array]) { }
if ($fieldValue.Count -gt 1) { else {
# Pretty-print array values as JSON, prefixed with a newline so the $fieldExists = $parsedComment.PSObject.Properties.Name -contains $jsonFieldName
# multi-line output starts cleanly under the field label.
$jsonArray = $fieldValue | ConvertTo-Json -Depth 10 if (-not $fieldExists) {
$valueDisplay = [Environment]::NewLine + $jsonArray $valueDisplay = 'Not found'
}
else {
$jsonArray = $fieldValue | ConvertTo-Json -Depth 10 -Compress
$valueDisplay = $jsonArray
}
} }
else { else {
$valueDisplay = $fieldValue $fieldValue = $parsedComment.$jsonFieldName
# If the value looks like a WxH resolution string and ffprobe
# reports a different actual encoded resolution, surface both. if ($null -eq $fieldValue) {
if ($actualResolution ` $valueDisplay = 'Not found'
-and ($fieldValue -is [string]) ` }
-and ($fieldValue -match '^\d+x\d+$') ` elseif ($jsonFieldName -eq 'generation_time') {
-and ($fieldValue -ne $actualResolution)) { $totalSeconds = [int]$fieldValue
$valueDisplay = "$fieldValue (real: $actualResolution)" $minutes = [Math]::Floor($totalSeconds / 60)
$seconds = $totalSeconds % 60
$valueDisplay = ('{0}s ({1}m {2}s)' -f $totalSeconds, $minutes, $seconds)
}
elseif ($jsonFieldName -eq 'creation_date') {
try {
$dateTime = [DateTime]::Parse($fieldValue)
$valueDisplay = $dateTime.ToString('yyyy-MM-dd HH:mm:ss')
}
catch {
$valueDisplay = $fieldValue -replace 'T', ' '
}
}
elseif ($jsonFieldName -eq 'video_length') {
# Always use the real frame rate reported by ffprobe for the
# duration calculation. The JSON metadata's force_fps may be a
# non-numeric mode marker (e.g. "control") or simply not match
# the actual encoded frame rate.
$fps = if ($actualFps) { $actualFps } else { 24.0 }
$frames = [int]$fieldValue
$durationSeconds = [Math]::Round($frames / $fps, 1)
$valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $durationSeconds, $fps)
}
elseif ($fieldValue -is [array]) {
if ($fieldValue.Count -gt 1) {
# Pretty-print array values as JSON, prefixed with a newline so the
# multi-line output starts cleanly under the field label.
$jsonArray = $fieldValue | ConvertTo-Json -Depth 10
$valueDisplay = [Environment]::NewLine + $jsonArray
}
else {
$jsonArray = $fieldValue | ConvertTo-Json -Depth 10 -Compress
$valueDisplay = $jsonArray
}
}
else {
$valueDisplay = $fieldValue
# If the value looks like a WxH resolution string and ffprobe
# reports a different actual encoded resolution, surface both.
if ($actualResolution `
-and ($fieldValue -is [string]) `
-and ($fieldValue -match '^\d+x\d+$') `
-and ($fieldValue -ne $actualResolution)) {
$valueDisplay = "$fieldValue (real: $actualResolution)"
}
} }
} }
} }