#!/usr/bin/perl #usage recwrap.pl ch length(sec) [bitrate(5)] [TID] [NO] [PID] [stationid] [digitalflag] [digitalband] [digitalch] # # Anime recording system foltia # http://www.dcc-jpl.com/soft/foltia/ # # #レコーディングラッパ #atから呼び出され、tvrecordingを呼び出し録画 #そのあとMPEG4トラコンを呼び出す # # DCC-JPL Japan/foltia project # use DBI; use DBD::Pg; use Schedule::At; use Time::Local; use Jcode; $path = $0; $path =~ s/recwrap.pl$//i; if ($pwd ne "./"){ push( @INC, "$path"); } require "foltialib.pl"; #引き数がアルか? $recch = $ARGV[0] ; if ($recch eq "" ){ #引き数なしで実行されたら、終了 print "usage recwrap.pl ch length(sec) [bitrate(5)] [TID] [NO] [PID]\n"; exit; } $recch = $ARGV[0] ; $reclength = $ARGV[1] ; $bitrate = $ARGV[2] ; $tid = $ARGV[3] ; $countno = $ARGV[4] ; $pid = $ARGV[5] ; $stationid = $ARGV[6] ; $usedigital = $ARGV[7] ; $digitalstationband = $ARGV[8] ; $digitalch= $ARGV[9] ; #DB初期化 my $data_source = sprintf("dbi:%s:dbname=%s;host=%s;port=%d", $DBDriv,$DBName,$DBHost,$DBPort); $dbh = DBI->connect($data_source,$DBUser,$DBPass) ||die $DBI::error;; if ($usedigital == 1){ $extension = ".m2t";#TSの拡張子 }else{ $extension = ".m2p";#MPEG2の拡張子 } $outputfile = `date +%Y%m%d-%H%M --date "1 min "`; chomp($outputfile); if ($tid == 0){ $outputfilename = "0--".$outputfile."-".$recch.$extension; $mp4newstylefilename = "-0--".$outputfile."-".$recch; }else{ if ($countno == 0){ $outputfilename = $tid ."--".$outputfile.$extension; $mp4newstylefilename = "-" . $tid ."--".$outputfile; }else{ $outputfilename = $tid ."-".$countno."-".$outputfile.$extension; $mp4newstylefilename = "-" . $tid ."-".$countno."-".$outputfile; } } if ($usedigital == 1){ #デジタルなら &writelog("recwrap RECSTART DIGITAL $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno friio"); #録画 $starttime = (`date +%s`); $oserr = system("$toolpath/perl/digitaltvrecording.pl $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno friio"); $oserr = $oserr / 256; if ($oserr == 1){ &writelog("recwrap ABORT recfile exist. [$outputfilename] $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno"); exit; }elsif ($oserr == 2){ &writelog("recwrap ERR 2:friio busy;retry."); &continuousrecordingcheck;#もうすぐ終わる番組をkill sleep(2); $oserr = system("$toolpath/perl/digitaltvrecording.pl $digitalstationband $digitalch $reclength $stationid N $outputfilename $tid $countno friio"); $oserr = $oserr / 256; if ($oserr == 2){ &writelog("recwrap ERR 2:friio busy;Giving up digital recording."); } }elsif ($oserr == 3){ &writelog("recwrap ABORT:ERR 3"); exit ; } }else{ #リモコン操作 # $haveirdaunit = 1;リモコンつないでるかどうか確認 if ($haveirdaunit == 1){ # 録画チャンネルが0なら if ($recch == 0){ # &つけて非同期でchangestbch.pl呼び出し &writelog("recwrap Call Change STB CH :$pid"); system ("$toolpath/perl/changestbch.pl $pid &"); }#end if }#end if if($recch == -10){ #非受信局なら &writelog("recwrap Not recordable channel;exit:PID $pid"); exit; }#end if # アナログ録画 &writelog("recwrap RECSTART $recch $reclength 0 $outputfilename $bitrate $tid $countno $pid $usedigital $digitalstationband $digitalch"); #録画 #system("$toolpath/perl/tvrecording.pl $recch $reclength 0 $outputfile $bitrate $tid $countno"); $starttime = (`date +%s`); $oserr = system("$toolpath/perl/tvrecording.pl $recch $reclength 0 $outputfilename $bitrate $tid $countno"); $oserr = $oserr / 256; if ($oserr == 1){ &writelog("recwrap ABORT recfile exist. [$outputfilename] $recch $reclength 0 0 $bitrate $tid $countno $pid"); exit; } }#endif #デジタル優先フラグ #デバイスビジーで即死してないか検出 $now = (`date +%s`); if ($now < $starttime + 100){ #録画プロセス起動してから100秒以内に戻ってきてたら $retrycounter == 0; while($now < $starttime + 100){ if($retrycounter >= 5){ &writelog("recwrap WARNING Giving up recording."); last; } &writelog("recwrap retry recording $now $starttime"); #アナログ録画 $starttime = (`date +%s`); if($outputfilename =~ /.m2t$/){ $outputfilename =~ s/.m2t$/.m2p/; } $oserr = system("$toolpath/perl/tvrecording.pl $recch $reclength N $outputfilename $bitrate $tid $countno"); $now = (`date +%s`); $oserr = $oserr / 256; if ($oserr == 1){ &writelog("recwrap ABORT recfile exist. in resume process.[$outputfilename] $recch $reclength 0 0 $bitrate $tid $countno $pid"); exit; }# if $retrycounter++; }# while } # if &writelog("recwrap RECEND [$outputfilename] $recch $reclength 0 0 $bitrate $tid $countno $pid"); # m2pファイル名をPIDレコードに書き込み $DBQuery = "UPDATE foltia_subtitle SET m2pfilename = '$outputfilename' WHERE pid = '$pid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); &writelog("recwrap DEBUG UPDATEDB $DBQuery"); &changefilestatus($pid,$FILESTATUSRECEND); # m2pファイル名をPIDレコードに書き込み $DBQuery = "insert into foltia_m2pfiles values ('$outputfilename')"; $sth = $dbh->prepare($DBQuery); $sth->execute(); &writelog("recwrap DEBUG UPDATEDB $DBQuery"); # Starlight breaker向けキャプチャ画像作成 if (-e "$toolpath/perl/captureimagemaker.pl"){ &writelog("recwrap Call captureimagemaker $outputfilename"); &changefilestatus($pid,$FILESTATUSCAPTURE); system ("$toolpath/perl/captureimagemaker.pl $outputfilename"); &changefilestatus($pid,$FILESTATUSCAPEND); } # MPEG4 ------------------------------------------------------ #MPEG4トラコン必要かどうか $DBQuery = "SELECT psp,aspect,title FROM foltia_program WHERE tid = '$tid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); @psptrcn= $sth->fetchrow_array; if ($psptrcn[0] == 1 ){#トラコン番組 &writelog("recwrap Launch ipodtranscode.pl"); exec ("$toolpath/perl/ipodtranscode.pl"); exit; # # ここから下は旧エンコード#2008/12/23 # 新エンコードはDBを見て未完了MPEG2を順次トラコン処理、 # 分散エンコードもきっとラクチンに対応可能 # 新エンコードではXviD/M4VスタイルとPSPファイル名対応を廃止 &changefilestatus($pid,80); #MPEG4ムービーディレクトリがあるかどうか #TIDが100以上の3桁の場合はそのまま my $pspfilnamehd = ""; $pspfilnamehd = $tid; &makemp4dir($tid); $pspdirname = "$tid.localized/"; $pspdirname = $recfolderpath."/".$pspdirname; #なければ作る #unless (-e $pspdirname ){ # system("$toolpath/perl/mklocalizeddir.pl $tid"); # #&writelog("recwrap mkdir $pspdirname"); #} $pspdirname = "$tid.localized/mp4/"; $pspdirname = $recfolderpath."/".$pspdirname; #なければ作る #unless (-e $pspdirname ){ # mkdir $pspdirname ,0777; # #&writelog("recwrap mkdir $pspdirname"); #} #ファイル名決定 if ($mp4filenamestyle == 1){# 1;よりわかりやすいファイル名 $pspfilname = $mp4newstylefilename ; }else{##0:PSP ファームウェアver.2.80より前と互換性を持つファイル名 #・フォルダ名[100MNV01]の100の部分は変更可(100〜999)。 # MP_ROOT ━ 100MNV01 ┳ M4V00001.MP4(動画) #┃   ┗ M4V00001.THM(サムネイル)※必須ではない #ファイル名決定 #ファイル名決定 #新アルゴリズム #TID 0000-3599まで[3桁] #話数 00-999まで[2桁] my $pspfilnameft = ""; my $pspfilnameyearhd = ""; my $pspfilnameyearft = ""; $btid = $tid % 3600; # print "$btid\n"; if($btid >= 0 && $btid < 1000){ $pspfilnamehd = sprintf("%03d",$btid); }elsif ($btid >= 1000 && $btid < 3600){ $pspfilnameyearhd = substr($btid, 0, 2); $pspfilnameyearhd =~ s/10/A/; $pspfilnameyearhd =~ s/11/B/; $pspfilnameyearhd =~ s/12/C/; $pspfilnameyearhd =~ s/13/D/; $pspfilnameyearhd =~ s/14/E/; $pspfilnameyearhd =~ s/15/F/; $pspfilnameyearhd =~ s/16/G/; $pspfilnameyearhd =~ s/17/H/; $pspfilnameyearhd =~ s/18/I/; $pspfilnameyearhd =~ s/19/J/; $pspfilnameyearhd =~ s/20/K/; $pspfilnameyearhd =~ s/21/L/; $pspfilnameyearhd =~ s/22/M/; $pspfilnameyearhd =~ s/23/N/; $pspfilnameyearhd =~ s/24/O/; $pspfilnameyearhd =~ s/25/P/; $pspfilnameyearhd =~ s/26/Q/; $pspfilnameyearhd =~ s/27/R/; $pspfilnameyearhd =~ s/28/S/; $pspfilnameyearhd =~ s/29/T/; $pspfilnameyearhd =~ s/30/U/; $pspfilnameyearhd =~ s/31/V/; $pspfilnameyearhd =~ s/32/W/; $pspfilnameyearhd =~ s/33/X/; $pspfilnameyearhd =~ s/34/Y/; $pspfilnameyearhd =~ s/35/Z/; $pspfilnameyearft = substr($btid, 2, 2); $pspfilnameyearft = sprintf("%02d",$pspfilnameyearft); $pspfilnamehd = $pspfilnameyearhd . $pspfilnameyearft; } # 話数 if (0 < $countno && $countno < 100 ){ # 2桁 $pspfilnameft = sprintf("%02d",$countno); }elsif(100 <= $countno && $countno < 1000 ){ # 3桁 $pspfilnameft = sprintf("%03d",$countno); # 話数3桁 $pspfilnamehd = substr($pspfilnamehd, 0, 2); # TID 二桁 後ろ1バイト落とし }elsif(1000 <= $countno && $countno < 10000 ){ # 4桁 $pspfilnameft = sprintf("%04d",$countno); # 話数4桁 $pspfilnamehd = substr($pspfilnamehd, 0, 1); # TID 1桁 後ろ2バイト落とし }elsif($countno == 0){ #タイムスタンプが最新のMP4ファイル名取得 my $newestmp4filename = `cd $pspdirname ; ls -t *.MP4 | head -1`; if ($newestmp4filename =~ /M4V$tid/){ $nowcountno = $' ; $nowcountno++; $pspfilnameft = sprintf("%02d",$nowcountno); while (-e "$pspdirname/M4V".$pspfilnamehd.$pspfilnameft.".MP4"){ $nowcountno++; $pspfilnameft = sprintf("%02d",$nowcountno); print "File exist:$nowcountno\n"; } #print "NeXT\n"; }else{ # 0の場合 週番号を100から引いたもの # week number of year with Monday as first day of week (01..53) #だったけど常に0に # my $weeno = `date "+%V"`; # $weeno = 100 - $weeno ; # $pspfilnameft = sprintf("%02d",$weeno); $pspfilnameft = sprintf("%02d",0); #print "WEEKNO\n"; } } my $pspfilname = $pspfilnamehd.$pspfilnameft ; # print "$pspfilname($pspfilnamehd/$pspfilnameft)\n"; }# endif MP4ファイル名が新styleなら #2006/12/03_10:30:24 recwrap TRCNSTART vfr4psp.sh /home/foltia/php/tv/591-87-20061203-1000.m2p -591-87-20061203-1000 /home/foltia/php/tv/591.localized/mp4/ 3 # トラコンキューイング #2007/7/10 my $trcnprocesses = ""; my $cpucores = `ls /proc/acpi/processor | wc -l`; $cpucores =~ s/[^0-9]//gi; unless ($cpucores >= 1 ){ $cpucores = 1; } do { $trcnprocesses = `ps ax | grep ffmpeg | grep -v grep | wc -l `; $trcnprocesses =~ s/[^0-9]//gi; # 既にトラコンプロセスが走っているなら適当に待機 if ($trcnprocesses >= $cpucores){ if (-e "/proc/uptime" ){ $loadaverage = `uptime`; chomp($loadaverage); }else{ $loadaverage = ""; } &writelog("recwrap TRCN WAITING :$trcnprocesses / $cpucores :$outputfilename $loadaverage"); sleep 113; sleep ($recch)*5; } } until ($trcnprocesses < $cpucores); if (($trconqty eq "")||($trconqty == 0 )){ &writelog("recwrap TRCNSTART vfr4psp.sh $recfolderpath/$outputfilename $pspfilname $pspdirname $psptrcn[1]"); system("$toolpath/perl/transcode/vfr4psp.sh $recfolderpath/$outputfilename $pspfilname $pspdirname $psptrcn[1]"); &writelog("recwrap TRCNEND vfr4psp.sh $recfolderpath/$outputfilename $pspfilname $pspdirname $psptrcn[1]"); #最適化 $DBQuery = "SELECT subtitle FROM foltia_subtitle WHERE tid = '$tid' AND countno = '$countno' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); @programtitle = $sth->fetchrow_array; if ( $countno == "0" ){ $pspcountno = ""; }else{ $pspcountno = $countno ; } &writelog("recwrap OPTIMIZE mp4psp -p $pspdirname/M4V$pspfilname.MP4 -t '$psptrcn[2] $pspcountno $programtitle[0]' "); Jcode::convert(\$programtitle[0],'euc'); system ("/usr/local/bin/mp4psp -p $pspdirname/M4V$pspfilname.MP4 -t '$psptrcn[2] $pspcountno $programtitle[0]'") ; $mp4filename = "M4V${pspfilname}.MP4"; $thmfilename = "M4V${pspfilname}.THM"; }else{# #2006/12/6 新エンコーダ &writelog("recwrap TRCNSTART ipodtranscode.pl $recfolderpath/$outputfilename $pspfilname $pspdirname $pid $psptrcn[1]"); system("$toolpath/perl/ipodtranscode.pl $recfolderpath/$outputfilename $pspfilname $pspdirname $pid $psptrcn[1]"); &writelog("recwrap TRCNEND ipodtranscode.pl $recfolderpath/$outputfilename $pspfilname $pspdirname $psptrcn[1]"); if($trconqty >= 2){#H.264/AVCなら $mp4filename = "MAQ${pspfilname}.MP4"; $thmfilename = "MAQ${pspfilname}.THM"; }else{ $mp4filename = "M4V${pspfilname}.MP4"; $thmfilename = "M4V${pspfilname}.THM"; } } #サムネール # mplayer -ss 00:01:20 -vo jpeg:outdir=/home/foltia/php/tv/443MNV01 -ao null -sstep 1 -frames 3 -v 3 /home/foltia/php/tv/443-07-20050218-0030.m2p #2005/02/22_18:30:05 recwrap TRCNSTART vfr4psp.sh /home/foltia/php/tv/447-21-20050222-1800.m2p 44721 /home/foltia/php/tv/447MNV01 3 &writelog("recwrap THAMJ mplayer -ss 00:01:20 -vo jpeg:outdir=$pspdirname -ao null -sstep 1 -frames 3 -v 3 $recfolderpath/$outputfilename "); system ("mplayer -ss 00:01:20 -vo jpeg:outdir=$pspdirname -ao null -sstep 1 -frames 3 -v 3 $recfolderpath/$outputfilename"); &writelog("recwrap THAMI convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/M4V$pspdirname.THM "); if (-e "$pspdirname/$thmfilename"){ $timestamp =`date "+%Y%m%d-%H%M%S"`; chomp $timestamp; system("convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/$thmfilename".$timestamp.".THM"); }else{ system("convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/$thmfilename"); } # rm -rf 00000001.jpg # convert -resize 160x120\! 00000002.jpg M4V44307.THM # rm -rf 00000002.jpg system("rm -rf $pspdirname/0000000*.jpg "); # MP4ファイル名をPIDレコードに書き込み $DBQuery = "UPDATE foltia_subtitle SET PSPfilename = '$mp4filename' WHERE pid = '$pid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); &writelog("recwrap UPDATEsubtitleDB $DBQuery"); # MP4ファイル名をfoltia_mp4files挿入 $DBQuery = "insert into foltia_mp4files values ('$tid','$mp4filename') "; $sth = $dbh->prepare($DBQuery); $sth->execute(); &writelog("recwrap UPDATEmp4DB $DBQuery"); &changefilestatus($pid,200); }#PSPトラコンあり sub continuousrecordingcheck(){ my $now = `date +%s --date "2 min "`; &writelog("recwrap DEBUG continuousrecordingcheck() now $now"); my @processes =`ps ax | grep recfriio`; my $psline = ""; my @processline = ""; my $pid = ""; my @pid; my $sth; foreach (@processes){ if (/friiodetect/) { if (/^.[0-9]*\s/){ push(@pid, $&); }#if }#if }#foreach if (@pid > 0){ my @filenameparts; my $tid = ""; my $startdate = ""; my $starttime = ""; my $startdatetime = ""; my @recfile; my $endtime = ""; my $endtimeepoch = ""; foreach $pid (@pid){ #print "DEBUG PID $pid\n"; &writelog("recwrap DEBUG continuousrecordingcheck() PID $pid"); my @lsofoutput = `/usr/sbin/lsof -p $pid`; my $filename = ""; #print "recfolferpath $recfolderpath\n"; foreach (@lsofoutput){ if (/m2t/){ @processline = split(/\s+/,$_); $filename = $processline[8]; $filename =~ s/$recfolderpath\///; &writelog("recwrap DEBUG continuousrecordingcheck() FILENAME $filename"); # 1520-9-20081201-0230.m2t @filenameparts = split(/-/,$filename); $tid = $filenameparts[0]; $startdate = $filenameparts[2]; $starttime = $filenameparts[3]; @filenameparts = split(/\./,$starttime); $startdatetime = $startdate.$filenameparts[0]; #DBから録画中番組のデータ探す $DBQuery = " SELECT foltia_subtitle.tid,foltia_subtitle.countno,foltia_subtitle.subtitle,foltia_subtitle.startdatetime ,foltia_subtitle.enddatetime ,foltia_subtitle.lengthmin ,foltia_tvrecord.bitrate , foltia_subtitle.startoffset , foltia_subtitle.pid ,foltia_tvrecord.digital FROM foltia_subtitle ,foltia_tvrecord WHERE foltia_tvrecord.tid = foltia_subtitle.tid AND foltia_tvrecord.tid = $tid AND foltia_subtitle.startdatetime = $startdatetime AND foltia_tvrecord.digital = 1"; &writelog("recwrap DEBUG continuousrecordingcheck() $DBQuery"); $sth = $dbh->prepare($DBQuery); &writelog("recwrap DEBUG continuousrecordingcheck() prepare"); $sth->execute(); &writelog("recwrap DEBUG continuousrecordingcheck() execute"); @recfile = $sth->fetchrow_array; &writelog("recwrap DEBUG continuousrecordingcheck() @recfile $recfile[0] $recfile[1] $recfile[2] $recfile[3] $recfile[4] $recfile[5] $recfile[6] $recfile[7] $recfile[8] $recfile[9] "); #終了時刻 $endtime = $recfile[4]; $endtimeepoch = &foldate2epoch($endtime); &writelog("recwrap DEBUG continuousrecordingcheck() $recfile[0] $recfile[1] $recfile[2] $recfile[3] $recfile[4] $recfile[5] endtimeepoch $endtimeepoch"); if ($endtimeepoch < $now){#まもなく終わる番組なら #kill system("kill $pid"); &writelog("recwrap recording process killed $pid/$endtimeepoch/$now"); } }#endif m2t }#foreach lsofoutput }#foreach }else{ #print "DEBUG fecfriio NO PID\n"; &writelog("recwrap No recording process killed."); } }#endsub