Editing Media Tags from PowerShell

This started out as a question on the #PowerShell IRC channel (irc.freenode.net) about how to edit tags on mp3 files, but we quickly discovered TagLib# (formerly under Novell, currently maintained on github by the Banshee project), which lets you access and edit tags on not only mp3s, but on everything from asf and avi to wma and wav and even includes supports for DIVX and FLAC and MovieID tags on top of ID3, etc.

Using TagLib# is pretty simple. Once you load the library, you can create a TagLib file record, view or edit the tags, and then save the changes back to the file:


[Reflection.Assembly]::LoadFrom( (Resolve-Path ".\taglib-sharp.dll") )
$media = [TagLib.File]::Create("C:\Users\Joel\Music\Audity\The Language I Think In-Music of My Heart.ogg")
# Write out the current album name
$media.Tag.Album
# Set the album name to the name of the directory
$media.Tag.Album = ([IO.FileInfo]$media.Name).Directory.Name
# Save the new album name into the file
$media.Save()

In my obsession to completely explore these sorts of things even though I don’t actually care for myself, I wrote a Add-MediaInfo filter which you can take and use if you like. It adds all of the properties in “Tag” and “Properties” to each object which matches the file extensions filter, prefixing them with the word “Media” to avoid naming conflicts. You’ll need to have the TagLib# assembly loaded (maybe put that in your Profile script).


filter Add-MediaInfo([switch]$editable)
{
   if( ($_ -is [IO.FileSystemInfo]) -and
       (@(".asf",".avi",".flac",".m4a",".m4p",".m4v",     `
       ".mp+",".mp3",".mp4",".mpc",".mpe",".mpeg",".mpg", `
       ".mpp",".mpv2",".ogg",".wav",".wma",".wmv",".wv") -notcontains $_.Extension ))      
   {
      Write-Output $_
   } else {
      $file = $_
      $taglib = [TagLib.File]::Create($file.FullName)
     
      if(!$mitags) {      
         $mitags = gm -in $taglib.Tag -member Property | %{$_.Name}
         $miprops = gm -in $taglib.Properties -member Property | %{$_.Name}
      }
      foreach( $tag in $mitags) { # Add the tag sub-properties
         Add-Member -inputObject $file -MemberType "NoteProperty" -Name "Media$tag" -Value $taglib.Tag."$tag"
      }
      foreach( $tag in $miprops) { # Add the property sub-properties
         Add-Member -inputObject $file -MemberType "NoteProperty" -Name "Media$tag" -Value $taglib.Properties."$tag"
      }
      if($editable) {
         # Add the TagLib object as a "MediaTags" property.  
         # You can use that to EDIT the tags, instead of just reading them...
         Add-Member -inputObject $file -MemberType "NoteProperty" -Name "MediaTags" -Value $taglib -passthru
      } else {
         Write-Output $file
      }
   }
}

If you pass the switch parameter (-editable), it also puts the TagLib object into the file as “MediaTags”, which you can use to edit the tags, since you can’t actually edit and save NoteProperty values. I have a couple ideas for next steps, and if anyone does anything with this, I’d love to see it:

  1. You could create a format file with “views” for different types of media to display the best properties
  2. You could write a script which would take the appended FileInfo objects and get the data off and save it.
  3. You could invert the action: instead of annotating the FileInfo, copy the FileInfo properties to the TagLib.File object
  1. You could create a type file for the TagLib.File object which could specify script or code properties which would show the FileInfo information, and then just output the plain TagLib.File object instead of adding properties in script.

    Similar Posts:

  • Creating PowerShell Modules, the easy way.
  • A new way to zip and unzip in PowerShell 3 and .Net 4.5
  • Get-Help for Modules you don’t have installed
  • PowerShell PowerUser Tips: The Hash TabExpansion

  • One thought on “Editing Media Tags from PowerShell”

    1. I had a bunch of mp3 files that did not have the artist or song title marked on the file (correctly). All the file names came over CollectionTrack#-Artist-SongTile (eq: 001 – Led Zeppelin – Stairway To Heaven). Here is the code that I used to label this files correctly. This would have a problem for files that have “-” somewhere in the artist or song title. But it worked well enough.

      [Reflection.Assembly]::Load(“taglib-sharp, Version=2.0.3.0, Culture=neutral, PublicKeyToken=db62eba44689b5b0”)
      cd F:\Music\500Rock
      foreach ($f in dir)
      {
      $media = [TagLib.File]::Create(“F:\Music\500Rock\” + $f.ToString())
      $newName = $f.Name
      $splitName = $newName.Split(”-”)

      $i = 1

      foreach($p in $splitName)
      {
      switch ($i)
      {
      2{$media.Tag.Performers= $p.ToString()}
      3{$media.Tag.Title= $p.ToString()}
      }
      $i++
      }
      $media.Tag.Album = “”
      $media.Save()
      Rename-Item $f -NewName ($splitName2.ToString())
      }

    Comments are closed.