カーオーディオで正しく認識されるMP3CDを作る

MP3CDの制限

うちのカーオーディオはMP3を書き込んだCD-Rに対応しています。
しかし、制限が色々とあり、普通にCDを焼いても一部しか認識されません。
MP3-CDの制限は以下のようなもの。

  • ファイル名の文字数が半角64文字まで(拡張子を含む)
  • ファイル名に使用可能な文字:
    • A-Z, 0-9, _(アンダースコア)
  • 最大ディレクトリ階層は8
  • 1フォルダ中の最大ファイル数は255、最大フォルダ数は50

さらに、ID3タグにも制限あり。

  • ID3v1, ID3v1.1
  • 表示可能なタグ:
    • 曲名, アーティスト名, アルバム名
  • 文字コードはShiftJISのみ
  • タグのトラック番号は無視され、ファイル名順に再生される

カーオーディオでMP3が正しく認識されるように、ID3タグとファイル名を変換する

僕がUbuntuで管理しているMP3ファイルは、ほとんどがID3v2.4で、UTF8でエンコーディングされています。
そのため、下記のような手順でCDを作成することにしました。

  • CDに焼きたいMP3ファイルを一ヶ所にまとめる
  • EasyTAGでID3タグとファイル名の変更
    • ID3v1.1に変換
    • ID3タグの文字コードをUTF8からShiftJISに変換
    • ファイル名を「アーティスト名,アルバム名,トラック番号,曲名」にリネーム
  • シェルスクリプトでファイル名の制限に引っかかる文字をリネームする
    • 日本語をローマ字に
    • 記号などを削除
    • 64文字以上のファイル名を短くする

ID3タグのバージョン変更と、ShiftJISへの変換


EasyTAGの「設定...」で

を行います。

ファイル名を「アーティスト名,アルバム名,トラック番号,曲名」にリネーム


EasyTAGでMP3のあるディレクトリを選択し、「スキャナ>ファイル名とフォルダ名の変更...」を選んで%a%b%n%tと入力。
こうすると、ファイル名が「アーティスト名,アルバム名,トラック番号,曲名」となります。(実際にはカンマは含まれない)
可読性は低いですが、曲順をアルバムの順番どおりにすることが目的なのでかまいません。
上の画像では、

となっています。


以上が終わったら、ファイルを全て選択して「ファイル>ファイルの強制保存」を選択し、終了します。

シェルスクリプトでファイル名を一括変更

ファイル名の制限に引っかからないようにリネームを行います。

  • 文字数が半角64文字まで(拡張子を含む)
  • 使用可能な文字:
    • A-Z, 0-9, _(アンダースコア)


制限をクリアするために、以下のような処理を行うシェルスクリプトを作りました。

  • 日本語をローマ字に変換する
  • 記号などを削除する
  • 64文字以内の長さにする
#!bin/bash

IFS='\\'
maxext=64 #最大ファイル名文字数(拡張子を含む)
maxnoext=`expr $maxext - 4`
cd $1
ls|while read f
do
    len=`expr length $f`
    len=`expr $len - 4` #変更前のファイル名の拡張子を除いた文字数
    ren=`expr substr $f 1 $len|nkf -e|kakasi -Ha -Ka -Ja -Ea -ka|tr a-z A-Z|sed -e "s/[^A-Z0-9_]//g"`
    len=`expr length $ren`
    if [ $len -gt $maxnoext ]
    then
        n=`expr $maxnoext - 2`
        ren=`expr substr $ren 1 $n`
        ren=`printf "$ren%02d" $i`
        i=`expr $i + 1`
    fi
    if [ $f != $ren.mp3 ] 
    then
        mv $f "$ren.mp3"
        echo Renamed: $ren.mp3
    else
        echo Not renamed: $ren.mp3
    fi
done

実行時は、

$ bash renmp3.sh mp3/

のように、MP3ファイルを格納したディレクトリを引数に渡します。
なお、nkf(日本語文字コードを変換するコマンド)とkakasi(日本語をローマ字アルファベットに変換するコマンド)が必要です。

シェルスクリプトの内容

ls|while read f
do

普通だったら for i in $(ls) としたいのですが、ファイル名にスペースがあるとそこで区切られてしまうので、このようにしました。
参考:http://www.ai.cs.scitec.kobe-u.ac.jp/~kawamura/2007-05-01-1.html

    len=`expr length $f`
    len=`expr $len - 4` #変更前のファイル名の拡張子を除いた文字数
    ren=`expr substr $f 1 $len|nkf -e|kakasi -Ha -Ka -Ja -Ea -ka|tr a-z A-Z|sed -e "s/[^A-Z0-9_]//g"`

3行めが長いです。ひとつづつ見ていくと、

expr substr $f 1 $len

ファイル名から拡張子を削除します。前の2行で、$lenに「ファイル名の文字数-4」をセットしています。

nkf -e

Ubuntu文字コードはデフォルトでUTF8です。従って、$fに格納されている文字列もUTF8です。
次に渡すkakasiコマンドがUTF8に対応していないため、ここでnkfを使ってEUC-JPに変換しています。

kakasi -Ha -Ka -Ja -Ea -ka

日本語をローマ字アルファベットに変換します。
当たり前かもしれませんが完璧な変換はできません(初音ミク→hatsuotomikuとか)。
今回はあくまで「曲順をアルバムの順番どおりにすることが目的」なので、これでも十分です。

tr a-z A-Z

アルファベットを全て大文字に。

sed -e "s/[^A-Z0-9_]//g"

正規表現です。大文字アルファベット・半角数字・アンダースコア以外の文字は削除します。

    len=`expr length $ren`
    if [ $len -gt $maxnoext ]
    then
        n=`expr $maxnoext - 2`
        ren=`expr substr $ren 1 $n`
        ren=`printf "$ren%02d" $i`
        i=`expr $i + 1`
    fi

文字列が長さの制限を越えていたら、末尾を削って短くします。

expr substrは文字列の一部を返すコマンドで、$renの1文字目から58文字目($nの値)までを返します。
さらに、アーティスト名とアルバム名の部分が58文字以上だと、重複がでてしまうので、連番をつけています。

    if [ $f != $ren.mp3 ] 
    then
        mv $f "$ren.mp3"
        echo Renamed: $ren.mp3
    else
        echo Not renamed: $ren.mp3
    fi

名前を変更します。

補足

最初の

IFS='\\'

ですが、これをしておかないと、mvコマンドでスペースを含むファイル名を引数に渡すと、スペースで区切られてしまい、うまくいきませんでした。
IFSはInternal Field Separatorの略で、区切り文字を表すようです。
ここではファイル名に使われなそうな\(バックスラッシュ)を指定したので、\を含むファイル名だとエラーが起こると思います。

CD-Rの作成

ID3タグの変換・リネームが終わったファイルをCD-Rに焼いて完了です。

感想

ID3タグの変換もスクリプトでやりたいと思い、eyeD3というアプリケーションを使ってみましたが、pythonからでないと使いづらいみたいです。
あと最近はCDをFLACで取り込んでいるので、FLAC→MP3に変換するスクリプトも作りたいと思っています。