iPod用動画一括変換スクリプト

iPod touch用のmpeg4動画を一括で作るwshスクリプトを書いてみた。

コンセプトは、

  • 新しいのだけ勝手に変換
  • 変換パラメータを動画の種類に応じて自動的に切り換える

というもの。

エンコーダは「携帯動画変換君」に付属のffmpegを使用。iTunesに登録するのに、同じく変換君に付属のAddiTunesも使う。

変換元と変換先のディレクトリを決めておき、変換元に入っているファイルをスキャンし、変換先に無いものだけをエンコード処理するようにする。変換元ディレクトリに変換したいファイルを放り込んで、スクリプトを実行するだけで自動的に変換してくれるようにするというわけ。

ついでに変換先のディレクトリにfiles.txtというテキストファイルを作成し、変換したファイル名とムービーの長さを記録してある。


ソースのさまざまなサイズやアスペクトに対応するべく、ファイル名によってパラメータのセットを切り換えるようにする。先頭の二文字に"W_"のように識別子をつけて、これによってパラメータを切り換える。

とりあえず用意したのは次の4パターン

  • Q_ 4:3ソースをQVGAに変換
  • V_ 4:3ソースを432x320に変換
  • W_ 4:3のソースを上下の黒帯をカットして16:9の480x272に変換
  • S_ そのまま480x272に変換(16:9ソースか4:3のスクイーズ画像用)

細かいパラメータやビットレートを調整しはじめるときりがないので、とりあえずはH264の700kbpsに設定してある。


というわけでスクリプトは以下。頭のディレクトリとツールのパスだけ環境に応じて変更すれば、どこでも動くはず。コマンドシェルからcscript ipod.jsとして実行するか、バッチを作っておいて実行してok


ipod.js

// mp4 convert and add iTunes

//settings この部分は環境に応じて書き換える
var ffmpeg = "C:\\RD\\tools\\ffmpeg.exe" ;		//ffmpeg path
var addtunes = "C:\\RD\\tools\\AddiTunes.exe " ;	//AddTunes path
var sdir = "C:\\RD\\" ;				//source dir
var ddir = "D:\\RD\\ipod\\" ;			//target dir
var sexts = "mpg|mp4|flv|vob|avi" ;
var additunes = true ;

//params
var opts_com = { 
	'y':'',
	'maxfr':30,
	'vcodec':'h264',
	'bitexact':'',
	'vprofile':'baseline',
	'bufsize':512,
	'g':250,
	'vlevel':20,
	'deinterlace':'',
	'b':768,
	'maxrate':1024,
	'hq':'', 
	'acodec':'aac',
	'ab':96, 
	'ar':48000, 
	'ac':2,
	'f':'ipod'
 } ;
var opts = {
	'Q' : { 
		's':'320x240' },
	'V' : {
		's':'432x320' },
	'W' : {
		'croptop':56,
		'cropbottom':64,
		's':'480x272' },
	'S' : {
		's':'480x272' }
 } ;


var sh = WScript.CreateObject("WScript.Shell");
var ostr_com = "" ;
for(var o in opts_com) {ostr_com += "-"+o+" "+opts_com[o]+" "; }

var files = [];
var ws = WScript.CreateObject("Shell.Application");
var fo = ws.NameSpace(sdir) ;
var fi = fo.Items() ;
for(var i=0;i< fi.Count;i++) {
	f = fi.Item(i) ;
	if(!f.IsFolder && f.Name.match("(.+)\.("+sexts+")$")) {
		files.push(f.Name) ;
	}	
};

var fs = WScript.CreateObject("Scripting.FileSystemObject") ;
var fp = fs.OpenTextFile(ddir+"files.txt",8,true) ;

for(var i=0;i<files.length;i++) {
	var ostr ="" ;
	var f=files[i];
	var sf = sdir+f ;
	if( f.match(/^([A-Z])_(.+)\.(.+)$/) ) {
		f = RegExp.$2 ;
		opt= opts[RegExp.$1];
	} continue ;
	for(var o in opt) {ostr += "-"+o+" "+opt[o]+" "; }
	var df = ddir+f+".m4v" ;
	if(fs.FileExists(df)) {
		WScript.Echo("Skip "+df) ;
		continue;
	}

	WScript.Echo("Conv "+sf) ;
	var c =ffmpeg + " -i "+sf+" "+ostr_com + ostr +df ;

	var ll ;
	var e = sh.Exec(c) ;
	while(!e.Status) {
		l = e.StdErr.ReadLine() ;
		ll = "{'name':'"+f+"'," ;

		if(l.match(/Duration: ([0-9]+):([0-9]+):([0-9.]+)/)) {
			ll += "'time':"+(RegExp.$1*3600+RegExp.$2*60+RegExp.$3*1)+"}," ;
			fp.WriteLine(ll) ;
			ll = "" ;
		}
		if(l.match(/^Stream mapping/)) {
			WScript.Echo("......");
			e.StdErr.ReadAll();
			break ;
		}
		
		WScript.Echo(l) ;
	}
	if(additunes) {
		e = sh.Exec(addtunes + df) ;
		WScript.Echo("Added to iTunes");
	}
}
fp.Close() ;
WScript.Echo("done") ;