diff --git a/Crop-ClipsKling.cmd b/Crop-ClipsKling.cmd deleted file mode 100644 index e018be4..0000000 --- a/Crop-ClipsKling.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0Crop-ClipsKling.ps1" %* diff --git a/Crop-ClipsKling.ps1 b/Crop-ClipsKling.ps1 deleted file mode 100644 index e81339e..0000000 --- a/Crop-ClipsKling.ps1 +++ /dev/null @@ -1,202 +0,0 @@ -<# -.SYNOPSIS - Crops video clips using ffmpeg. -.PARAMETER Source - Source directory containing video files. -.PARAMETER Target - Target directory for cropped video files. -.DESCRIPTION - Crops video clips using ffmpeg. - Supports -WhatIf and -Confirm for safe execution. -#> -[CmdletBinding(SupportsShouldProcess)] -param( - [Parameter(Mandatory = $false)] - [string]$Source = '.', - - [Parameter(Mandatory = $false)] - [string]$Target = '.' -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -function Get-VideoInfo { - param( - [Parameter(Mandatory = $true)] - [string]$Path - ) - - $json = & ffprobe -v error -print_format json -show_streams -show_format -- "$Path" - if ($LASTEXITCODE -ne 0 -or -not $json) { - throw "ffprobe failed for: $Path" - } - - $info = $json | ConvertFrom-Json - $videoStream = $info.streams | Where-Object { $_.codec_type -eq 'video' } | Select-Object -First 1 - if (-not $videoStream) { - throw "No video stream found in: $Path" - } - - $audioStream = $info.streams | Where-Object { $_.codec_type -eq 'audio' } | Select-Object -First 1 - - # Safe property accessor: returns $null when the property is absent (strict-mode friendly). - $get = { param($obj, $name) if ($obj -and ($obj.PSObject.Properties.Name -contains $name)) { $obj.$name } else { $null } } - - $rFrameRate = & $get $videoStream 'r_frame_rate' - $fps = $null - if ($rFrameRate -and $rFrameRate -match '^(\d+)/(\d+)$') { - $num = [double]$Matches[1] - $den = [double]$Matches[2] - if ($den -ne 0) { - $fps = $num / $den - } - } - - $videoBitRate = & $get $videoStream 'bit_rate' - $formatBitRate = & $get $info.format 'bit_rate' - $bitRate = if ($videoBitRate) { $videoBitRate } else { $formatBitRate } - - [pscustomobject]@{ - Path = $Path - FileName = [System.IO.Path]::GetFileName($Path) - Width = [int]$videoStream.width - Height = [int]$videoStream.height - Fps = $fps - BitRate = $bitRate - HasAudio = [bool]$audioStream - VideoBitRate = $videoBitRate - } -} - -function Format-Quality { - param( - [Parameter(Mandatory = $false)] - $BitRate - ) - - if (-not $BitRate -or $BitRate -notmatch '^\d+$') { - return 'unknown' - } - - $kbps = [math]::Round(([double]$BitRate) / 1000.0) - return "${kbps}kbps" -} - -$sourceFull = (Resolve-Path -LiteralPath $Source).Path -$targetFull = (Resolve-Path -LiteralPath $Target).Path - -$BackupRequired = ($sourceFull.TrimEnd('\') -ieq $targetFull.TrimEnd('\')) - -$processedCount = 0 - -$videos = Get-ChildItem -LiteralPath $sourceFull -Filter '*.mp4' -File -foreach ($video in $videos) { - if ($video.Name -like '*.bak.mp4' -or $video.Name -like '*.skip.mp4') { - continue - } - - $inputPath = $video.FullName - - $inInfo = $null - try { - $inInfo = Get-VideoInfo -Path $inputPath - } - catch { - Write-Error $_ - throw - } - - $inRes = "{0}x{1}" -f $inInfo.Width, $inInfo.Height - - $is1072 = ($inInfo.Height -eq 1072 -and ($inInfo.Width -eq 1920 -or $inInfo.Width -eq 1928)) - $is1916x1080 = ($inInfo.Width -eq 1916 -and $inInfo.Height -eq 1080) - $is1920x1076 = ($inInfo.Width -eq 1920 -and $inInfo.Height -eq 1076) - - if (-not $is1072 -and -not $is1916x1080 -and -not $is1920x1076) { - Write-Host "Skipping: $($inInfo.FileName) (resolution $inRes)" - continue - } - - if ($BackupRequired) { - $backupPath = Join-Path $video.DirectoryName ($video.BaseName + '.bak' + $video.Extension) - if ($PSCmdlet.ShouldProcess($backupPath, 'Create backup of original video')) { - Copy-Item -LiteralPath $inputPath -Destination $backupPath -Force - } - } - - $outCropPath = Join-Path $targetFull ($video.BaseName + '.crop.mp4') - $outFinalPath = Join-Path $targetFull $video.Name - - if ($is1916x1080) { - $vfFilter = 'pad=1920:1082:2:1:black,crop=1920:1080:0:1' - } - else { - $vfFilter = 'scale=-2:1080,crop=1920:1080:(in_w-1920)/2:(in_h-1080)/2' - } - - $ffArgs = @( - '-y', - '-i', $inputPath, - '-vf', $vfFilter - ) - - if ($inInfo.HasAudio) { - $ffArgs += @('-c:a', 'copy') - } - else { - $ffArgs += @('-an') - } - - if ($inInfo.VideoBitRate -and $inInfo.VideoBitRate -match '^\d+$') { - $ffArgs += @('-b:v', $inInfo.VideoBitRate) - } - else { - $ffArgs += @('-crf', '8', '-preset', 'slow') - } - - $ffArgs += @($outCropPath) - - if ($PSCmdlet.ShouldProcess($outCropPath, 'Crop video with ffmpeg')) { - $ffmpegOutput = & ffmpeg @ffArgs 2>&1 - $ffmpegExit = $LASTEXITCODE - - if ($ffmpegExit -ne 0) { - if (Test-Path -LiteralPath $outCropPath) { - Remove-Item -LiteralPath $outCropPath -Force -ErrorAction SilentlyContinue - } - - $ffmpegOutput | ForEach-Object { Write-Error $_ } - Write-Error "ffmpeg failed while cropping: $($inInfo.FileName)" - Write-Host "ffmpeg $($ffArgs -join ' ')" - exit 1 - } - - if (($BackupRequired) -and ($PSCmdlet.ShouldProcess($inputPath, 'Remove original video after backup'))) { - Remove-Item -LiteralPath $inputPath -Force - } - - if ((Test-Path -LiteralPath $outFinalPath) -and ($PSCmdlet.ShouldProcess($outFinalPath, 'Remove existing output file'))) { - Remove-Item -LiteralPath $outFinalPath -Force - } - if ($PSCmdlet.ShouldProcess("$outCropPath -> $outFinalPath", 'Move cropped video to final location')) { - Move-Item -LiteralPath $outCropPath -Destination $outFinalPath -Force - } - } else { - $formattedArgs = $ffArgs | ForEach-Object { if ($_ -match '\s') { "`"$_`"" } else { $_ } } - Write-Host "WhatIf: Would crop video with ffmpeg $($formattedArgs -join ' ')" - } - - $outInfo = Get-VideoInfo -Path $outFinalPath - $outRes = "{0}x{1}" -f $outInfo.Width, $outInfo.Height - $outFpsText = if ($outInfo.Fps) { "{0:0.###}" -f $outInfo.Fps } else { 'unknown' } - $outQuality = Format-Quality -BitRate $outInfo.BitRate - $outAudioText = if ($outInfo.HasAudio) { 'yes' } else { 'no' } - - Write-Host "Output: Filename=$($outInfo.FileName) Resolution=$outRes FPS=$outFpsText Quality=$outQuality Audio=$outAudioText" - - $processedCount++ -} - -Write-Host "Processed (cropped) videos: $processedCount" - diff --git a/Crop-ClipsWan.cmd b/Crop-ClipsWan.cmd deleted file mode 100644 index 71e1a4e..0000000 --- a/Crop-ClipsWan.cmd +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0Crop-ClipsWan.ps1" %* diff --git a/Crop-ClipsWan.ps1 b/Crop-ClipsWan.ps1 deleted file mode 100644 index 3cfab94..0000000 --- a/Crop-ClipsWan.ps1 +++ /dev/null @@ -1,210 +0,0 @@ -<# -.SYNOPSIS - Crops video clips using ffmpeg. -.PARAMETER Source - Source directory containing video files. -.PARAMETER Target - Target directory for cropped video files. -.DESCRIPTION - Crops video clips from 1928x1076 or 1926x1076 to 1920x1080, or from 1284x716 to 1280x720 using ffmpeg. - Supports -WhatIf and -Confirm for safe execution. -#> -[CmdletBinding(SupportsShouldProcess)] -param( - [Parameter(Mandatory = $false)] - [string]$Source = '.', - - [Parameter(Mandatory = $false)] - [string]$Target = '.' -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -function Get-VideoInfo { - param( - [Parameter(Mandatory = $true)] - [string]$Path - ) - - $json = & ffprobe -v error -print_format json -show_streams -show_format -- "$Path" - if ($LASTEXITCODE -ne 0 -or -not $json) { - throw "ffprobe failed for: $Path" - } - - $info = $json | ConvertFrom-Json - $videoStream = $info.streams | Where-Object { $_.codec_type -eq 'video' } | Select-Object -First 1 - if (-not $videoStream) { - throw "No video stream found in: $Path" - } - - $audioStream = $info.streams | Where-Object { $_.codec_type -eq 'audio' } | Select-Object -First 1 - - # Safe property accessor: returns $null when the property is absent (strict-mode friendly). - $get = { param($obj, $name) if ($obj -and ($obj.PSObject.Properties.Name -contains $name)) { $obj.$name } else { $null } } - - $rFrameRate = & $get $videoStream 'r_frame_rate' - $fps = $null - if ($rFrameRate -and $rFrameRate -match '^(\d+)/(\d+)$') { - $num = [double]$Matches[1] - $den = [double]$Matches[2] - if ($den -ne 0) { - $fps = $num / $den - } - } - - $videoBitRate = & $get $videoStream 'bit_rate' - $formatBitRate = & $get $info.format 'bit_rate' - $bitRate = if ($videoBitRate) { $videoBitRate } else { $formatBitRate } - - [pscustomobject]@{ - Path = $Path - FileName = [System.IO.Path]::GetFileName($Path) - Width = [int]$videoStream.width - Height = [int]$videoStream.height - Fps = $fps - BitRate = $bitRate - HasAudio = [bool]$audioStream - VideoBitRate = $videoBitRate - } -} - -function Format-Quality { - param( - [Parameter(Mandatory = $false)] - $BitRate - ) - - if (-not $BitRate -or $BitRate -notmatch '^\d+$') { - return 'unknown' - } - - $kbps = [math]::Round(([double]$BitRate) / 1000.0) - return "${kbps}kbps" -} - -$sourceFull = (Resolve-Path -LiteralPath $Source).Path -$targetFull = (Resolve-Path -LiteralPath $Target).Path - -$BackupRequired = ($sourceFull.TrimEnd('\') -ieq $targetFull.TrimEnd('\')) - -$processedCount = 0 - -$videos = Get-ChildItem -LiteralPath $sourceFull -Filter '*.mp4' -File -foreach ($video in $videos) { - if ($video.Name -like '*.bak.mp4' -or $video.Name -like '*.skip.mp4') { - continue - } - - $inputPath = $video.FullName - - $inInfo = $null - try { - $inInfo = Get-VideoInfo -Path $inputPath - } - catch { - Write-Error $_ - throw - } - - $inRes = "{0}x{1}" -f $inInfo.Width, $inInfo.Height - $inFpsText = if ($inInfo.Fps) { "{0:0.###}" -f $inInfo.Fps } else { 'unknown' } - $inQuality = Format-Quality -BitRate $inInfo.BitRate - $inAudioText = if ($inInfo.HasAudio) { 'yes' } else { 'no' } - - $isValidResolution = ($inInfo.Width -eq 1928 -and $inInfo.Height -eq 1076) -or - ($inInfo.Width -eq 1926 -and $inInfo.Height -eq 1076) -or - ($inInfo.Width -eq 1284 -and $inInfo.Height -eq 716) - - if (-not $isValidResolution) { - Write-Host "Skipping: $($inInfo.FileName) (resolution $inRes)" - continue - } - - Write-Host "Input : Filename=$($inInfo.FileName) Resolution=$inRes FPS=$inFpsText Quality=$inQuality Audio=$inAudioText" - - if ($BackupRequired) { - $backupPath = Join-Path $video.DirectoryName ($video.BaseName + '.bak' + $video.Extension) - if ($PSCmdlet.ShouldProcess($backupPath, 'Create backup of original video')) { - Copy-Item -LiteralPath $inputPath -Destination $backupPath -Force - } - } - - $outCropPath = Join-Path $targetFull ($video.BaseName + '.crop.mp4') - $outFinalPath = Join-Path $targetFull $video.Name - - # Determine crop parameters based on input resolution - if ($inInfo.Width -eq 1284 -and $inInfo.Height -eq 716) { - # 1284x716: expand to 720 height, then crop to 1280x720 - $videoFilter = 'scale=-2:720,crop=1280:720:(in_w-1280)/2:(in_h-720)/2' - } - else { - # 1928x1076 or 1926x1076: expand to 1080 height, then crop to 1920x1080 - $videoFilter = 'scale=-2:1080,crop=1920:1080:(in_w-1920)/2:(in_h-1080)/2' - } - - $ffArgs = @( - '-y', - '-i', $inputPath, - '-vf', $videoFilter - ) - - if ($inInfo.HasAudio) { - $ffArgs += @('-c:a', 'copy') - } - else { - $ffArgs += @('-an') - } - - if ($inInfo.VideoBitRate -and $inInfo.VideoBitRate -match '^\d+$') { - $ffArgs += @('-b:v', $inInfo.VideoBitRate) - } - else { - $ffArgs += @('-crf', '8', '-preset', 'slow') - } - - $ffArgs += @($outCropPath) - - if ($PSCmdlet.ShouldProcess($outCropPath, 'Crop video with ffmpeg')) { - $ffmpegOutput = & ffmpeg @ffArgs 2>&1 - $ffmpegExit = $LASTEXITCODE - - if ($ffmpegExit -ne 0) { - if (Test-Path -LiteralPath $outCropPath) { - Remove-Item -LiteralPath $outCropPath -Force -ErrorAction SilentlyContinue - } - - $ffmpegOutput | ForEach-Object { Write-Error $_ } - Write-Error "ffmpeg failed while cropping: $($inInfo.FileName)" - Write-Host "ffmpeg $($ffArgs -join ' ')" - exit 1 - } - - if (($BackupRequired) -and ($PSCmdlet.ShouldProcess($inputPath, 'Remove original video after backup'))) { - Remove-Item -LiteralPath $inputPath -Force - } - - if ((Test-Path -LiteralPath $outFinalPath) -and ($PSCmdlet.ShouldProcess($outFinalPath, 'Remove existing output file'))) { - Remove-Item -LiteralPath $outFinalPath -Force - } - if ($PSCmdlet.ShouldProcess("$outCropPath -> $outFinalPath", 'Move cropped video to final location')) { - Move-Item -LiteralPath $outCropPath -Destination $outFinalPath -Force - } - } else { - $formattedArgs = $ffArgs | ForEach-Object { if ($_ -match '\s') { "`"$_`"" } else { $_ } } - Write-Host "WhatIf: Would crop video with ffmpeg $($formattedArgs -join ' ')" - } - - $outInfo = Get-VideoInfo -Path $outFinalPath - $outRes = "{0}x{1}" -f $outInfo.Width, $outInfo.Height - $outFpsText = if ($outInfo.Fps) { "{0:0.###}" -f $outInfo.Fps } else { 'unknown' } - $outQuality = Format-Quality -BitRate $outInfo.BitRate - $outAudioText = if ($outInfo.HasAudio) { 'yes' } else { 'no' } - - Write-Host "Output: Filename=$($outInfo.FileName) Resolution=$outRes FPS=$outFpsText Quality=$outQuality Audio=$outAudioText" - - $processedCount++ -} - -Write-Host "Processed (cropped) videos: $processedCount" -