powershell script to find bitrate for MP3 M4A FLAC audio files

May 30, 2022
26
0
I’m working on a powershell script to create a list of all of my mp3 and m4a files, complete with bitrate. I have a really large amount of music files, but some of them are at low bitrates (like 128k). And there are a lot of duplicates. In the case of duplicates, I want to be able to pick out the one with the best bitrate.



I found some code online which would do the job, but it was a bit slow. Finding the bitrate for 80k files took about 31 minutes.
Code:
$s = Get-Date
del files3.ps1.txt
$shellObject = New-Object -ComObject Shell.Application
$bitrateAttribute = 0

# Find all mp3 files under the given directory
$mp3Files = Get-ChildItem -recurse -file -include *.mp3,*.m4a,*.wav,*.flac,*.ape
foreach( $file in $mp3Files ) {
    # Get a shell object to retrieve file metadata.
    $directoryObject = $shellObject.NameSpace( $file.Directory.FullName )
    $fileObject = $directoryObject.ParseName( $file.Name )

    # Find the index of the bit rate attribute, if necessary.
    for( $index = 5; -not $bitrateAttribute; ++$index ) {
      $name = $directoryObject.GetDetailsOf( $directoryObject.Items, $index )
      if( $name -eq 'Bit rate' ) { $bitrateAttribute = $index }
    }

    # Get the bit rate of the file.
    $bitrateString = $directoryObject.GetDetailsOf( $fileObject, $bitrateAttribute )
    echo "$file $bitrateString" >> files3.ps1.txt
}
$e = Get-Date
$elapsed = ($e - $s).TotalSeconds
echo "Time $elapsed Seconds"

I was able to speed things up quite a bit by eliminating the code for "#Find the index of the bit rate attribute". In my case, the index is always 28, and just hardwiring that cut my time from 31 minutes down to right at 10 minutes.

This is where I'm at now:
Code:
$s = Get-Date
del files3.ps1.txt
$shellObject = New-Object -ComObject Shell.Application
$bitrateAttribute = 0

# Find all mp3 files under the given directory
$mp3Files = Get-ChildItem -recurse -file -include *.mp3,*.m4a,*.wav,*.flac,*.ape
foreach( $file in $mp3Files ) {
    # Get a shell object to retrieve file metadata.
    $directoryObject = $shellObject.NameSpace( $file.Directory.FullName )
    $fileObject = $directoryObject.ParseName( $file.Name )

    # Get the bit rate of the file.
    $bitrateString = $directoryObject.GetDetailsOf( $fileObject, 28 )
    [string]$str1 = $bitrateString
#   remove first character, which is u200e, which is the "left-to-right" unicode char
    $str2 = $str1.substring(1)
    echo "$file $str2" >> files3.ps1.txt
}
$e = Get-Date
$elapsed = ($e - $s).TotalSeconds
echo "Time $elapsed Seconds"