#!/usr/bin/perl # # Anime recording system foltia # http://www.dcc-jpl.com/soft/foltia/ # #tvrecording.pl # record-v4l2.plを呼びだす録画モジュール。 # #usage tvrecording.pl ch length(sec) [clip No(000-)] [filename] [bitrate(5)] [TID] [NO] [/dev/video0] #引数 #ch :録画チャンネル 0だとS入力、-1だとコンポジット入力 [必須項目] #length(sec) :録画秒数 [必須項目] #[sleeptype] :0かN Nならスリープなしで録画 #[filename] :出力ファイル名 #[bitrate(5)] :ビットレート Mbps単位で指定 #[TID] :しょぼかるタイトルID #[NO] :その番組の放送話数 #[/dev/video0]:キャプチャデバイス # # # DCC-JPL Japan/foltia project # # #use Time::HiRes qw(usleep); $path = $0; $path =~ s/tvrecording.pl$//i; if ($path ne "./"){ push( @INC, "$path"); } ## #キャプチャカード枚数検出 #cat /proc/interrupts | grep ivtv |wc -l # 11: 1054118 XT-PIC uhci_hcd, eth0, ivtv0, ivtv1, ivtv2 #失敗 #tvConfig.pl ------------------------------- $extendrecendsec = 10; #recording end second. #$startupsleeptime = 52; #process wait(MAX60sec) $startupsleeptime = 37; #process wait(MAX60sec) #------------------------------- require 'foltialib.pl'; &writelog("tvrecording: DEBUG $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4] $ARGV[5] $ARGV[6] $ARGV[7] "); sub getChCallsign { if ($ARGV[5] ne ""){ $recchname = $ARGV[5] ; }else{ $recchname = $recch."ch"; } }#endsub getChCallsign sub getRecPath{ #capture directory define $recfolderpath = '/home/foltia/php/tv'; }#end sub getRecPath # # -- ここからメイン ---------------------------- #準備 &prepare; #もし録画が走ってたら、止める $reclengthsec = &chkrecprocess(); &setbitrate; &chkextinput; $reclengthsec = $reclengthsec + $extendrecendsec ; &callrecordv4l; &writelog("tvrecording:$recch:$reclengthsec:$outputfile:$recdevice:$capturedeviceinputnum:$ivtvrecch:$stdbitrate:$peakbitrate"); # -- これ以下サブルーチン ---------------------------- sub chkextinput{ if ($recch == 0){ if ($svideoinputnum > -1 && $svideoinputnum < 30){ $capturedeviceinputnum = $svideoinputnum ; }else{ $capturedeviceinputnum = 7 ; } $capturedeviceinputName = "S-Video 1"; $ivtvrecch = ''; }elsif($recch == -1){ if ($comvideoinputnum > -1 && $comvideoinputnum < 30){ $capturedeviceinputnum = $comvideoinputnum; }else{ $capturedeviceinputnum = 8; } $capturedeviceinputName = "Composite 1"; $ivtvrecch = ''; }else{ if ($tunerinputnum > -1 && $tunerinputnum < 30){ $capturedeviceinputnum = $tunerinputnum ; }else{ $capturedeviceinputnum = 6 ; } $capturedeviceinputName = "Tuner 1"; $ivtvrecch = $recch; } # 1-12chはntsc-bcast-jp if($recch > 12){ if ($uhfbandtype == 1){ $frequencyTable = "ntsc-cable-jp"; }else{ $frequencyTable = "ntsc-bcast-jp"; } }else{ $frequencyTable = "ntsc-bcast-jp"; }#if &writelog ("tvrecording DEBUG $frequencyTable $recch"); }#chkextinput sub chkrecprocessOLD{ #もし録画が走ってたら、止める my $mencoderkillcmd = ""; $mencoderkillcmd =`/usr/sbin/lsof -Fp $recdevice`; $mencoderkillcmd =~ s/p//; if ($mencoderkillcmd != ""){ #kill process $mencoderkillcmd = "kill ".$mencoderkillcmd; system ($mencoderkillcmd); chomp($mencoderkillcmd); &writelog ("tvrecording Killed current recording process. process:$mencoderkillcmd"); sleep(1); my $videodevice =`/usr/sbin/lsof $recdevice`; while ($videodevice =~ /tvrecording/){ $videodevice =`/usr/sbin/lsof $recdevice`; sleep(1); $sleepcounter++; $reclengthsec = $reclengthsec - $sleepcounter; &writelog ("tvrecording videodevice wait:$sleepcounter"); } $sleepcounter = 0; }#if ($mencoderkillcmd != "") return $reclengthsec; }#end chkrecprocess sub chkrecprocess{ my $mencoderkillcmd = ""; my $j = $recunits -1; my $i = 0; my $testrecdevice = ""; my @usedevices ; my @unusedevices; my $n = 0; $recdevice = ""; if ($ARGV[7] ne ""){ $recdevice = $ARGV[7] ; } #for ($i = $j ;$i >= 0 ; $i--){ for ($i = 0 ;$i <= $j ; $i++){ #print "$i,$j\n"; $testrecdevice = "/dev/video$i"; $mencoderkillcmd =`/usr/sbin/lsof -Fp $testrecdevice`; $mencoderkillcmd =~ s/p//; if ($mencoderkillcmd != ""){ push (@usedevices , $testrecdevice); &writelog ("tvrecording now using:$testrecdevice"); }else{ push (@unusedevices , $testrecdevice); &writelog ("tvrecording unused:$testrecdevice"); }#if }#for $i = 0; #初期化 $n = @unusedevices; #デバイス指定があるか? if ($recdevice ne ""){ #指定があったら #そこが使われているかチェック $mencoderkillcmd =`/usr/sbin/lsof -Fp $recdevice`; $mencoderkillcmd =~ s/p//; if ($mencoderkillcmd != ""){ #使われてたら無条件に落とす $mencoderkillcmd = "kill ".$mencoderkillcmd; system ($mencoderkillcmd); chomp($mencoderkillcmd); &writelog ("tvrecording Killed current recording process. $recdevice:$mencoderkillcmd"); sleep(1); } }else{ #地上波or 指定なしなら if (($n == 0) and ($recch > 0)) {#空きデバイスがなくて、地上波なら $mencoderkillcmd =`/usr/sbin/lsof -Fp /dev/video$i`;#→$i $mencoderkillcmd =~ s/p//; if ($mencoderkillcmd != ""){ #使われてたら最高位/dev/video$j を無条件に落とす →最低位$i $mencoderkillcmd = "kill ".$mencoderkillcmd; system ($mencoderkillcmd); chomp($mencoderkillcmd); &writelog ("tvrecording Killed current recording process. /dev/video$i:$mencoderkillcmd"); sleep(1); } $recdevice = "/dev/video$i"; #→最低位$i &writelog ("tvrecording select device:$recdevice"); }elsif ($recch <= 0) { # 外部入力なら #外部入力だけどデバイス指定されていないときも #落とす $mencoderkillcmd =`/usr/sbin/lsof -Fp /dev/video$j`;# $mencoderkillcmd =~ s/p//; if ($mencoderkillcmd != ""){ #使われてたら最高位/dev/video$j を無条件に落とす $mencoderkillcmd = "kill ".$mencoderkillcmd; system ($mencoderkillcmd); chomp($mencoderkillcmd); &writelog ("tvrecording Killed current recording process. /dev/video$j:$mencoderkillcmd"); sleep(1); } $recdevice = "/dev/video$j"; # 外部入力は最高位デバイス }else{ #空きを使う $recdevice = shift(@unusedevices ); }#endif 空きデバイスなければ }#end if 指定あるか #ここには落ちてこないはずなのに? if ($recdevice eq ""){ $recdevice = "/dev/video0"; &writelog ( "Rec Device un defined. / $recch "); } return $reclengthsec; }#end chkrecprocessNew sub prepare{ #引数エラー処理 $recch = $ARGV[0] ; $reclengthsec = $ARGV[1]; if (($recch eq "" )|| ($reclengthsec eq "")){ print "usage tvrecording.pl ch length(sec) [clip No(000-)] [filename] [bitrate(5)] [TID] [NO] [/dev/video0]\n"; exit; } #1分前にプロセス起動するから指定時間スリープ #srand(time ^ ($$ + ($$ << 15))); #my $useconds = int(rand(12000000)); #my $intval = int ($useconds / 1000000); #my $startupsleeptimemicro = ($startupsleeptime * 1000000) - $useconds; #$reclengthsec = $reclengthsec + $intval + 1; #&writelog("tvrecording: DEBUG SLEEP $startupsleeptime:$useconds:$intval:$startupsleeptimemicro"); # usleep ( $startupsleeptimemicro ); # $recch でウェイト調整入れましょう #52 #my $intval = $recch % 50; # 0〜49 #my $startupsleep = $startupsleeptime - $intval; # 3〜52 (VHF 40-51) #37 my $intval = $recch % 35; # 0〜34 my $startupsleep = $startupsleeptime - $intval; # 3-37 (VHF 25-36,tvk 30) $reclengthsec = $reclengthsec + (60 - $startupsleep) + 1; # if ( $ARGV[2] ne "N"){ &writelog("tvrecording: DEBUG SLEEP $startupsleeptime:$intval:$startupsleep:$reclengthsec"); sleep ( $startupsleep); }else{ &writelog("tvrecording: DEBUG RAPID START"); } if ($recunits > 1){ my $deviceno = $recunits - 1;#3枚差しのとき/dev/video2から使う $recdevice = "/dev/video$deviceno"; $recch = $ARGV[0] ; }else{ #1枚差し $recdevice = "/dev/video0"; $recch = $ARGV[0] ; } &getChCallsign(); #&getRecPath; $outputpath = "$recfolderpath"."/"; if ($ARGV[6] eq "0"){ $outputfile = $outputpath.$ARGV[5]."--"; }else{ $outputfile = $outputpath.$ARGV[5]."-".$ARGV[6]."-"; } #2番目以降のクリップでファイル名指定があったら if ($ARGV[3] ne ""){ # if ($ARGV[3] =~ /[0-9]{8}-[0-9]{4}/){ # $outputfile .= "$ARGV[3]"; # }else{ # $outputfile .= strftime("%Y%m%d-%H%M", localtime(time + 60)); # } $outputfile = $ARGV[3]; $outputfile = &filenameinjectioncheck($outputfile); $outputfilewithoutpath = $outputfile ; $outputfile = $outputpath.$outputfile ; # $outputfile .= "$ARGV[3]"; # $outputfile .= strftime("%Y%m%d-%H%M", localtime(time + 60)); &writelog("tvrecording: DEBUG ARGV[2] ne null \$outputfile $outputfile "); }else{ $outputfile .= strftime("%Y%m%d-%H%M", localtime(time + 60)); chomp($outputfile); $outputfile .= ".m2p"; $outputfilewithoutpath = $outputfile ; &writelog("tvrecording: DEBUG ARGV[2] is null \$outputfile $outputfile "); } @wday_name = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat"); $sleepcounter = 0; $cmd=""; #二重録りなど既に同名ファイルがあったら中断 if ( -e "$outputfile" ){ if ( -s "$outputfile" ){ &writelog("tvrecording :ABORT :recfile $outputfile exist."); exit 1; } } }#end prepare sub setbitrate{ $bitrate = $ARGV[4] ; $bitrate = $bitrate * 1024*1024;#Mbps -> bps $peakbitrate = $bitrate + 350000; $recordbitrate = " --bitrate $bitrate --peakbitrate $peakbitrate "; $stdbitrate = "$bitrate"; $peakbitrate = "$peakbitrate"; }#end setbitrate sub callrecordv4l{ #$frequency = `ivtv-tune -d $recdevice -t $frequencyTable -c $ivtvrecch | awk '{print $2}'|tr -d .`; my $ivtvtuneftype = ''; if ($frequencyTable eq "ntsc-cable-jp"){ $ivtvtuneftype = 'japan-cable'; }else{ $ivtvtuneftype = 'japan-bcast'; } #print "ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch\n"; &writelog("tvrecording DEBUG ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch"); &writelog("tvrecording DEBUG $ENV{PATH}"); $frequency = `env PATH=PATH=/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/bin:/usr/bin:/home/foltia/bin ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch`; &writelog("tvrecording DEBUG frequency:$frequency"); @frequency = split(/\s/,$frequency); $frequency[1] =~ s/\.//gi; $frequency = $frequency[1] ; &writelog("tvrecording DEBUG frequency:$frequency"); my $recordv4lcallstring = "$toolpath/perl/record-v4l2.pl --frequency $frequency --duration $reclengthsec --input $recdevice --directory $recfolderpath --inputnum $capturedeviceinputnum --inputname '$capturedeviceinputName' --freqtable $frequencyTable --bitrate $stdbitrate --peakbitrate $peakbitrate --output $outputfilewithoutpath "; &writelog("tvrecording $recordv4lcallstring"); &writelog("tvrecording DEBUG $ENV{HOME}/.ivtvrc"); $oserr = `env HOME=$toolpath $recordv4lcallstring`; &writelog("tvrecording DEBUG $oserr"); }#end callrecordv4l