Last active
August 15, 2024 18:08
-
-
Save milnak/8f7c24514b2d5bb430092ba15c6c2d99 to your computer and use it in GitHub Desktop.
Script to normalize MP3 and FLAC: Uses ffmpeg-normalize and ffmpeg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Normalize mp3 and flac files in current directory using ffmpeg-normalize | |
| # scoop install ffmpeg | |
| $ffmpeg = 'ffmpeg.exe' | |
| # scoop install python | |
| # pip3.exe install ffmpeg-normalize | |
| $ffmpeg_normalize = 'ffmpeg-normalize.exe' | |
| function Get-MeanVolume { | |
| Param([Parameter(Mandatory = $true)][string]$File) | |
| $psi = New-Object Diagnostics.ProcessStartInfo | |
| $psi.FileName = $ffmpeg | |
| $psi.RedirectStandardError = $true | |
| $psi.RedirectStandardOutput = $false | |
| $psi.UseShellExecute = $false | |
| $psi.Arguments = "-hide_banner -nostdin -i `"{0}`" -filter:a volumedetect -f null /dev/null" -f $File | |
| $proc = New-Object System.Diagnostics.Process | |
| $proc.StartInfo = $psi | |
| $proc.Start() | Out-Null | |
| # Important: ReadToEnd must come before WaitForExit! | |
| $err = $proc.StandardError.ReadToEnd() | |
| $proc.WaitForExit() | Out-Null | |
| [double]($err -split "`r`n" | Select-String 'mean_volume: (.+) dB').Matches.Groups[1].Value | |
| } | |
| function Normalize-File { | |
| Param( | |
| [Parameter(Mandatory = $true)][string]$File, | |
| [int]$TargetLevel = -18, | |
| [string]$OutputFolder = 'NORMALIZED' | |
| ) | |
| # Extension without dot. | |
| $ext = [IO.Path]::GetExtension($File).Substring(1) | |
| # Why -c:a ext ? | |
| # See https://github.com/slhck/ffmpeg-normalize#could-not-write-header-for-output-file-error | |
| # The conversion does not work and I get a cryptic ffmpeg error! | |
| & $ffmpeg_normalize --output-folder $OutputFolder --normalization-type rms --target-level $TargetLevel --force -c:a $ext --extension $ext $File | |
| } | |
| if (-not (Get-Command $ffmpeg -CommandType Application -ErrorAction SilentlyContinue)) { | |
| "'{0}' not found." -f $ffmpeg | |
| return | |
| } | |
| if (-not (Get-Command $ffmpeg_normalize -CommandType Application -ErrorAction SilentlyContinue)) { | |
| "'{0}' not found." -f $ffmpeg_normalize | |
| return | |
| } | |
| Get-ChildItem -File | Where-Object Extension -in '.mp3', '.flac' | ForEach-Object { | |
| # --target-level -13 (Average RMS Power in dbFS) is what pynormalize uses https://pypi.org/project/pynormalize/ | |
| # but that seems too aggressive, so I'm using -18. | |
| [int]$targetLevel = -18 | |
| $_.Name | |
| [double]$level = Get-MeanVolume -File $_.FullName | |
| if ([int]$level -ge [int]$targetLevel) { | |
| "`tLevel $level is fine. Skipping" | |
| } | |
| else { | |
| Normalize-File -File $_.FullName -TargetLevel $targetLevel -OutputFolder 'NORMALIZED' | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment