0

Thanks to the help of the user mklement0 I got this script to automatically convert all files in the folder "video_old" and move them into "video_new", all while keeping the original filename. Original Post.

Now I want to remove the black bars in the container. I know that there is "cropdetect" but AFAIK you have to manually parse the the value into the script. What parameter should I add to bellow's ffmpeg execution?

Get-ChildItem .\video_old -Filter *.mkv | ForEach-Object {
  .\ffmpeg.exe -i $_.FullName -c:v libx265 -crf 18 ".\video_new\$($_.Name)"
}

Parameters used to remove the bars

ffmpeg -ss 90 -i input.mkv -vframes 10 -vf cropdetect -f null -
...
[Parsed_cropdetect_0 @ 0x220cdc0] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:215 t:0.215000 crop=1280:720:0:0
[Parsed_cropdetect_0 @ 0x220cdc0] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:257 t:0.257000 crop=1280:720:0:0
[Parsed_cropdetect_0 @ 0x220cdc0] x1:0 x2:1279 y1:0 y2:719 w:1280 h:720 x:0 y:0 pts:299 t:0.299000 crop=1280:720:0:0

In this example, we can apply the filter like this:

ffmpeg -i input.mkv -vf crop=1280:720:0:0 -c:a copy output.mkv

OriginalPost

Screenshot

Example screenshot from one of the files

6
  • exactly what do you mean with black bars, can you add a screenshot? and what value needs to be inserted into the script (this script does not accept any named parameters)? Commented Apr 7, 2020 at 17:14
  • @RoqueSosa Imgur. No the script doesn't accept any named parameters because I don't know what to enter :C Commented Apr 7, 2020 at 17:30
  • I can help you with the modification to the script, but can you edit the question and add an example of them parameter used to remove the black bars from 1 video? Commented Apr 7, 2020 at 23:38
  • @RoqueSosa Done as you wish Commented Apr 8, 2020 at 22:52
  • @timlwsk Perhaps not particularly useful for you as it is for Linux, but the solution in ffmpeg get value from cropdetect is worth looking at. I don't know PowerShell at all so I can't suggest alternative tools to emulate awk, etc. Commented Apr 8, 2020 at 23:16

2 Answers 2

4

Now that I understand, try this:

Get-ChildItem .\video_old -Filter *.mkv | ForEach-Object {
    $exportPath=".\video_new\$($_.Name)"
    #Export
    .\ffmpeg.exe -i $_.FullName -c:v libx265 -crf 18 $exportPath
    Write-Host "Exported file on $exportPath."
    #Know where to cut
    $results = .\ffmpeg.exe -ss 90 -i $exportPath -vframes 10 -vf cropdetect -f null - 2>&1
    #Cut
    if(($results | ? {$_ -match 'crop=\d{1,4}:\d[0-9]{1,4}:\d:\d'})){
        Write-Host "The regular expression was matched, value $($Matches[0])."
        .\ffmpeg.exe -i $exportPath -vf ($Matches[0]) -c:a copy ($exportPath.Replace($_.BaseName,"$($_.BaseName)_CUT"))
    }else{
        Write-Host "The regular expression was NOT matched. The line was '$($resultsParsed[0])'"
        $results | Out-File .\resultsFromCropDetect.txt
    }
}

I don't really have a way to test it, but basically I'm running the first command that tells me where to cut, with regex I pull only that part and then do the actual cutting exporting to a new file named "OriginalName_CUT.mkv".

Let me know how it goes happy to make modifications.

EDIT

After a long amounts of try, I asked for the output of ffmpeg cropdetect and debugged locally, simplified the process to find the match of cropdetect.

Sign up to request clarification or add additional context in comments.

8 Comments

Sadly, it fails right where it should cut. Es ist nicht möglich, einen Index auf ein NULL-Array anzuwenden. In D:\FFMPEG BatchProcessing\convert.ps1:9 Zeichen:8 + if($results[0] -match 'crop=\d{1,4}:\d[0-9]{1,4}:\d:\d'){ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray Translation says: not possible to use an index at a NULL array
ok, that error was thrown because, $results did not get filled, I'm guessing the .\ffmpeg -ss 90 -i $exportPath -vframes 10 -vf cropdetect -f null - didnt return anything. I'll modify it to just write to console the vars to debug, also Ich spreche ein bisschen Deutsch.
Kinda unsure if you already tried to fix it or not (sorry). Is the version up above the fixed already?
yeah, try it again please, I added small text output so I can debug from here hahaha
Oh, my bad! It now returns "Crop Detect gave 0 line(s) of output." full console output.
|
1

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
    }
}

1 Comment

that is very thorough, I didn't expect to get a reply anymore. Thank you very much Gille!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.