Trim multiple mp3 files at once

I know four methods: mp3DirectCut, Mp3splt-GTK, Mp3splt or ffmpeg


mp3DirectCut (GUI version, best choice for quick results)

  • After starting, go to File » Batch processing
  • Add your mp3 folder, select Auto crop and press Start

    enter image description here

Hints

  • Choose a different folder as output to test some result files. After verifying, rerun it and choose Overwrite originals. You should be done in a couple of seconds since the program doesn't re-encode your mp3 files
  • You probably want to enable Settings » Keep date on overwriting source files

Mp3splt-gtk (GUI version, available for all major OS platforms)

  • Download $ start the program, click on Batch & automatic split
  • Select Trim using silence detection and press Batch split

    enter image description here


mp3splt (Command Line version, available for all major OS platforms)

Download mp3splt, open your PowerShell ISE, change both paths and run the following code:

$files = Get-ChildItem "C:\my\musicfolder" -Recurse -Include *.mp3,*.ogg,*.flac
$exe = "C:\path\to\mp3splt.exe"

ForEach ($file in $files) {    
    If ($file.BaseName -notmatch "_trimmed$" ) {        

        $newFile = $file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension
        If (Test-Path $newFile) {Remove-Item $newFile }

        & $exe -r -p "th=-48,min=2" `"$file`" | Out-Null

        Remove $file.Fullname
        Rename $($file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension) $file.Fullname
    }
}

enter image description here

Hints

  • -r -p th=-48, min=2 is the option to remove silence at the start/end of your file. th defines the threshold level in dB. Everything below is considered as silence. min=2 sets the minimum silence in seconds. Only silence longer then 2 seconds will be truncated
  • You could pretend a test run by adding an uppercase -P at the end of mp3splt command. It outputs errors or says everything went well. If used, comment out Remove and Rename since no new files are created to process them
  • For testing, you could also use -d FOLDERPATH to choose a single output folder and -o@f to use the original filename as output (otherwise _trimmed will be appended)

    Documentation explaining all available options


FFmpeg (Command Line version, available for all major OS platforms)

FFmpeg's audio filter -af silenceremove should not be used since it always re-encodes your files and you cannot for gods sake keep the same audio quality as your input file. -acodec copy can not be used here. You can only choose one fixed bit rate even if you process multiple files with different qualities.

However, there is another ffmpeg option: -af silencedetect. The theory is already explained at StackOverflow. I adopted it to Windows and PowerShell.

Download ffmpeg, open your PowerShell ISE, change both paths and run the following code:

$files = Get-ChildItem "C:\path\to\musicfolder" -Recurse -Include *.mp3,*.ogg,*.flac
$ffmpeg = "C:\path\to\ffmpeg.exe"

ForEach ($file in $files) {
    If ($file.BaseName -notmatch "_trimmed$" ) {

        # Detect silence with ffmpeg and "silencedetect". Save the complete output to variable $log
        $log = & $ffmpeg -hide_banner -i `"$file`" -af "silencedetect=duration=1:noise=-50dB" -f null - 2>&1

        $totalLength = [string]$log | where {$_ -match '(?<= Duration:.*)[\d:\.]+' } | % {$matches[0]}        
        $totalLength = ([TimeSpan]::Parse($totalLength)).TotalSeconds

        # Use regex to search all numbers after string "silence_end". Save them as string array in the format XXX.XXX
        # Check if any 'silence_end' was found. If yes, save the first silence ending time as mp3 start time        
        [string[]]$silenceEnd = $log | where {$_ -match '(?<=silence_end: )[-\d\.]+' } | % {$matches[0]}            
        If ($silenceEnd.count -gt 0 -And [double]$silenceEnd[0] -lt $totalLength/2) {
            [double]$trackStart = $silenceEnd[0]
        } else {
            [double]$trackStart = 0
        }

        # Do the same again but for silence starting times. Save the last one as mp3 end time
        [string[]]$silenceStart = $log | where {$_ -match '(?<=silence_start: )[-\d\.]+' } | % {$matches[0]}                
        If ($silenceStart.count -gt 0 -And $silenceStart[$silenceStart.count-1] -gt $totalLength/2) {
            [double]$trackEnd = $silenceStart[$silenceStart.count-1]
        } else {        
            [double]$trackEnd = $totalLength
        } 

        # calculate duration since ffmpeg's -t option wants a duration and not a timestamp
        $duration = $trackEnd - $trackStart

        # Put together the new file name. If file already exists from  previous run, delete it
        $newFile = $file.DirectoryName + "\" + $file.BaseName + "_trimmed" + $file.Extension
        If (Test-Path $newFile) {Remove-Item $newFile }                        

        # Run ffmpeg with our calculated start and duration times to remove silence at start and end
        write-host "$ffmpeg -i `"$file`" -ss $trackStart -t $duration -acodec copy `"$newFile`"  2>&1"
        & $ffmpeg -i `"$file`" -ss $trackStart -t $duration -acodec copy `"$newFile`"  2>&1

        # Delete the original mp3 file and rename the new mp3 file to the original name
        Remove-Item $file.Fullname   
        Rename-Item $newFile $file.Fullname
    }
}

Tags:

Mp3