2012年5月20日日曜日

[Ruby] iTunes - ディレクトリ構成から、MP3タグを更新

転んでもただでは起きないよw


2012年05月16日水曜日 に音楽ファイルが消えてしまったけど、復元はできた。 
復元できたファイルは、曲名が復元できなかったので整理は後回し。 

MP3タグを付けてない音楽ファイルは別のHDDに入っていたので無事だったので、 
消えた音楽ファイルの場所にファイルを同期。 
ファイル名は元通り。ただMP3タグは付いてない。。。

MP3タグ付けは気の遠くなる作業で、さらに気が遠くなる。。。それを考えると・・・orz
そうだ!自動化だ! と思い、昨日1日調査と実装してました。 

因みに言語は、Rubyです。 

取りあえず、完成しました。 

以下で動作確認済みです。
・Windows 7 Professional 64bit
・Ruby 1.9.3p194
・iTunes 10.6.1.7

曲名、トラック番号、アルバム名、グループのタグ付けをファイルパスからMP3タグを付けるようなプログラムを作りました。 
こんなディレクトリ構成しているのは、きっと珍しいから、たぶんこのコードは使えないと思います。

一応、参考になればと思い、コードを以下に公開しておきます。

※2012/05/22更新
iTunes_mp3tag_update.rb
# -*- encoding: utf-8 -*-
# -------------------------------------------------------------------------------
# iTunes_mp3tag_update.rb
# iTunes - ディレクトリ構成によって、MP3タグを更新。
# 更新するMP3タグ : 曲名、トラック番号、アルバム名、グループ名
# (c) 2012 shiro
#
# 動作確認済み:
#   Windows 7 Professional 64bit
#   Ruby 1.9.3p194
#   iTunes 10.6.1.7
#
# ex) 以下のようなディレクトリ構成で有効です。
# Music/
# ├ グループ名2
#    ├ 01.アルバム名1
#    | ├ 01.曲名1.mp3
#    | └ 02.曲名2.mp3
#    └ 02.アルバム名2
#       ├ DISC-1
#       | ├ 01.曲名3.mp3
#       | └ 02.曲名4.mp3
#       └ DISC-2
#          ├ 01.曲名5.mp3
#          └ 02.曲名6.mp3
# -------------------------------------------------------------------------------

require 'win32ole'
require 'pathname'

class String
  # 半角記号だとフォルダ名、ファイル名に使用できない文字を半角文字に変換
  def normalize
    self.tr("&%}{#|><”?*:/","&%}{#|><\"?*:/").tr("¥","\\")
  end
end

# 音楽ファイル
ITTrackKindFile = 1
# 変更された曲数
modify_count = 0
# 例外数
exception_count = 0
exception_text = []
# 削除数
deleted_tracks = 0

# iTunes 初期化
itunes_app  = WIN32OLE.new("iTunes.Application")
# メインライブラリ
playlist = itunes_app.LibraryPlayList
# 特定のプレイリスト
#playlist = itunes_app.LibrarySource.Playlists.ItemByName("無題のプレイリスト")
start_time = Time.now

begin
  # プレイリスト内のトラックを取得
  tracks = playlist.Tracks

  if playlist
    #プレイリスト中の曲数
    num_tracks = tracks.Count

    num_tracks.downto(1) do |i|
      track = tracks.Item(i)
      begin
        if track.Kind == ITTrackKindFile
          if track.Location == ""
            # デッドリンク削除
            track.Delete()
            deleted_tracks += 1
          else
            # 変更フラグ
            modify_flag = false

            # 曲名取得
            track_name = track.Name
            # ファイル場所取得
            path = Pathname.new(track.Location)

            # 曲名更新
            file_name = path.basename(".mp3").to_s
            song_name = file_name.gsub(/^\d\d(|\d)\./,"").encode("utf-8").normalize

            if /^\d\d(|\d)\./ =~ track_name && file_name == track_name || track_name.encode("utf-8") != song_name
              p "Before Name : #{track.Name}"
              p "After Name : #{song_name}"
              # iTunesの自動補完機能対応
              track.Name = "#{song_name}_dummy".upcase
              # 曲名を変更
              track.Name = song_name
              modify_flag = true
              p "Name Updated."
            end

            # トラック番号更新
            file_name =~ /^\d\d(|\d)\./
            track_number = $&.to_i
            tn = track.TrackNumber
            if tn == 0 || tn != track_number
              # トラック番号を変更
              track.TrackNumber = track_number
              modify_flag = true
              p "TrackNumber Updated."
            end

            album_name = ""
            album_path = nil
            if /^[Dd][Ii][Ss][Cc]-\d(|\d)/ =~ path.dirname.basename.to_s
              # 複数ディスクの場合
              disc_path = path.dirname
              album_disc = disc_path.basename.to_s.upcase
              album_path = disc_path.dirname
              album_name = "#{album_path.basename.to_s.gsub(/^\d\d\./,"")} #{album_disc}".encode("utf-8").normalize
            else
              # 複数ディスクでない場合
              album_path = path.dirname
              album_name = album_path.basename.to_s.gsub(/^\d\d\./,"").encode("utf-8").normalize
            end

            # アルバム更新
            album = track.Album
            if album  == "" || album.encode("utf-8") != album_name
              # iTunesの自動補完機能対応
              track.Album = "#{album_name}_dummy".upcase
              track.Album = album_name
              modify_flag = true
              p "Album Updated."
            end

            # グループ更新
            circle = track.Grouping
            circle_name = album_path.parent.basename.to_s.encode("utf-8").normalize
            if circle == "" || circle.encode("utf-8") != circle_name
              # iTunesの自動補完機能対応
              track.Grouping = "#{circle_name}_dummy".upcase
              track.Grouping = circle_name
              modify_flag = true
              p "Grouping Updated."
            end

            # 更新した場合は、曲のファイルパスをコンソールに出力
            if modify_flag
              modify_count += 1
              p "#{path.to_s} updated!"
#              File.open('updated.log','a'){|f|
#                f.write "#{path.to_s}\n"
#              }
            end
          end
        end
      rescue => e
        exception_count += 1
        exception_text << "#{track.Location} : #{e}"
      end
    end
  end
  p "#{modify_count} updated!"
  if exception_count > 0
    exception_text.each do |exception|
      p exception
    end
    p "#{exception_count} exceptions."
  end
  if deleted_tracks > 1
    p "#{deleted_tracks} files deleted."
  elsif deleted_tracks == 1
    p "1 file deleted."
  end
  p "Processing has been completed!"
rescue NoMethodError => e
  p e
  p "No playlist!"
rescue WIN32OLERuntimeError => e
  p e
  p "WIN32OLERuntimeError"
ensure
  finish_time = Time.now
  p "start time : #{ start_time }"
  p "finish time : #{ finish_time }"
  p "#{finish_time - start_time} sec."
end

参考URL

2012年5月17日木曜日

[雑談] 2012年05月16日水曜日は最悪な日となりました。

音楽ファイルが全て消えた日。。。

頑張ってMP3タグ付けしていた苦労が一気に水のあわになった日



2012年05月16日水曜日 この日は忘れない日となったorz



簡単に説明すると、

Linuxの某音楽プレイヤーで読み込まれてる曲のリストを削除したつもりが、音楽ファイルが削除されたorz


現在は、復元作業は完了したが、ファイル名やフォルダ情報が失われた。。。

焦って、すぐに復元作業したことを、物凄く後悔しています><


復元に使用したのが「PhotoRec」

復元作業を開始してすぐに知ったことだけど、ファイル名が復元されない。。。
もうちょっと慎重に復元ソフトを選んでいれば、こんなことにならなかったと思います。



ただ、削除された曲数がかなり多かったので、冷静でいられなかった。。。


バックアップを怠っていたのも自分の責任。誰も責めれない。
でも、某音楽プレイヤーには文句を言いたい!インターフェイスがが使いづらいよ!!!

2012年5月6日日曜日

[雑談] 備忘録

Sqlite3とPostgreSQL

gem install sqlite3 でエラーが出た。

$ sudo apt-get install -y sqlite3 libsqlite3-dev
で解決できた。
エラー内容が依存関連だった。

gem install pg でエラーが出た。

$ sudo apt-get install -y postgresql-8.4 postgresql-server-dev-8.4
で解決できた。
同じく依存関連のエラーでした。

でも、インストール時に
「postgresql-8.4」は使われなくなります!って警告された。。。


取り敢えず、両方解決できた。