<# .SYNOPSIS Extracts and displays video metadata from the comment tag in a video file's format metadata. .PARAMETER Video Path to the input video file. Can be absolute or relative to current directory. .PARAMETER Full When present, outputs the parsed comment metadata as JSON. .DESCRIPTION This script uses ffprobe to extract video format metadata, parses the comment tag as JSON, and outputs the structured information with proper error handling. #> param( [Parameter(Mandatory = $true)] [string]$Video, [Parameter(Mandatory = $false)] [switch]$Full ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8 $VideoPath = $Video if (-not (Test-Path -LiteralPath $VideoPath)) { Write-Error ('Video file not found: {0}' -f $VideoPath) exit 1 } $PSNativeCommandUseErrorActionPreference = $false try { $ffprobeOutput = & ffprobe -v quiet -print_format json -show_format -- $VideoPath 2>&1 $ffprobeExit = $LASTEXITCODE if ($ffprobeExit -ne 0) { $ffprobeOutput | ForEach-Object { Write-Error $_ } Write-Error ('ffprobe failed to read video file: {0}' -f $VideoPath) exit 1 } $raw = $ffprobeOutput | ConvertFrom-Json if (-not $raw -or -not $raw.format) { Write-Error ('ffprobe did not return valid format metadata for: {0}' -f $VideoPath) exit 1 } if (-not $raw.format.tags -or -not $raw.format.tags.comment) { Write-Error ('Video file does not contain a comment tag in format metadata: {0}' -f $VideoPath) exit 1 } $commentJson = $raw.format.tags.comment try { $parsedComment = $commentJson | ConvertFrom-Json } catch { Write-Error ('Failed to parse comment tag as JSON: {0}' -f $_.Exception.Message) exit 1 } $output = $parsedComment | ConvertTo-Json -Depth 20 if ($Full) { Write-Output $output } Write-Output '----------------------------------------' Write-Output ('File Name: {0}' -f $Video) $iniPath = Join-Path $PSScriptRoot 'Get-VideoInfo.ini' if (-not (Test-Path -LiteralPath $iniPath)) { Write-Error ('INI configuration file not found: {0}' -f $iniPath) exit 1 } $iniLines = Get-Content -LiteralPath $iniPath -Encoding UTF8 foreach ($line in $iniLines) { $trimmedLine = $line.Trim() if ([string]::IsNullOrWhiteSpace($trimmedLine) -or $trimmedLine.StartsWith('#')) { continue } if ($trimmedLine -notmatch '^([^=]+)=([^=]+)$') { continue } $displayName = $matches[1].Trim() $jsonFieldName = $matches[2].Trim() $displayNameFormatted = $displayName -replace '_', ' ' $fieldExists = $parsedComment.PSObject.Properties.Name -contains $jsonFieldName if (-not $fieldExists) { $valueDisplay = 'Not found' } else { $fieldValue = $parsedComment.$jsonFieldName 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') { $fps = 24.0 $fieldExists = $parsedComment.PSObject.Properties.Name -contains 'force_fps' if ($fieldExists) { $fps = [double]$parsedComment.force_fps } $frames = [int]$fieldValue $secondsAt24fps = [Math]::Round($frames / $fps, 1) $valueDisplay = ('{0} frames ({1}s, {2} fps)' -f $frames, $secondsAt24fps, $fps) } elseif ($fieldValue -is [array]) { $valueDisplay = ($fieldValue | ConvertTo-Json -Compress -Depth 10) } else { $valueDisplay = $fieldValue } } Write-Output ('{0}: {1}' -f $displayNameFormatted, $valueDisplay) } Write-Output '----------------------------------------' } catch { Write-Error ('Unexpected error: {0}' -f $_.Exception.Message) exit 1 }