A Better Project@はてなダイアリー(インポート版)

基本的にここは更新されません。詳細はaboutへ。

m4a を ogg に変換する JScript(EasyMonaPlayer を試す人向け)

OSC 2007 Fall - higepon blog
今日は時間があったので、EasyMonaPlayer を試してみたのですが、私の今の手持ちの音楽ファイルは、mp3 よりも m4a の方が圧倒的に多いので、m4a も ogg に変換できないかなあと思い、以下の JScriptを書いてみました(scheme は分からなかったので。だいたいやっていることは、mp3 を ogg に変換する convert_ogg.scm と同じなはずです。タグ情報取得には、MP4BOX を使っています)。

//mp4ogg.js
//
// requirements
//    MP4Box.exe
//    ffmpeg.exe
//    oggenc.exe
//
// this script is the MIT License.
//  http://www.opensource.org/licenses/mit-license.php

var WshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var m4aRe = /\.m4a$/i
var oggRe = /\.ogg$/i
var mydir = fso.GetFolder(".");// music
var binpath = "..\\bin\\"
var fileList = new Enumerator(mydir.files);
while (!fileList.atEnd()){
    var myfile = fileList.item();
    //myfile.search() not work.
    if(m4aRe.test(myfile)){
        var inFileName = myfile.Name;
        var outFileName = inFileName.replace(m4aRe, ".ogg");
        if (!fso.FileExists(".\\" + outFileName)){
            WScript.Echo(myfile + " getting info start.");
            var myMP4Box = WshShell.Exec(binpath + "MP4Box -info " + '"' +
                                         myfile + '"');
            while (myMP4Box.Status == 0){
                WScript.Sleep(100);
            }
            var myMP4Info= myMP4Box.StdOut;
            var myInfoRe = [/^\tName:\s+(.*)/, /^\tArtist:\s+(.*)/]
            var myOGGInfo = [];
            while (!myMP4Info.AtEndOfStream){
                var myMP4InfoLine = myMP4Info.ReadLine();
                for (var i = 0; i < myInfoRe.length; i++){
                    if (myInfoRe[i].test(myMP4InfoLine)){
                        myOGGInfo[i] = myInfoRe[i].exec(myMP4InfoLine)[1];
                    }
                }
            }
            if(myOGGInfo[0]==null){
                myOGGInfo[0] = "No Title";
            }
            if(myOGGInfo[1]==null){
                 myOGGInfo[1] = "Unknown Artist"
            }
            WScript.Echo(myfile + " getting info end.");
            WScript.Echo(myfile + " decoding start.");
            var myffm = WshShell.Exec(binpath + "ffmpeg -y -i " + '"' +
                                      myfile + '"' + " tmp.wav");
            while (myffm.Status == 0){
                WScript.Sleep(100);
            }
            WScript.Echo(myfile + " decoding end.");
            WScript.Echo(myfile + " encoding start.");
            // if use Exec, failed getting ExitCode...
            WshShell.Run(binpath + "oggenc.exe -o " + '"' + outFileName + '"'
                         + " --title=" + '"' + myOGGInfo[0] + '"' +
                         " --artist=" + '"' + myOGGInfo[1] + '"' +
                         " tmp.wav", 1, true);
            WScript.Echo(myfile + " encoding end.");
        }
     }
        fileList.moveNext();
}
fso.DeleteFile (".\\tmp.wav");

試してみたい人のために、MP4BOX を含めた必要なファイル一式 を置いておきます。同梱のインストール用バッチファイルで EasyMonaPlayer のディレクトリを指定するのが面倒くさい人は、C:\EasyMonaPlayer に EasyMonaPlayer を解凍しておくと、何も入力せずに Enter で済みます。

このスクリプトの仕様及び EasyMonaPlayer の感想

タグ情報に多バイト文字を使っている場合、文字化けします。解決する時間が今はないのと、convert_ogg.scm でも同様だったので、これについては、仕様とします。スクリプトは、MIT ライセンスにしましたので、直したい人はご自由にどうぞ。
結局、このスクリプトの制作で一日潰したわけですけど、EasyMonaPlayer は、それだけの制作意欲を刺激するものがあるので、ぜひ試してみることをお勧めします。再生速度がおかしかったり(既知の問題)と、実用には耐えないのですが、小さな OS で音楽ファイルが頑張って再生されているというのは、けっこう感動します。「作るという楽しさ。」というキャッチフレーズも良いです。
ちなみに、CPU 負荷を解消するには、http://www.h7.dion.ne.jp/~qemu-win/index-ja.html から、Kqemu をダウンロードしてインストールすると、それなりに安定します。