Modifying the previous answer.. there's no need to encode twice... doing so introduces unnecessary generational loss. Also, the regex match needs to be able to detect more than one digit in the last section of the cropdetect output to handle things like this "crop=1920:880:0:40"... without the modification you may get a weird offset and incorrect crop. I have ffmpeg in my system's PATH, so I replaced ".\ffmpeg.exe" with "ffmpeg". I changed ".\video_old" to ".\ " to detect files in the directory that the script is run in and export to a known folder I have on my network "X:\HEVC_Output". This workflow just makes more sense for me. Another note: The encoder settings I have in there are a bit overkill for most cpus. Something like -c:v libx265 -crf 18 -c:a copy should be sufficient for most. You may also get wonky crop results if its dark in parts of the scene at 90 seconds into the file, so you can mess around with that number and see if you get a more accurate result. You can also mess around with the limit on the cropdetect Example: cropdetect=16:2:0 ...16 is the limit argument in this case, 2 is the round argument (result is divisible by this value, if not, it rounds to nearest integer that is divisible by the value), and 0 being the reset argument (used for looping scenarios). The defaults are 24:16:0. Higher limit values will result in over-cropping, lower limit values can lead to under-cropping, but its another dial you could tinker with if needed.
Get-ChildItem .\ -Filter *.mkv | ForEach-Object {
$exportPath="X:\HEVC_Output\$($_.Name)"
#Know where to cut
$results = ffmpeg -ss 90 -i $($_.Name) -vframes 10 -vf cropdetect -f null - 2>&1
#Cut
if(($results | ? {$_ -match 'crop=\d{1,4}:\d[0-9]{1,4}:\d:\d[0-9]{0,4}'})){
Write-Host "The regular expression was matched, value $($Matches[0])."
ffmpeg -i $($_.Name) -vf ($Matches[0]) -c:v libx265 -crf 22 -preset medium -tune ssim -profile:v main10 -level:v 4 -x265-params "bframes=8:scenecut-bias=0.05:me=star:subme=5:refine-mv=1:limit-refs=1:rskip=0:max-merge=5:rc-lookahead=80:lookahead-slices=5:min-keyint=23:max-luma=1023:psy-rd=2:strong-intra-smoothing=0:b-intra=1:hist-threshold=0.03" -c:a copy -c:s copy $exportPath
}else{
Write-Host "The regular expression was NOT matched. The line was '$($resultsParsed[0])'"
$results | Out-File .\resultsFromCropDetect.txt
}
}
Another variation using the crop detect limit and round settings from the example, also allowing user to select the input directory. Searches the dir and subdirs recursively for *.mkv and *.mp4.
Add-Type -AssemblyName System.Windows.Forms
$dialog = [System.Windows.Forms.FolderBrowserDialog]::new()
$dialog.Description = 'Select a folder containing videos you want to convert'
$dialog.RootFolder = [System.Environment+specialfolder]::Desktop
$dialog.ShowNewFolderButton = $true
$dialog.ShowDialog()
$importPath = $dialog.SelectedPath
Write-Host "Import path chosen $importPath."
Start-Sleep -s 5
Get-ChildItem $importPath -Recurse -Include *.mkv, *.mp4 | ForEach-Object {
$exportPath="X:\HEVC_Output\$($_.Name)"
Write-Host "Exporting file to $exportPath."
#Know where to cut
$results = ffmpeg -ss 90 -i $_.FullName -vframes 10 -vf cropdetect=16:2:0 -f null - 2>&1
#Cut
if(($results | ? {$_ -match 'crop=\d{1,4}:\d[0-9]{1,4}:\d:\d[0-9]{0,4}'})){
Write-Host "The regular expression was matched, value $($Matches[0])."
Start-Sleep -s 5
ffmpeg -i $_.FullName -vf ($Matches[0]) -c:v libx265 -crf 22 -preset medium -tune ssim -profile:v main10 -level:v 4 -x265-params "bframes=8:scenecut-bias=0.05:me=star:subme=5:refine-mv=1:limit-refs=1:rskip=0:max-merge=5:rc-lookahead=80:lookahead-slices=5:min-keyint=23:max-luma=1023:psy-rd=2:strong-intra-smoothing=0:b-intra=1:hist-threshold=0.03" -c:a copy -c:s copy $exportPath
}else{
Write-Host "The regular expression was NOT matched. The line was '$($resultsParsed[0])'"
$results | Out-File .\resultsFromCropDetect.txt
}
}