2022年01月30日
_ [computer] バッチ処理で動く、FLACファイルの連結とCUEシート作成プログラム
一番よく乗っているトラックのカーオーディオを交換して、車内でUSBメモリからの音楽再生が可能になり、(聴き流しが出来るので)買ったもののほぼ聴いていなかったいろいろな全集物などの、かなりボリュームの有る音源をそこで聴くことにしました。
まず最初に聴いたのは、バッハのカンタータ全集です。カンタータだけでもCDにして50枚以上、バッハ全集の中でもカンタータのパートは将来とも聴かないかも知れない、、などと思っていたのですが、苦労してUSBに入れて毎日聴いてみたら、これは本当に素晴らしい!。数ヶ月と時間はかかったのだけれど、先日で2回通り聴いてしました。何せ、朝夕の子供の送り迎えで、最低1時間、待ち時間を入れたりするとそれ以上車に居るわけですから、平日は結構すすみます。現在は、フレスコバルディ全集(CD15枚)に移ったばかりです。
USBメモリにデータを入れて車で聴くと言っても、実際どうするかが問題で、最初に試してみたところ、ラジオから切り替えたり、またUSBを外しても、さすがに再生の位置くらいは覚えてくれていて、差し直すと前回の続きから再生してくれます。しかし、一旦違うUSBメモリを使用したりすると、もう覚えてくれません。CD数十枚の全集では、1曲が1ファイルでは合計膨大なトラック数になり、もし途中で再生位置をクリアされてしまうと、たとえ聴いている方は大体場所はわかっていても、まず再生位置をそこまで持って行くのが何とも大変そうです。パソコンと違い、カーオーディオでは小さな先送りのボタンを、場合によっては100回以上押さねばならなくなる可能性があります。
最近はリッピングする場合もCUE+FLACと、CD1枚をCUEシート付きの1つのファイルにしていますが、このCD1枚を一つのファイルにまとめたデータの方が、車で聴く場合、実際扱いが楽で有る事が良くわかりました。もし再生位置をクリアされても、トラック数がそれほど多くないのですぐ指定できるし、その中で再生位置まで進めるのが面倒なら、そのCDを最初から聴き直すのであっても全く問題ない。
現状1曲づつ一つのファイルになっている場合は、普通はfoobarやfreacで1ファイルへのまとめ作業とCUEシート作成が可能です。しかし、一般的なGUIプログラムfoobarやfreacでは、自動化が無理なので、処理の数が多い場合も一々手で作業しなければならなくて、とても時間がかかります。それでバッチファイルに書いて処理できる、幾つかのFLACファイルを1つのファイルに連結しCUEシートを作成できる、コマンドラインのプログラムを少し前から時折探していたのですが、なかなか見つかりませんでした。
freacには"freaccmd.exe"と言うコマンド版が有るのですが、どうも形式変換は出来るのだけれど、ファイルを纏めたりCUEシート作成したりは出来ない模様です。そこでLinuxでの音楽データ操作関連のソフトなら当然可能だろうと、範囲をLinuxまで広げて探していたら、"shntool"と言うのを見つけました。探してダウンロードしてみたら、何とwindows版も有りまして、こちらを使用する事にしました。ただ、このshntoolと言うのは、既に10年以上前に開発が終わっているみたいで、あまり使用例の情報が有りません。付属のドキュメントを読んでみましても、イマイチ使い方がはっきりしないので、ここはまずは試行錯誤です。
このツールは、CUE+FLACを分割する事によく使われたらしく、いくらか出てくる使用例はそれが多いので、まずはその通り分割をやってみたのですが、当然動かない。まぁ"flac.exe"にパスが通っていないとダメだよね、とflac.exeを同じディレクトリに入れると無事作動しました。
>shntool split -f AAA.cue -t %n -o flac AAA.flac
これで、AAA.flacを、AAA.cueと言うCUEシートを参照して、1トラック1つのファイルに切り分けてくれます。逆に、幾つかのファイルを1つに纏める方は、
>shntool join -o flac *.flac
で簡単に出来る筈なのですが、ここでエラーが出て、半日程中断してしまいました。エラーの原因は、この時適当に2、3個持ってきたテスト用のFLACファイルの形式が、違っていた事でした。わかってしまえば当然なんだけど、こんなつまらないミスで数時間つぶしてしました。
同じ形式のFLACファイルを用意して上記のコマンドを実行すると、連結された"joined.flac"が出来上がります。このjoinの時に、同時にcueを作成出来きないかオプションを探しましたが見当たらないので、CUEシート作成は、別のコマンドで、
>shntool cue *.flac >joined.cue
としておく必要があるみたいです。但しこのshntoolのCUEシート作成はかなり単機能でして、TRACKとINDEXを出力するだけで、CUEシートの中のFILEの項の記載も、何と "joined.wav" の決め打ちの固定です。ここはオプションで変更できないか見てみましたが、どうも出来ないみたいです。なので、少なくても後でFILEの項目は実際のファイル名に書き換えなければいけません。しかしそんな後作業が必要とは言え、これでCMDのコマンドで一連の処理が可能な訳で、とりあえずバッチファイルでの連続処理に見通しがたちました。後は簡単だよな、とその時は思ったのですが、実際は結構大変だったのでした、、(スキルが無いって、言えばその通りですが)
ここでまず、shntoolのオプションを確認です。"*.flac"とかの処理でなく、用意したファイル名のリストで普通入力できるよな、と探しますと、案の定 "-F (file名)"というオプションを発見、ついでに、join時の出力ファイル名の指定オプション"-a" も存在しまして、例えば以下で、
>shntool cue -F (file名) >AAA.cue
>shntool join -o flac -F (file名) -a AAA
で(file名)にリストされているファイルを1つにまとめた"AAA.flac"と、そのCUEシート"AAA.cue"が出来て、CUEシートの方を、後でプログラムで修正すれば良いわけです。入力のファイルリストの作成と、後のCUEシートの手直しは、この所使い始めたpythonで書いてみます。
まず、処理ファイルのリストを作るプログラム"f_list.py"を書いてみました。60過ぎると、プログラムを書くにも時間がかかります。おまけに新しい言語なので、まだマナーが良く分かりません。(かと言ってCで書こうとしても、今だと結構時間がかかるでしょうね)処理内容は指定ディレクトリの中の".flac"ファイルのリストを作成するだけで、単純なものです。出来たので、実際の音楽全集のデータで少し試したところ、幾つか上手くいった後で、途中でエラーが出てしまいました。
エラーメッセージでは、CP932ではこの文字コードは扱えない、と言う内容のものでした。見たところ、該当ファイル名のテキストがフランス語で、アクサンが付いる文字があります。調べると、日本語windowsはCP932(Shift-JISのMS改変版らしい)と言うのをデフォルトで使っていて、特に指定をしないとpythonもそれに従う模様。windows上のエクスプローラーの画面では、キチンとファイル名の文字が出ているんですが、ダメなんですね。解決法は、pythonで open文のオプションに encoding="utf-8"とエンコードを指定して、明示的にUFT-8で出すと大丈夫らしいので、このオプションを付けました所、エラーは消えました。
ただし今度は、このファイルをshntoolが正常に読み込めない事が有ると分かりました。恐らく、shntool自体もデフォルトのCP932で読み込むので、UTF-8でしか表現できないコードが有ると、それを読めないみたいです。その結果、該当のファイルが存在しない、と言うエラーになってしまいます。正直、これには困ってしまいました。ファイル名は曲名を表している事が多いので、実際フランス語やらその他の言語やらの特殊な文字は、結構出て来ます。
一番直截な解決法は、shntoolのソースを修正してコンパイルしなおす事。ソースコードが付いてきているので、まぁやって出来ない事は無いでしょうが、どのくらいかかるか判らないのであまり手を付けたくない。それで、今回はCUEシートと1つに纏めたファイルを作る事が目的なので、コピーを取ってからCP932で扱えない文字のファイル名を書き換えてしまい、その上でCUE+FLACを作る、って言うのが現実的かなぁ、と、、その他にも、最初の考え通り、Linuxに持って行って、そちらで処理を行うとか、、
そんな中、検索した解決法の下の方で、windowsのデフォルトをUTF-8にする、と言う方法を見つけました。コントロール=>地域=>管理=>システムロケールの変更で、下段、「ベータ:~~UFT-8を使用」と言うのが有って、ここにチェックを入れて再起動すると、UTF-8を扱ってくれるらしい。実際やってみると、上手く行きまして、shntoolでUTF-8のファイルリストを正常に読み取り、ファイルにアクセス出来ました。ただしそのまま使うと、逆に動かなくなるプログラムも有るらしいし、まだベータ版らしいので、今回の処理をする時のみ一時的にこのモードにする事とします。
色々ありましたが、これで一連の流れは出来たので、次にバッチファイルを書いて、複数のディレクトリのドラッグ&ドロップで、連続処理させます。該当のディレクトリ名を処理後のファイル名にしますので、まず、フルパスからディレクトリ名だけを取るのですが、最初のファイルリストを作るpythonのプログラム中で、既にそれをやらせているので、それを環境変数で渡せば大丈夫だろ、と安直に思ったのですが、色々やってみたのですがpythonのプログラム実行中から、システムの環境変数に値を渡す事は出来ませんでした。
仕方ないので、バッチファイルの書き方解説をよく読んでみますと、ファイル名だけと言う変数の受け渡しが有る事が分かりました。"%~n0"とか言う書き方です。何か変な書き方ですね。このバッチファイルの仕様を設計した人、私はどうも尊敬できません。今回の場合、ループ変数"%%i"なのですが(これも変な表記)、この何処に"~n"を入れれば良いのかわからないので、ここは試行錯誤して、結局"%%~ni"とすれば良い事が判りました。で、まず書いてみたのが、こんな感じです、
for %%i in (%*) do (
echo.
echo Target directory path =%%i
set COLL_NAME=%%~ni
py f_list.py %%i
shntool cue -F %COLL_NAME%.lst >%COLL_NAME%.cue
shntool join -o flac -F %COLL_NAME%.lst -a %COLL_NAME%
py fix_cue.py %COLL_NAME%.cue
)
でもこれでは動かない!、期待した環境変数%COLL_NAME%の展開が出来ないのです。それで更に、バッチファイルの書き方をもう一度よく読んでみますと、「for文などは一つのブロックとして扱われるため、中の変数は最初に展開される」との事で、内部で値を設定しても反映されないらしい。それを可能にする為に、遅延環境変数展開と言うのが有るらしくて、結局こんな感じに、、
setlocal enabledelayedexpansion
for %%i in (%*) do (
echo.
echo Target directory path =%%i
set COLL_NAME=%%~ni
py f_list.py %%i
shntool cue -F !COLL_NAME!.lst >!COLL_NAME!.cue
shntool join -o flac -F !COLL_NAME!.lst -a !COLL_NAME!
py fix_cue.py !COLL_NAME!.cue
)
一般にCUEシートの内容としては、全体の"TITLE","PERFORMER","FILE"の項目が有り、それ以下に各"TRACK"の下に"TITLE"と"INDEX"の項目が有ります。このshntoolが出力するCUEシートはかなりシンプルなもので、タイトル名などの項目は有りません。それに前述の通り、参照のFILEの項が "joined.wav"で固定です。
後のプログラムfix_cue.pyで、参照ファイルの名前の変更と、全体のTITLE、各トラックのTITLEを追加します。トラックのTITLEは、ファイル名をそのまま設定しておきます。全体のTITLEは、先に環境変数で設定しておいて、プログラム中にそれを読んで設定することにしました。"PERFORMER"の項は空白にしました。
実際の処理は上述の通り、windowsをUTF-8に設定して、再起動させてから行います。おかげで、一応全部ちゃんと処理できているみたいです。しかし、簡単な文字処理のプログラム2本とバッチファイル1つ、それを作るのに土曜日、丸1日かかりました。逐一手作業でやった方が早かったかも、、です。でも、pythonとバッチファイルの良い勉強にはなりましたか、、
追記: 用意したUSBには、少し大きくて入らなかったので、mp3に変換してみました。数が多くても、普通にfreacなどからまとめて変換出来るしょうけど、コマンドラインづいているのでコマンドライン版の"freaccmd.exe"を使ってみました。流石にshntool.exeやflac.exeと違って単独では動かないので、インストールした場所にパスを通すかフルパスで、、
>(インストールパス)\freaccmd -e lame -m VBR -q 0 *.flac
でやってみました。オプションは最良のクオリティ指定ですが、だいぶ小さくなります。車の中なので、このmp3で充分かも。