@set @EXIT_SUCCESS = 0
@set @EXIT_FAILURE = 1
@set @DEFAULT_CH_KBPS = 64
var InputExtRegExp = /^wav$/i;
var OutputExt = "mp3";
var Shell= new ActiveXObject("WScript.Shell");
var Fso = new ActiveXObject("Scripting.FileSystemObject");
var Opt = new struct_options();
main();
exit();
function echo(text)
{
Script.Echo(text);
}
function exit(exit_code)
{
Script.Quit(exit_code);
}
function print_usage()
{
echo(Script.ScriptName);
echo(" [/kbps[:<ビットレート kbps>]]");
echo(" [/fs:<サンプリング レート kHz>]");
echo(" [/force] [/suspend]");
echo(" <フォルダ名/ファイル名> [<フォルダ名/ファイル名 2> [...]]");
echo();
echo(" /kbps ビットレートの指定 (kbps)。");
echo(" /fs 優先するサンプリング レート (kHz)。");
echo(" /export 開かれているファイル群を圧縮する。");
echo(" /force 既存ファイルがあっても上書きする。");
echo(" /suspend 終了後 OS を待機状態にする。");
echo();
echo("注: ビットレートの指定は 2 ch の場合の値 (kbps) を書く。");
echo();
echo("注: ビットレートの既定値は " + (@DEFAULT_CH_KBPS * 2) + " kbps。");
echo();
echo("注: フォルダ名やファイル名が一つも指定されていない場合は、指定コー");
echo(" デックのフォーマットが列挙表示される。");
echo();
}
function print_fmts(codec_info, fs, ch)
{
var fmt_list, fmt, i;
fmt_list = codec_info.GetCodecFormats(fs, ch);
fmt_list = fmt_list.toArray();
if (fmt_list.length) {
echo("--- " +
(fs / 1000) + " kHz / " +
ch + " ch" +
" ---");
for (i in fmt_list)
echo(fmt_list[i].Desc);
echo();
}
return fmt_list.length;
}
function print_formats(codec_info)
{
var fs_list = new Array();
var n;
for (n = 1; n <= 4; n *= 2) {
fs_list[fs_list.length] = 48000 / n;
fs_list[fs_list.length] = 44100 / n;
fs_list[fs_list.length] = 32000 / n;
}
echo("使用可能な圧縮フォーマット:");
var num_fmts = 0;
var fs, ch, i;
for (i in fs_list) {
for (ch = 2; ch; --ch) {
fs = fs_list[i];
num_fmts += print_fmts(codec_info, fs, ch);
}
}
if (num_fmts == 0)
echo("(なし)");
echo("※全てのフォーマットを列挙していない可能性があります。");
}
function struct_options()
{
this.ChKbps = @DEFAULT_CH_KBPS;
this.SampleRate = 0;
this.ExportMode = false;
this.ForceOverwrite = false;
this.Suspend = false;
this.InputFiles = new Array();
}
function str2chkbps(str)
{
var val = @DEFAULT_CH_KBPS;
if ((typeof(str) == "string") && str.length) {
val = parseInt(str);
if (val >= 1000)
val = Math.round(val / 1000);
val /= 2;
}
return val;
}
function str2fs(str)
{
var val = 0;
if ((typeof(str) == "string") && str.length) {
val = parseFloat(str);
if (val < 1000)
val *= 1000;
if (val < 8000)
val = 8000;
else if (val > 48000*4)
val = 48000*4;
val = Math.round(val);
switch (val) {
case 44000*4:
case 44000*2:
case 44000:
case 22000:
case 11000:
val += val / 440;
break;
}
}
return val;
}
function read_options()
{
var args = Script.Arguments;
if (args.Named.Exists("?")) {
print_usage();
exit(@EXIT_FAILURE);
}
var e, key;
for (e = new Enumerator(args.Named); !e.atEnd(); e.moveNext()) {
key = e.item().toLowerCase();
if (key == "kbps")
Opt.ChKbps = str2chkbps(args.Named(key));
else if (key == "fs")
Opt.SampleRate = str2fs(args.Named(key));
else if (key == "export")
Opt.ExportMode = true;
else if (key == "force")
Opt.ForceOverwrite = true;
else if (key == "suspend")
Opt.Suspend = true;
else {
echo("エラー: 不明なオプション " + e.item());
exit(@EXIT_FAILURE);
}
}
var i;
for (i = 0; i < args.Unnamed.length; ++i)
Opt.InputFiles[i] = args.Unnamed(i);
}
function select_fmt(codec_info, sample_rate, channels)
{
var fmt_list, fmt;
var fmt_cand = null;
var i, diff, diff2;
fmt_list = codec_info.GetCodecFormats(sample_rate, channels);
fmt_list = fmt_list.toArray();
for (i in fmt_list) {
fmt = fmt_list[i];
if (fmt.IsQualityBased)
continue;
diff = Math.round(fmt.Bitrate / 1000) - Opt.ChKbps * channels;
if (diff == 0)
return fmt;
if (fmt_cand == null)
fmt_cand = fmt;
else {
diff2 = Math.round(fmt_cand.Bitrate / 1000) - Opt.ChKbps * channels;
if (diff2 * diff >= 0) {
if (Math.abs(diff2) > Math.abs(diff))
fmt_cand = fmt;
}
else {
if (diff <= 0)
fmt_cand = fmt;
}
}
}
return fmt_cand;
}
function select_format(codec_info, sample_rate, channels)
{
var fmt = select_fmt(codec_info, sample_rate, channels);
if ((fmt == null) && (channels == 1))
fmt = select_fmt(codec_info, sample_rate, 2);
return fmt;
}
function get_link_target(file_path)
{
if (Fso.GetExtensionName(file_path).toLowerCase() == "lnk")
return Shell.CreateShortcut(file_path).TargetPath;
else
return file_path;
}
function process_file(writer, input_file)
{
var codec_info = writer.CodecInfo;
var input_ext = Fso.GetExtensionName(input_file);
var output_file = input_file.slice(0, -input_ext.length) + OutputExt;
echo(output_file);
if (!Opt.ForceOverwrite)
if (Fso.FileExists(output_file))
if (Fso.GetFile(output_file).DateLastModified > Fso.GetFile(input_file).DateLastModified) {
echo(" ファイルが既に存在します。");
return;
}
var clip = Application.CreateSoundClip(input_file);
var fmt = null;
if (Opt.SampleRate)
fmt = select_format(codec_info, Opt.SampleRate, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != clip.SampleRate))
fmt = select_format(codec_info, clip.SampleRate, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != 44100) && (clip.SampleRate != 44100))
fmt = select_format(codec_info, 44100, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != 22050) && (clip.SampleRate != 22050))
fmt = select_format(codec_info, 22050, clip.Channels, clip.BitsPerSample);
if (fmt == null) {
echo(" 圧縮フォーマットが見つかりません。");
echo("(途中終了)");
exit(@EXIT_FAILURE);
}
echo(" 圧縮フォーマット: " + fmt.Desc);
var time;
writer.CodecFormat = fmt;
time = Application.System.GetTickCount();
writer.Process(clip, output_file);
time = Application.System.GetTickCount() - time;
var sec, min;
sec = Math.round(time / 1000);
min = Math.floor(sec / 60);
sec -= min * 60;
echo(" 経過時間: " + min + " 分 " + sec + " 秒");
var fi = Fso.GetFile(get_link_target(input_file));
var fo = Fso.GetFile(output_file);
echo(" ファイル サイズ比: " + Math.round(fo.Size / fi.Size * 100) + "%");
}
function process_folder(writer, folder_path)
{
var folder = Fso.GetFolder(folder_path);
var fc, input_file, input_ext;
for (fc = new Enumerator(folder.Files); !fc.atEnd(); fc.moveNext()) {
input_file = fc.item().Path;
input_ext = Fso.GetExtensionName(get_link_target(input_file));
if (InputExtRegExp.test(input_ext))
process_file(writer, input_file);
}
}
function process_doc(writer, output_file, doc)
{
var codec_info = writer.CodecInfo;
echo(output_file);
if (!Opt.ForceOverwrite)
if (Fso.FileExists(output_file)) {
echo(" ファイルが既に存在します。");
return;
}
doc.SelectionFrom = 0;
doc.SelectionTo = doc.Length;
var clip = doc.CreateSoundClip();
var fmt = null;
if (Opt.SampleRate)
fmt = select_format(codec_info, Opt.SampleRate, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != clip.SampleRate))
fmt = select_format(codec_info, clip.SampleRate, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != 44100) && (clip.SampleRate != 44100))
fmt = select_format(codec_info, 44100, clip.Channels, clip.BitsPerSample);
if ((fmt == null) && (Opt.SampleRate != 22050) && (clip.SampleRate != 22050))
fmt = select_format(codec_info, 22050, clip.Channels, clip.BitsPerSample);
if (fmt == null) {
echo(" 圧縮フォーマットが見つかりません。");
echo("(途中終了)");
exit(@EXIT_FAILURE);
}
echo(" 圧縮フォーマット: " + fmt.Desc);
var time;
writer.CodecFormat = fmt;
time = Application.System.GetTickCount();
writer.Process(clip, output_file);
time = Application.System.GetTickCount() - time;
var sec, min;
sec = Math.round(time / 1000);
min = Math.floor(sec / 60);
sec -= min * 60;
echo(" 経過時間: " + min + " 分 " + sec + " 秒");
var fi_size = (clip.Length * clip.SampleRate) * (clip.BitsPerSample / 8) * clip.Channels;
var fo = Fso.GetFile(output_file);
echo(" ファイル サイズ比: " + Math.round(fo.Size / fi_size * 100) + "%");
}
function process_documents(writer, output_dir)
{
var names = new Array();
var i, j, s, t, n;
for (i = 0; i < Application.Documents.Count; ++i)
names[i] = Fso.GetBaseName(Application.Documents(i).Title);
for (i in names) {
s = names[i];
for (j = 0; j < i; ++j) {
if (s.toUpperCase() == names[j].toUpperCase())
break;
}
if (j < i) {
for (n = 2; ; ++n) {
t = s + " (" + n + ")";
for (j = 0; j < names.length; ++j) {
if (t.toUpperCase() == names[j].toUpperCase())
break;
}
if (j == names.length)
break;
}
names[i] = t;
}
}
for (i in names) {
s = output_dir + "\\" + names[i] + "." + OutputExt;
process_doc(writer, s, Application.Documents(i));
}
}
function main()
{
read_options();
var writer = Application.CreateFileWriter("mp3");
if (Opt.InputFiles.length == 0) {
print_formats(writer.CodecInfo);
exit(@EXIT_FAILURE);
}
if (Opt.Suspend)
Application.System.SetSuspendState(false, true, false);
var i, str;
if (Opt.ExportMode) {
if (Opt.InputFiles.length != 1) {
echo(" 出力先フォルダを一つだけ指定してください。");
exit(@EXIT_FAILURE);
}
str = Opt.InputFiles[0];
if ((str.length > 0) && (str.charAt(str.length - 1) == "\\"))
str = str.substr(0, str.length - 1);
if (Fso.FileExists(str)) {
echo(str);
echo(" パスが無効です。");
exit(@EXIT_FAILURE);
}
process_documents(writer, str);
}
else {
for (i in Opt.InputFiles) {
str = Opt.InputFiles[i];
if (Fso.FolderExists(str))
process_folder(writer, str);
else if (Fso.FileExists(str))
process_file(writer, str);
else {
echo(str);
echo(" パスが無効です。");
echo("(途中終了)");
exit(@EXIT_FAILURE);
}
}
}
exit(@EXIT_SUCCESS);
}