読者です 読者をやめる 読者になる 読者になる

ゴミ溜め@技術系日常系雑文

主にWeb技術やそのほかつまづいたこととか引っかかって調べたこととかをまとめてます。

はてなダイアリーから引っ越しました。)

PT3導入したので、EpgTimerで録画したファイル名を書き換えるバッチ+perlスクリプトを書いた

バッチ perl

発売日に買ったのにずっと放置してたPT3をようやくPCに導入した。
で、EpgTimerで録画したTSファイルの録画情報ファイル(.ts.program.txt)からサブタイトルを抽出してTSファイルのファイル名に追記したいと思ったので、PerlとBATで何とかしてみた。

で、今回作ったプログラムの動作は、録画情報ファイルをrename.batにドラッグアンドドロップすることで動作するようにした。

Perlを選んだ理由は「何となく」。
最近使ってないのでちょっと使ってみたくなったので使っただけなので、特に意味は無い。

フォルダ構成

EpgTimer側で動画保存先を「D:\TV_RECORDING」としておく。
動画保存先フォルダに下記のような構成でファイルを作成する。

動画保存先(D:\TV_RECORDING\)
 └ rename\
  ├ rename.bat
  └ rename.pl

このうちrename.batに録画情報ファイル(.ts.program.txt)をドラッグ&ドロップすると、rename.plを呼び出し、ファイル名書き換え処理を行う流れ。

EpgTimerの設定

「設定」→「動作設定」→「予約情報管理」から、「録画時のファイル名にPlugInを使用する」にチェックを入れ、下記の通り「設定」する。

$Title2$($SDYYYY$-$SDMM$-$SDDD$-$STHH$-$STMM$).ts
(番組名(放送日時ハイフン区切り).ts)

構文がよくわからない。どこかにまとまってないかな。

なお今回は番組名と放送日時の間にサブタイトルを挿入するスクリプトをつくる。

ソース

rename.bat

@echo off
setlocal ENABLEDELAYEDEXPANSION

for %%i in (%*) do (
perl %~dp0rename.pl %%i
)

「%*」は与えられた引数をすべて返すもの。EpgTimerの吐くファイル名は、モノによっては全角・半角スペースを含むモノが有り、%1だと通らないことがあるので注意。

[2014/04/05 加筆]複数のパスが渡されたときにパス毎にrename.plを呼び出すように改良。

次にrename.pl

use Config::Tiny;

# SETTINGS ##############################################################
# ファイルの拡張子
my %exp = (
	"ts"      => ".ts",
	"program" => ".ts.program.txt",
	"err"     => ".ts.err"
);

# 設定ファイルのパス
my $ini = Config::Tiny->read('D:\TV_RECORDING\rename\settings.ini');

# ConvertText.txt ファイルのパス
my $convfile = "C:\\Users\\Tatsuya\\app\\EpgDataCap_Bon\\x64\\ConvertText.txt";

# 使用禁止文字
my %replacechars = (
	':'  => ':',
	';'  => ';',
	'/'  => '/',
	'\\' => '¥', 
	'|'  => '|',
	','  => ',',
	'*'  => '*',
	'?'  => '?',
	'"'  => '”',
	'<'  => '<',
	'>'  => '>'
);
#########################################################################

my $routine = "";

print "-------------------------------------------------\n";

# バッチからファイルパスを受け取る。
my $arg = shift; &message("arg : $arg\n");
my %fpath = ("ts"=>"", "err" => "", "program"=>"");

if(!$arg) { &error("ファイルが指定されていません"); }

$arg =~ s/\.ts\.err$//;

$fpath{ts} = $arg.$exp{ts};
&message("[動画ファイルパス]\n$fpath{ts} ...");
-f $fpath{ts} ? &message("OK\n") : &error("ファイルがありません");

$fpath{err} = $arg.$exp{err};
&message("[エラーログファイルパス]\n$fpath{err} ...");
-f $fpath{err} ? &message("OK\n") : &error("ファイルがありません");

$fpath{program} = $arg.$exp{program};
&message("[動画情報ファイル]\n$fpath{program} ...");
-f $fpath{program} ? &message("OK\n") : &error("ファイルがありません");

&message("\n");

my @fpath = split(/\\/, $arg);

# ファイル名を取得。
$fname = @fpath[$#fpath];
&message("ファイル名      : $fname($exp{ts}|$exp{program}|$exp{err})\n");

# ファイルのあるディレクトリのパスを取得。
@fdir = @fpath;
pop @fdir;
$fdir = join("\\", @fdir) . "\\";
&message("ファイル保存場所: $fdir\n");

$fname =~ /^(.*)(\(\d{4}-\d{2}-\d{2}-\d{2}-\d{2}\))$/;
$before = $fname;
my ($title, $time) = ($1, $2);
&message("録画開始時刻    : $time\n");
&message("番組名          : $title\n");

&message("-------------------------------------------------\n");
&rename(%fpath);
RENAME_END:;
_END:;


sub rename {

	my %fpath = @_;

	&message("# リネーム処理開始...\n");

	$routine = "RENAME";

	# 動画情報ファイルを開く。
	open(FH, "< " . $fpath{program}) or &error(
		"動画情報ファイルの展開に失敗しました。\n" .
		"(指定されたパス: $fpath{base})");
	
	# サブタイトルの抽出。
	my $subtitle;
	while(my $line = <FH>) { print "[line]$line\n";
		chomp($line);
		if($title eq "Z/X IGNITION" && $line =~ /PHASE([0-90-9]+)/i) {
			$subtitle = "#$1";
			$subtitle =~ s/^(.*)』$/$1/; # なぜかカッコがついてきてしまうので削除。
			last;
		} elsif($line =~ /^(#|#|第)[0-90-9]+/i) {
			$subtitle = $line; last;
		}
	}

	# 使用禁止文字の置換
	while(my ($b, $a) = each(%replacechars)) {
		$subtitle =~ s/\Q$b\E/$a/g;
	}
	
	print "[subtitle]$subtitle\n";
	$subtitle ? &message("サブタイトル    : $subtitle\n")
	          : &error("サブタイトルらしき文字列は見当たりませんでした。");
	close(FH);

	if( $ini->{'command'}->{'rename_enable_yes'} ? 1 : &command("上記の内容でリネームしますか?" )) {

		&message("リネームします。\n");
		
		# リネーム実行
		my $rename = "$title$subtitle$time";
		while( ($step, $e) = each(%exp) ) {
			my $before = "$fdir$before$e";
			my $after = "$fdir$rename$e";
			
			&message("[$step] $before ...\n... $after\n");
			rename($before, $after) or &error("リネームエラー($e :$!)");
		}

		$before = $rename;

	} else {
		&message("リネームをキャンセルしました。\n");
	}

	&message("# リネーム処理終了...\n");
	&message("-------------------------------------------------\n");
}

sub command {
	&message(shift."(Y/N) ");
	my $in = <STDIN>;
	chomp $in;
	return ($in eq "y" || $in eq "Y" || $in eq "") ? 1 : 0;
}

sub message {
#	print encode("cp932", shift);
	print shift;
}

sub error {
	my $msg = shift;
	&message("[!]$msg\n");
	
	my $in = <STDIN>;

	goto $routine."_END";
}

[2014/04/05 追記]ソースを一新した。とりあえず動いてるけど文字コードの関係でたまに文字化けするので改良予定。

以上。