Mp3 addiction

I’ve recently developed a tool that helps in keeping your music library clean and organized.

image

It allows you to rename and reorganize all your music library in batch using your mp3 tags.

Of course the tool works best only if your mp3 files have tags complete with all the details such as artist, album, year, track number… 

The script is based on the mp3info gem; this gem can read information and manipulate mp3 tags.

My tool examines all mp3 files contained into base_source_dir folder, it moves them into the base_target_dir folder organizing them following the user defined structure according to dir method and rename files according to filename method. Here’s the code:

#!/usr/bin/env ruby

require 'rubygems'
require 'mp3info'
require 'titleize'
require 'fileutils'
require 'ruby-progressbar'


def base_source_dir
  '/Volumes/Shared/Music/Tmp'
end

def base_target_dir
  '/Volumes/Shared/Music/Temporary'
end

def invalid_character
  Regexp.new('[|/\\<>:"?*;,^]')
end

class Mp3
  attr_accessor :source_path, :artist, :album, :title, :year, :track_n, :disc_n

  def initialize(path)
    @source_path = path
    get_metadata
  end

  def self.all
    Dir.glob("#{base_source_dir}/**/*.mp3").map do |path|
      new(path)
    end
  end

  def filename
    "#{escape(artist)} - [#{year}] #{escape(album)} - #{leading_0(disc_n)}.#{leading_0(track_n)} - #{escape(title)}.mp3"
  end

  def dir
    "#{escape(artist)}/[#{year}] #{escape(album)}"
  end

  def target_dir
    "#{base_target_dir}/#{dir}"
  end

  def target_path
    "#{target_dir}/#{filename}"
  end

  private

  def get_metadata
    Mp3Info.open(source_path) do |mp3info|
      @artist  = mp3info.tag.artist
      @album   = mp3info.tag.album.titleize
      @title   = mp3info.tag.title.titleize
      @year    = mp3info.tag.year || mp3info.tag1.year || mp3info.tag2.TDRC
      @track_n = mp3info.tag.tracknum || 1
      @disc_n  = mp3info.tag2.disc_number || 1
    end
  end

  def escape(tag)
    tag.gsub(invalid_character, '_')
  end

  def leading_0(tag)
    sprintf '%02d', tag
  end
end

class Mp3Renamer
  attr_accessor :source_path, :target_path, :target_dir

  def initialize(mp3)
    @source_path = mp3.source_path
    @target_dir = mp3.target_dir
    @target_path = mp3.target_path
  end

  def perform
    prepare_folder
    FileUtils.mv(source_path, target_path)
  end

  private

  def prepare_folder
    FileUtils.mkdir_p target_dir
  end
end

mp3s = Mp3.all
bar = ProgressBar.create total: mp3s.count

FileUtils.mkdir_p base_target_dir
mp3s.each do |mp3|
  Mp3Renamer.new(mp3).perform
  bar.increment
end
puts "#{mp3s.count} mp3 processed!"

Here’s my organization method, enjoy your listening!

image

Leave a Reply

wpDiscuz