今回は、フリーのMP3タグ編集用クラスライブラリをC#で使うための方法について解説します。
TagLibで検索すると、いくつかのサイトが表示されますが、簡単な説明とサンプルプログラムだけ紹介されていることが多く、実際使った時に起きる文字化けの対応方法がほとんど記載されていません。
ここでは、TagLibの使い方と文字化けの対策についても解説しています。
TagLibはMP3タグが編集できるフリーのクラスライブラリ
MP3タグを編集する方法として、以下の方法が考えられます。
- タグ情報が格納されている部分を直接編集
- OS標準の「Shell32.dll」を使ってファイルのプロパティを編集
- フリーのクラスライブラリ「TagLib」などを使ってタグを編集
このうち、1はタグの内容がいくつかのバージョンで異なるため、それらを考慮する必要があり、難易度は高めです。
2についてはファイルのタグ情報にMP3タグが含まれているようなイメージで、MP3タグが保存されている場所とは違う場所に格納されているようです。
また、「Sell32.dll」を使ってファイルのタグ情報を変更する方法が見つかりませんでしたので、編集するという事に関しては現時点でこの方法は使えません。
3はMP3タグの読み書きが簡単に行えるので、現時点での選択しはこの方法オンリーになります。
特に「TagLib」は簡単にMP3タグの編集が出来るクラスライブラリとして広く使われていて、安心感があります。
ただ、日本語の場合は文字化けすることがあるので、この点だけ対策が必要です。
インストール方法
TagLib は Visual StudioのNuGetから簡単に自分のプロジェクトに取り込むことが出来ます。
具体的には、Visual Studio のパッケージ管理機能 NuGetとは? の記事に記載していますが、以下の様に画面をクリックしていくことで、インストール(自分のプロジェクトへの取り込み)が行えます。


タグの読み出し
まず、静的クラスである Taglib.FileクラスのCreate メソッドを呼んで、TagLib.Fileクラスのインスタンスを生成します。
1 |
TagLib.File mp3 = TagLib.File.Create(filename); |
以降は、インスタンスのプロパティを通して、MP3タグにアクセスできます。

主なタグは次の様に記述することで取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
TagLib.File mp3 = TagLib.File.Create(@"d:\Boyfriend (Moonlight Version).mp3"); Debug.WriteLine(mp3.Tag.Title); //タイトル Debug.WriteLine(string.Join(";", mp3.Tag.Artists)); //アーティスト Debug.WriteLine(string.Join(";", mp3.Tag.AlbumArtists)); //アルバムアーティスト Debug.WriteLine(mp3.Tag.Album); // アルバム Debug.WriteLine(string.Join(";", mp3.Tag.Composers)); //作曲家 Debug.WriteLine(mp3.Tag.Year); // 年 Debug.WriteLine(mp3.Tag.Track); //トラック番号 Debug.WriteLine(mp3.Tag.Disc); //ディスク番号 Debug.WriteLine(string.Join(";", mp3.Tag.Genres)); //ジャンル Debug.WriteLine(string.Format("{0:D2}:{1:D2}:{2:D2}", mp3.Properties.Duration.Hours, mp3.Properties.Duration.Minutes, mp3.Properties.Duration.Seconds)); // 再生時間 Debug.WriteLine(mp3.Properties.AudioBitrate); //ビットレート Debug.WriteLine(mp3.Tag.TagTypes); //タグのタイプ Debug.WriteLine(mp3.Tag.Comment); //コメント |
以下は主なタグ名とTagLibのプロパティの対応表です。
実際にはこれ以外にもありますが、ほとんど馴染みがないものばかりです。
MP3タグの名前 | 型 | 対応するプロパティ名 |
---|---|---|
タイトル | string | Title |
アーティスト | string[] | Artists |
アルバムアーティスト | string[] | AlbumArtists |
アルバム名 | string | Tag.Album |
作曲家 | string[] | Composers |
年 | uint | Year |
トラック番号 | uint | Track |
ディスク番号 | uint | Disc |
ジャンル | string[] | Genres |
長さ(再生時間) | TimeSman | Properties.Duration |
ビットレート(Kbps) | int | Properties.AudioBitrate |
タグ | string | TagTypes |
コメント | string | Comment |
ちなみに、TagLibの長さ(再生時間)やビットレートについては、正しく取得できない場合がありました。
たとえば、5分の曲が30分で表示されたり、128kbps が 32kbps で表示されるようなパターンです。
エクスプローラーからファイルを右クリックしてプロパティを表示してみると、そちらは正しく表示されていました。
有名どころのMP3編集ソフトとTagLibの取得結果は同じだったので、そもそもMP3タグの値がおかしいのだろうと思います。
MP3に埋め込まれた画像の取得
MP3には画像を埋め込むことが出来ますが、その画像は Tag.Pictureプロパティにバイト配列(byte[])で格納されています。
PictureBoxコントロールを用いて画面に表示するには Image 型に変換する必要がありますが、それはFromStream メソッドを使います。
1 2 |
var bin = (byte[])(mp3.Tag.Pictures[0].Data.Data); Image img = Image.FromStream(new MemoryStream(bin)) |
尚、画像は複数格納できるように配列型になっているため、Length プロパティを使って画像が埋め込まれているかを判定できます。
以上のことを踏まえ、画像が埋め込まれている時のみ pictureBox1 に画像を表示するサンプルは次の様になります。
1 2 3 4 5 |
if (mp3.Tag.Pictures.Length >= 1) { var bin = (byte[])(mp3.Tag.Pictures[0].Data.Data); pictureBox1.Image = Image.FromStream(new MemoryStream(bin)).GetThumbnailImage(200, 200, null, IntPtr.Zero); } |
埋め込まれている画像は必ずしも小さな画像とは限らないため、サンプルでは縦横200ドットのサムネイルを作成し、それをpictureBox1.Image に渡しています。
サムネイルを作成せず、pictureBox1のSizeModeプロパティを使って適切なサイズ時自動縮小して表示する方法もあります。
1 2 3 4 5 6 |
if (mp3.Tag.Pictures.Length >= 1) { var bin = (byte[])(mp3.Tag.Pictures[0].Data.Data); uxImage.SizeMode = PictureBoxSizeMode.Zoom; uxImage.Image = Image.FromStream(new MemoryStream(bin)); } |
タグの書き込み
タグの書き込みは、読み込みと同様 Createメソッドで Fileクラスを作成し、Tagクラスのプロパティに値を設定していき、最後に Saveメソッドを呼ぶだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
TagLib.File mp3 = TagLib.File.Create(@"d:\Boyfriend (Moonlight Version).mp3"); mp3.Tag.Title = "Boyfriend"; mp3.Tag.Artists = "Flower"; mp3.Tag.AlbumArtists = new string[]{"Flower"}; mp3.Tag.Album = "THIS IS Flower THIS IS BEST"; mp3.Tag.Composers = ""; mp3.Tag.Year = 2016; mp3.Tag.Track = 6; mp3.Tag.Disc = 1; mp3.Tag.Genres = new string[]{"JPop"}; mp3.Tag.Comment = "Flowerベストアルバム"; //mp3ファイルにタグを書き込む mp3.Save(); |
MP3ファイルへの画像の埋め込み
Pictureクラスのコンストラクタにimageデータを渡すことで、TagLibで取り扱えるデータに変換できます。
それを TagクラスのPictures プロパティに配列形式で渡した後、Saveメソッドを呼ぶだけで埋め込むことが出来ます。
1 2 3 4 |
TagLib.IPicture picture = new TagLib.Picture(image); mp3.Tag.Pictures = new TagLib.IPicture[] { picture }; mp3.Save(); |
文字化けの対応
さて、TagLibで一番問題になるのは漢字の文字化けです。
文字化けする場合としない場合があるのですが、これはMP3タグのバージョンによって文字コードが異なることと、その規則を無視してシフトJISを書き込んでしまうMP3エンコーダーが横行していることが原因のようです。
理由はともかく、私が試したところによるとTagLibで正しく日本語が表示される場合と文字化けする場合があったので、それを解決する手段を思考錯誤しました。
最終的にたどり着いたのが次のソースコードになります。
有名どころのMP3タグ編集ソフトで表示される結果と、この方法で変換した結果を約1000ファイルに渡って比較したところ、両者は一致したので、おそらくこれが正解なんだろうと勝手に思ってます。
考え方としては、元の文字列をシフトJISと仮定して一旦バイト列に変換後、再びシフト列に変換してあげると、もしシフトJISであったなら元の文字列に戻るはずです。
この考え方を使ってシフトJISか否かを判断し、シフトJISでなければシフトJISに変換してあげるという事をやっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
private string UTF2Jis(string str) { //指定された文字列が null なら、空の文字列を返す if (str == null) { return ""; } //Shift-JISのエンコーディングを取得 var enc = System.Text.Encoding.GetEncoding("shift-jis"); //取得したエンコーディングを使って引数ををバイト列に変換後、再びShift-JISの文字列に変換 string cnv_str = enc.GetString(enc.GetBytes(str)); //上記の変換結果と引数を比較し、異なればShift-JISではないと判断 if (str != cnv_str) { //引数をShift-JISに変換 var l_bytes = System.Text.Encoding.Unicode.GetBytes(str); //Unicodeにバイト列に変換すると1バイト毎に0x00 が付加されるため、0x00を取り除いてShift-JISに変換 return System.Text.Encoding.GetEncoding("shift-jis").GetString(l_bytes.Where(i => i > 0).ToArray<byte>()); } return str; } |
シフトJISに変換する際、一旦バイト列に変換する必要があるのですが、その時1バイトごとに0x00が付加されていますので、これを取り除いています。
私はMP3タグについて詳しく無いので、何故こうなるか理由は分かりませんので、もし分かる方がいれば是非教えて頂きたいと思います。
Shell32.dllを使ったタグの読み出し
最後にオマケとして、Shell32.dll を使ったタグの読み出しだけメモ書きとして記載しておきます。
Google検索して見つけた内容なので、原文はこちらの記事をご覧下さい。
方法は、Shell32.dll をプロジェクト参照してから、数行プログラムを書くことで、プロパティが取得できます。
参照設定の方法
Visual Studio のソリューションエクスプローラーから、「参照」→「参照の追加」→「参照マネージャ」→「COM」と選択していきます。
次に、「Microsoft Shell Controls And Automation 」を探してチェックを入れ、「OK」ボタンをクリックすると完了です。

「参照」の一覧に Sell32 が表示されたと思いますので、これをクリックし、「相互運用型の埋め込み」をFalseに設定します。
初期値はTrueなのですが、Trueのままだとエラーになります。

タグ読み出しのソースコード
参照した Shell32 を使ってタグを読み出す方法は次の通りです。
GetDetailsOfメソッドの第2引数にタグ番号を代入すると、そのタグ番号に登録されている値が取得できます。
1 2 3 4 5 6 7 8 9 10 |
//あらかじめ Shell32 のネームスペースを using しておく using Shell32; //事前準備 ShellClass shell = new ShellClass(); Folder folder = shell.NameSpace(フォルダ名); FolderItem item = folder.ParseName(ファイル名); //タグの読み出し folder.GetDetailsOf(item, タグ番号); |
実験的に、0~300までタグ番号を変えて値を取得するプログラムを作って、どんな値が返ってくるのか調べてみました。
0010(タグ番号10)は私の端末名とユーザー名が表示されていたので、あえてボカしました。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
private void button1_Click(object sender, EventArgs e) { string dir = Path.GetDirectoryName(textBox2.Text); string file = Path.GetFileName(textBox2.Text); ShellClass shell = new ShellClass(); Folder folder = shell.NameSpace(dir); FolderItem item = folder.ParseName(file); textBox1.Text = ""; for (int i = 0; i < 300; i++) { var val = folder.GetDetailsOf(item, i); if (val != "") { textBox1.AppendText(string.Format("{0:0##}\t{1}", i, val) + Environment.NewLine); } } } |
原文にもタグ番号と内容の一覧が記載されていますが、WindowsXP時代のもののようで、Windows10の場合は次の様になりました。
タグ番号 | 内容 |
---|---|
0 | ファイル名 |
1 | ファイル容量 |
2 | MP3 形式サウンド |
3 | 更新日時 |
4 | 作成日時 |
5 | アクセス日時 |
9 | ファイルの種類(オーディオ、ビデオ等) |
10 | 所有者 |
11 | 音楽 |
13 | アーティスト |
14 | アルバム名 |
15 | 年 |
16 | ジャンル |
19 | 評価なし |
20 | アーティスト |
21 | タイトル |
24 | コメント |
26 | トラック番号 |
27 | 長さ(再生時間) |
28 | ビットレート |
194 | フルパス |
196 | ファイル形式(MP3 形式サウンド、MP4ファイルなど) |
215 | サブタイトル |
237 | アルバムアーティスト |
243 | 作曲家 |
248 | 雰囲気 |
249 | ディスク番号 |
まとめ
以上でTagLibの説明は終わりです。
TagLibを使う事で、簡単にMP3タグを編集することができます。
有名どころのフリーツールにせよ、TagLibにせよ、文字化けする時は文字化けしますので、100%完全という訳ではありませんが、十分使えるクラスライブラリなので、もし使う機会が有れば、是非この記事を参考にして頂ければと思います。