mutagenでMP3のヘッダデータ中のコメントを編集して保存する

chosic.comというサイトでフリーの音源を漁るのが好きです。soundcloudなどで活動する人が投稿してくれて自分好みの曲が多いのでよく使っています。。

ダウンロードした楽曲がどういう条件で使えるのかわかるようにしておくために、再生ソフトでmp3ファイルのヘッダデータ中のコメントデータをちまちまと編集してメモするのですが、これをPython使ってもう少しシンプルな作業にしたいと思いました。

MP3ヘッダを扱えるmutagenというライブラリがあるのですが、メディアファイル全般を扱える結構汎用的なライブラリでちょっと複雑だったのでメモしときます。

コメントの読み出し: id3クラスを使います。ディクショナリ形式でアクセスができます。ここまでは結構いろんなサイトでも解説されていると思います。

from mutagen import id3

#...中略....

try:
    audio = id3.ID3(args.mp3file) #args.mp3fileにはファイル名を入れてね。
except id3._util.ID3NoHeaderError:
    print(f"{args.mp3file}にはヘッダがありません。")
    exit()

printf(audio["COMM::eng"][0])

コメントの書き出しと保存:string型のデータを直接”COMM:eng”に渡すのではなく、id3クラスのCOMMメソッドを使ってコメントデータを生成して渡します。ここで、langという引数を設定するのと、コメントテキストは配列で与えること。ここがなかなか調べても出てこなかった。最後はsaveメソッドです。

from mutagen import id3

#...中略...

try:
    audio = id3.ID3(args.mp3file)
except id3._util.ID3NoHeaderError:
    print(f"{args.mp3file}にはヘッダがありません。作成します。")
    audio = id3.ID3()

comment = "この楽曲はアメリカ中西部の原住民のスタイルを踏襲しています。"

if "COMM::eng" in audio:
     audio['COMM::eng'] = id3.COMM(encoding=3, lang='eng',text=[comment])
audio.save(args.mp3file)
print(f"書き込まれたデータは:\n{audio['COMM::eng'][0]}")

ディクショナリ形式でCOMM::engを登録先に指定してもCOMM::engに登録されない(”COMM:XXX”というキーに登録されてしまう。)というところが謎だったのですが、id3.COMMメソッドでlang=として3文字の言語コードを指定することで記入ができるというのがポイントです。日本語のデータでも’eng’でよいと思います。多くのプレーヤソフトはlang=”eng”のデータを参照しているように見えます。

なお、この手順でコメントを保存すると。 ID3v2v2.4のタグとして挿入されます。おおよそ問題はないと思いますが古いプレーヤを使っている人は注意。

import argparse
from mutagen import id3
if __name__ == "__main__":
parser =argparse.ArgumentParser()
parser.add_argument("mode", help="load or write:コメントをcommentfileに読み出すか、書き出すか。")
parser.add_argument("mp3file",help="対象とするMP3")
parser.add_argument("commentfile", help="コメントファイル。load modeで書き出したうえで、修正して、save modeでMP3に書き出す。")
args = parser.parse_args()
if args.mode == 'load':
print(f"{args.mp3file} からコメントを読み出しコメントファイル {args.commentfile} に書き出します\n")
try:
audio = id3.ID3(args.mp3file)
except id3._util.ID3NoHeaderError:
print(f"{args.mp3file}にはヘッダがありません。{args.commentfile} は変更していません。")
exit()
with open(args.commentfile, 'w', encoding="utf-8") as f:
if "COMM::eng" in audio:
f.write(audio["COMM::eng"][0])
print(f"{args.commentfile} にコメントデータを書き込みました")
else:
print(f"{args.mp3file} の中にコメントタグが見つかりませんでした")
elif args.mode == 'write':
print(f"コメントファイル {args.commentfile} から {args.mp3file} にコメントを書き出します\n")
try:
audio = id3.ID3(args.mp3file)
except id3._util.ID3NoHeaderError:
print(f"{args.mp3file}にはヘッダがありません。作成します。")
audio = id3.ID3()
with open(args.commentfile, 'r', encoding="utf-8") as f:
comment = f.read()
comment = comment.replace('\r\n', '\n')
if "COMM::eng" in audio:
audio['COMM::eng'] = id3.COMM(encoding=3, lang='eng',text=[comment])
else:
audio['COMM::eng'] = id3.COMM(encoding=3, lang='eng',text=[comment])
audio.save(args.mp3file)
print(f"書き込まれたデータは:\n{audio['COMM::eng'][0]}")
else:
#コマンドが指定されていない
print("modeコマンドが指定されていません\n")
parser.print_usage()
exit()

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です