MP3の「曲の長さ」を調べる


お気に入りのMP3を何曲か集めて音楽CDを焼くようなとき、演奏時間が全部で何分になるかを事前に知りたい場合があります。他の人はどうだか知りませんが、私にはあります。もちろん、そうした情報を提供してくれるフリーソフトなどはたくさんあるでしょうけど、できればチャチャっと、自分で簡単に調べられたら幸せです。

そうした情報は、MP3ファイルの末尾や先頭に記録されているのは知っていましたし、適当に当たりをつけて力わざで抜き出そうかとも思いました。しかし、WSHを使うと簡単に取得できるのを発見したので(備忘録として)書いておきます。そのうち、使いやすいUIを作るかもしれませんが、とりあえずはExcelのシートに出力するVBAサンプルです。ExcelのGetOpenFilenameメソッドを使っていますので、VB6では動きません。

Sub Sample1()
    Dim FSO As Variant, SHell As Variant, Folder As Variant
    Dim Songs As Variant, i As Long, Target As String
    Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True)
    If Not IsArray(Songs) Then Exit Sub
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set SHell = CreateObject("Shell.Application")
    Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)
    For i = 1 To UBound(Songs)
        Target = FSO.GetFile(Songs(i)).Name
        Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0)
        Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21)
    Next i
    Set Folder = Nothing
    Set SHell = Nothing
    Set FSO = Nothing
End Sub

思いのほか長くなったので、ちょっと解説します。

最初の2行は変数の宣言。これはいいですね。

  Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True)

  If Not IsArray(Songs) Then Exit Sub

は、MP3ファイルを選択するところです。MultiSelect:=Trueで複数選択可にしていますので、[キャンセル]ボタンがクリックされたかどうかは、返り値が配列かどうかで見ています。

続く

  Set FSO = CreateObject("Scripting.FileSystemObject")

  Set SHell = CreateObject("Shell.Application")

  Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)

は、オブジェクト(インスタンス)の生成です。最初のFSOは、おなじみのFileSystemObjectです。今回のメイン処理である「MP3のタグ情報」は、WSHのShellオブジェクトを使います。それが、CreateObject("Shell.Application")です。

「MP3のタグ情報」は、MP3ファイルを右クリックして[プロパティ]を実行し、表示される[○○のプロパティ]ダイアログボックスの[概要]タブで確認することができます。

この[概要]タブの情報を取得するには、WSHのShellオブジェクト配下にある、FolderオブジェクトのGetDetailsOfメソッドを使います。たとえば「C:\Music」フォルダにある「001.mp3」というMP3ファイルのタグ情報を取得したいときは、次のようにします。

C:\Musicを示すFolderオブジェクト.GetDetailsOf(001.mp3を示すFolderItemオブジェクト, _
                                                                        タグ情報の番号)

任意のFolderオブジェクトを取得するには、ShellオブジェクトのNamespaceメソッドを使って、たとえば次のようにします。

Set Folder = SHell.Namespace("C:\Music")

今回は、GetOpenFilenameメソッドの返り値を利用しますので、[ファイルを開く]ダイアログボックスで選択されたフォルダのパス名を、Namespaceメソッドの引数にしてやります。[ファイルを開く]ダイアログボックスで選択されたファイルは「C:\Music\001.mp3」のようにフルパスが返りますから、FSOを使ってパスだけを抜き出しました。

Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)

もしかすると、他にもっと良い手があるかもしれませんが、とりあえず今回はこれで。

以上の処理を除いて、実際にタグ情報を取得しているのが下記の部分です。

Sub Sample1()
    Dim FSO As Variant, SHell As Variant, Folder As Variant
    Dim Songs As Variant, i As Long, Target As String
    Songs = Application.GetOpenFilename(FileFilter:="MP3ファイル,*.mp3", MultiSelect:=True)
    If Not IsArray(Songs) Then Exit Sub
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set SHell = CreateObject("Shell.Application")
    Set Folder = SHell.Namespace(FSO.GetFile(Songs(1)).ParentFolder.Path)
    For i = 1 To UBound(Songs)
        Target = FSO.GetFile(Songs(i)).Name
        Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0)
        Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21)
    Next i
    Set Folder = Nothing
    Set SHell = Nothing
    Set FSO = Nothing
End Sub

選択されたMP3ファイル群は、配列Songsに格納されています。

  For i = 1 To UBound(Songs)

で、順番に選択されたファイルを取り出します。

配列Songsに格納されているのは「C:\Music\001.mp3」のようにパスを含んでいますので、

  Target = FSO.GetFile(Songs(i)).Name

とファイル名(だけ)を取得して、変数Targetに格納します。

変数Targetは、このままでは単なる文字列ですから、

  Folder.ParseName(Target)

として、FolderItemオブジェクトに変換します。

MP3ファイルのタグ情報のうち「ファイル名」を表すヘッダ番号は「0」で、「曲の長さ」を表すヘッダ番号が「21」ですので、

        Cells(i, 1) = Folder.GetDetailsOf(Folder.ParseName(Target), 0)
        Cells(i, 2) = Folder.GetDetailsOf(Folder.ParseName(Target), 21)

として抜き出しています。

※Windows Vistaではヘッダ番号が異なります。ヘッダ番号を調べる方法は、このページの最後に追記します。

上の実行結果画面では、SUM関数で合計時間を計算していますが、それは手で入力した方が簡単なのでコード化していません。ツールバーの[オートSUM]ボタンを押したときのように、自動的にSUM関数を入力するには、Alt+Shift+「=」キーを押します。同様に、前回の出力結果をクリアする処理も手動としました。Ctrl+Shift+「*」キーを押して全体を選択してDeleteキーを押せば済みますからね。

ちなみに、GetDetailsOfメソッドを使うと、MP3のタグ情報だけでなく、ファイルの「作成者」や「更新日時」などを取得できますし、画像ファイルでしたら「カメラの名前」や「画像の大きさ」なども取得できます。要するに、エクスプローラの[表示]-[詳細]で表示される情報を取得できるわけですね。

(追記)

このマクロ、便利に使っていたのですが、Windows Vistaで実行したら演奏時間を取得できませんでした。Windows XPに比べて、Windows Vistaはフォルダに表示できる詳細表示情報が変更になったようです。調べてみたら、写真関係や、プロフィール関係などの詳細が、ずいぶん追加されていました。

すべてのヘッダ番号を調べるには次のようにします。なお、演奏時間を表す「長さ」のところで、MsgBoxを出すようにしています。

Sub Sample2()
    Dim objShell, objFolder, i As Long
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.Namespace("C:\")
    For i = 0 To 1000    ''十分に大きい数字
        Debug.Print i, objFolder.GetDetailsOf("", i)
        If objFolder.GetDetailsOf("", i) = "長さ" Then MsgBox "長さ:" & i
    Next i
    Set objFolder = Nothing
    Set objShell = Nothing
End Sub

ヘッダのタイトルを取得するには、GetDetailsOfメソッドの第1引数に「""」を指定します。ネットで調べた情報では「Nullを指定する」と書かれていたものもありました。Excel VBAでは、とりあえず「""」で正常に動作しましたが、VBなどから実行して取得できないときは、vbNullやNothingなども試してください。

ちなみにWindows Vistaで演奏時間を取得するには、ヘッダ番号「27」を指定します。