Add actual encoded resolution and frame rate detection from ffprobe video stream data
This commit is contained in:
+44
-21
@@ -33,7 +33,7 @@ if (-not (Test-Path -LiteralPath $VideoPath)) {
|
|||||||
$PSNativeCommandUseErrorActionPreference = $false
|
$PSNativeCommandUseErrorActionPreference = $false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$ffprobeOutput = & ffprobe -v quiet -print_format json -show_format -- $VideoPath 2>&1
|
$ffprobeOutput = & ffprobe -v quiet -print_format json -show_format -show_streams -- $VideoPath 2>&1
|
||||||
$ffprobeExit = $LASTEXITCODE
|
$ffprobeExit = $LASTEXITCODE
|
||||||
|
|
||||||
if ($ffprobeExit -ne 0) {
|
if ($ffprobeExit -ne 0) {
|
||||||
@@ -56,6 +56,34 @@ try {
|
|||||||
|
|
||||||
$commentJson = $raw.format.tags.comment
|
$commentJson = $raw.format.tags.comment
|
||||||
|
|
||||||
|
# Extract the actual (encoded) resolution and frame rate from the first video
|
||||||
|
# stream reported by ffprobe. These may differ from the values stored in the
|
||||||
|
# JSON comment metadata (e.g. WanGP/LTX records "720x1280" but the file is
|
||||||
|
# actually encoded at 704x1280 after the model's internal padding/cropping).
|
||||||
|
$actualResolution = $null
|
||||||
|
$actualFps = $null
|
||||||
|
$get = { param($obj, $name) if ($obj -and ($obj.PSObject.Properties.Name -contains $name)) { $obj.$name } else { $null } }
|
||||||
|
|
||||||
|
if ($raw.PSObject.Properties.Name -contains 'streams') {
|
||||||
|
$videoStream = $raw.streams | Where-Object { $_.codec_type -eq 'video' } | Select-Object -First 1
|
||||||
|
if ($videoStream) {
|
||||||
|
$w = & $get $videoStream 'width'
|
||||||
|
$h = & $get $videoStream 'height'
|
||||||
|
if ($w -and $h) {
|
||||||
|
$actualResolution = '{0}x{1}' -f [int]$w, [int]$h
|
||||||
|
}
|
||||||
|
|
||||||
|
$rfr = & $get $videoStream 'r_frame_rate'
|
||||||
|
if ($rfr -and $rfr -match '^(\d+)/(\d+)$') {
|
||||||
|
$num = [double]$matches[1]
|
||||||
|
$den = [double]$matches[2]
|
||||||
|
if ($den -ne 0) {
|
||||||
|
$actualFps = [Math]::Round($num / $den, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$parsedComment = $commentJson | ConvertFrom-Json
|
$parsedComment = $commentJson | ConvertFrom-Json
|
||||||
}
|
}
|
||||||
@@ -123,33 +151,28 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ($jsonFieldName -eq 'video_length') {
|
elseif ($jsonFieldName -eq 'video_length') {
|
||||||
$fps = 24.0
|
# Always use the real frame rate reported by ffprobe for the
|
||||||
$fieldExists = $parsedComment.PSObject.Properties.Name -contains 'force_fps'
|
# duration calculation. The JSON metadata's force_fps may be a
|
||||||
|
# non-numeric mode marker (e.g. "control") or simply not match
|
||||||
if ($fieldExists) {
|
# the actual encoded frame rate.
|
||||||
# force_fps may be a number (e.g. 30) or a non-numeric mode string
|
$fps = if ($actualFps) { $actualFps } else { 24.0 }
|
||||||
# (e.g. "control" in some WanGP/LTX presets). Only override the
|
|
||||||
# default when the value parses as a positive number.
|
|
||||||
$forceFpsRaw = $parsedComment.force_fps
|
|
||||||
$parsedFps = 0.0
|
|
||||||
if ([double]::TryParse(
|
|
||||||
[string]$forceFpsRaw,
|
|
||||||
[System.Globalization.NumberStyles]::Float,
|
|
||||||
[System.Globalization.CultureInfo]::InvariantCulture,
|
|
||||||
[ref]$parsedFps) -and $parsedFps -gt 0) {
|
|
||||||
$fps = $parsedFps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$frames = [int]$fieldValue
|
$frames = [int]$fieldValue
|
||||||
$secondsAt24fps = [Math]::Round($frames / $fps, 1)
|
$durationSeconds = [Math]::Round($frames / $fps, 1)
|
||||||
$valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $secondsAt24fps, $fps)
|
$valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $durationSeconds, $fps)
|
||||||
}
|
}
|
||||||
elseif ($fieldValue -is [array]) {
|
elseif ($fieldValue -is [array]) {
|
||||||
$valueDisplay = ($fieldValue | ConvertTo-Json -Compress -Depth 10)
|
$valueDisplay = ($fieldValue | ConvertTo-Json -Compress -Depth 10)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$valueDisplay = $fieldValue
|
$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)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user