事象の水平線

個人的ブックマーク代わりなメモ書きブログ。 地球は丸いよ。↓このへん。

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PageTop
recpt1をhttp版に改造し、クライアントPCのTVtest(with BonDriver_HTTP.dll)からリアルタイム視聴を使っている訳ですが、リアルタイムで見ているときに予約録画が始まりチューナーが足りないと予約録画が失敗するので、EPGrec側を改造してみたメモ。

ちなみに、recpt1のhttp版に関しては
recpt1 http版 怒られながら入れてみる
recpt1 http版 プロセスが落ちたときにphpで手動でブラウザからexecする
recpt1 カテゴリー
あたり参照

ついでに、TVtest(with BonDriver_HTTP.dll)についても
TVtest with BonDriver_HTTP.dll でリアルタイム視聴
の記事を書く予定参照




動作の概要としては、予約録画が始まるときにdo-record.shが走るので、そこでチューナー数が足りないようならhttp版のdaemonをkillする。と言うだけの話。
で、予約録画が終わってチューナーに余裕がありそうならhttp版daemonを復活。
さらに、リアルタイム視聴しているときにたまにhttp版がよく分からない待ち状態に入り視聴できなくなるので、手動でブラウザから再起動できるようにもする。

ちなみに、考慮している環境
・PT3が一枚のみの場合  (それ以上の場合は適度に定数をいじってください)
・配信のポートは8888  (新規導入ならfirewallでudp,tcp8888開放とか)



/var/www/epgrec/do-record.sh
とりあえず自分の環境のをまんま載せておきます。関係するのは赤部分のみ。
#!/bin/bash
echo "CHANNEL : $CHANNEL"
echo "DURATION: $DURATION"
echo "OUTPUT : $OUTPUT"
echo "TUNER : $TUNER"
echo "TYPE : $TYPE"
echo "MODE : $MODE"
echo "SID : $SID"

RECORDER=/usr/local/bin/recpt1

# fail safe
case $CHANNEL in
101|102|191|192|193|200|201|202)
if [ $SID = 'hd' ]; then
SID=$CHANNEL
fi ;;
esac
if [ -z $SID ]; then
SID='hd'
fi

# recpt1-httpを終了
recpt1LivePID=`ps axl | grep recpt1 | grep 'http 8888' | awk '{print$3}'`;
if [ `ps -el | grep 'do-record.sh' | wc -l` -gt 2 ]; then
sudo kill -9 $recpt1LivePID ;
fi


if [ ${MODE} = 0 ]; then
# MODE=0では必ず無加工のTSを吐き出すこと because of epg
$RECORDER --b25 --strip $CHANNEL $DURATION ${OUTPUT} >/dev/null
elif [ ${MODE} = 1 ]; then
if [ ${CHANNEL} = "17" ] || [ ${CHANNEL} = "18" ]; then
# テレビ朝日とテレビ東京はFullTS
$RECORDER --b25 --strip $CHANNEL $DURATION ${OUTPUT} >/dev/null
else
# 目的のSIDのみ残す
$RECORDER --b25 --strip --sid $SID $CHANNEL $DURATION ${OUTPUT} >/dev/null
fi
elif [ ${MODE} = 2 ]; then
if [ ${CHANNEL} = "17" ] || [ ${CHANNEL} = "18" ]; then
# テレビ朝日とテレビ東京はFullTS
$RECORDER --b25 --strip $CHANNEL $DURATION ${OUTPUT} >/dev/null
else
# 目的のSIDのみ残す
$RECORDER --b25 --strip --sid $SID $CHANNEL $DURATION ${OUTPUT} >/dev/null
fi
/usr/local/bin/PSconvert.sh ${OUTPUT} >/dev/null
echo "------ do-record.sh MODE2 complete "`date` >> /var/log/autosuspend.log
fi

# recpt1-httpを復活
sleep 1
recpt1LivePID=`ps axl | grep recpt1 | grep 'http 8888' | awk '{print$3}'`;
if [ `ps -el | grep recpt1 | wc -l` -lt 2 ]; then
if [ `echo $recpt1LivePID | wc -w` -eq 0 ]; then
/usr/local/bin/reload_recpt1.sh
fi
fi

まぁ、難しいことしてないんで動作の詳細説明は省略。(ぉぃ
最後の復活する際に、http版が走っていない時のみ復活の動作をさせているのは、リアルタイム視聴をしているときに不用意にrecpt1http版が再起動するのを避けるため。
sleep 1は気休めです。



/var/www/html/reload_recpt1.php
うまくリアルタイム視聴できなくなった時に手動でrecpt1http版を再起動するphp
phpを呼び出すフォームとかは『recpt1 http版 プロセスが落ちたときにphpで手動でブラウザからexecする』参照
<html>
<head>
<MEtA http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="refresh" content="20;URL=http:../">
<?php
//if submit has been pressed
if(isset($_POST['submit'])){
#reload_recpt1
exec("/usr/local/bin/reload_recpt1.sh");

#HTML
echo('<title>recpt1リロード終了</title>
</head>
<body><br><br><br>
recpt1をリロードしました。<br>
20秒後にHomeに戻ります。<br><br>
<font color="#0000FF"><b>チャンネルを切り替える</b>か、<b>TVTestを再起動</b></font>してください。<br><br>
それでも写らない場合、<b><font size="+2" color="#FF0000">2番組以上の録画をしている</font></b>可能性があります。<br>
その場合録画が優先されます。
');
}else{
echo('<title>不正に呼び出された</title></head><body>不正に呼び出されました。<br>20秒後にHomeに戻ります。');
}
php?>

</body>
</html>
phpの設定やパーミッションなどは良しなに・・・


/usr/local/bin/reload_recpt1.sh
do-record.shとreload_recpt1.phpが呼び出す、recpt1http版を再起動するスクリプト
分けたのは単に構築に至る紆余曲折によりこうなっただけで、それ以上の意味はないです。
#!/bin/bash

recpt1LivePID=`ps axl | grep recpt1 | grep 'http 8888' | awk '{print$3}'`;
if [ `echo $recpt1LivePID | wc -w` -gt 0 ]; then
sudo kill -9 $recpt1LivePID ;
fi

/usr/local/bin/recpt1 --b25 --strip --http 8888 > /dev/null 2>&1 &

recpt1http版は走っているが、よく分からない待ち状態になっていることがあるので、単に再度走らせるだけでなく確実にkillしてから起動している。



/var/www/epgrec/getepg.php
cronでgetepg.phpが走る(EPG取得)とこれもチューナーも使うしdo-record.shも使う。ので、1番組(以上)の録画中にリアルタイム視聴をしてるとEPG取得が行われるときにリアルタイム視聴が止まることになる。
デフォルトでEPGは2時間おきに取得になっているので、リアルタイムで見てるときにEPG更新されなくても、ま~いいやろ、と言うことで予約録画中はEPG取得をスルーするようにした。
他にも多少いじっているけれど、どうもEPGrecのバージョンでスクリプトが結構違うようでどれが最新か、自分の使っているのが最新かよく分からないので全文を載せておきます。やっていることは単純なので、環境に合わせて改造してください。
GPLだかGNUだかライセンスで問題があれば連絡ください。ライセンスとかよー分かりません
#!/usr/bin/php
<?php
$script_path = dirname( __FILE__ );
chdir( $script_path );
include_once( $script_path . '/config.php');
include_once( INSTALL_PATH . '/DBRecord.class.php' );
include_once( INSTALL_PATH . '/Reservation.class.php' );
include_once( INSTALL_PATH . '/Keyword.class.php' );
include_once( INSTALL_PATH . '/Settings.class.php' );
include_once( INSTALL_PATH . '/storeProgram.inc.php' );
include_once( INSTALL_PATH . '/recLog.inc.php' );


// SIGTERMシグナル
function handler( $signo = 0 ) {
// とりあえずシグナルは無視する
}

// デーモン化
function daemon() {
if( pcntl_fork() != 0 )
exit();
posix_setsid();
if( pcntl_fork() != 0 )
exit;
pcntl_signal(SIGTERM, "handler");

fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
}

function check_file( $file ) {
// ファイルがないなら無問題
if( ! file_exists( $file ) ) return true;

// 1時間以上前のファイルなら削除してやり直す
if( (time() - filemtime( $file )) > 3600 ) {
@unlink( $file );
return true;
}

return false;
}

// 子プロセス起動
function epgrec_exec( $cmd, $env = null ) {
$descspec = array(
0 => array( 'file','/dev/null','r' ),
1 => array( 'file','/dev/null','w' ),
2 => array( 'file','/dev/null','w' ),
);
$p = proc_open( $cmd, $descspec, $pipes, INSTALL_PATH, $env );
if( is_resource( $p ) ) return $p;

return false;
}

daemon();

$settings = Settings::factory();

// ユーザー/グループの切り替えを試みる
if(intval($settings->use_power_reduce) != 0 ) {
$userinfo = posix_getpwnam( $settings->www_user );
$groupinfp = posix_getgrnam( $settings->www_group );

posix_setgid( $groupinfo['gid'] );
posix_setuid( $userinfo['uid'] );
}


// 後方互換性
if( ! defined( "BS_EPG_CHANNEL" ) ) define( "BS_EPG_CHANNEL", "211" );
if( ! defined( "CS1_EPG_CHANNEL" ) ) define( "CS1_EPG_CHANNEL", "CS8" );
if( ! defined( "CS2_EPG_CHANNEL" ) ) define( "CS2_EPG_CHANNEL", "CS24" );

$bs_proc = false;
$gr_procs = array();
$cs1_proc = false;
$cs2_proc = false;


$temp_data_bs = $settings->temp_data.".bs";
$temp_data_cs1 = $settings->temp_data.".cs1";
$temp_data_cs2 = $settings->temp_data.".cs2";
$temp_data_gr = $settings->temp_data.".gr";

if( file_exists( $settings->temp_data ) ) @unlink( $settings->temp_data );


// forhttp////////////////////////////////////////////
$num = DBRecord::countRecords( RESERVE_TBL, "WHERE complete = '0' AND endtime > now() AND starttime < addtime( now(), '00:15:00')" );
if($num > 0) {
reclog("EPG更新をスルー");
exit();
}





// BSを処理する
if( $settings->bs_tuners != 0 ) {
// 録画重複チェック
$num = DBRecord::countRecords( RESERVE_TBL, "WHERE complete = '0' AND (type = 'BS' OR type = 'CS') AND endtime > now() AND starttime < addtime( now(), '00:03:05')" );
if($num < $settings->bs_tuners && check_file($temp_data_bs)) {
$cmdline = "CHANNEL=".BS_EPG_CHANNEL." DURATION=180 TYPE=BS TUNER=0 MODE=0 OUTPUT=".$temp_data_bs." ".DO_RECORD . " >/dev/null 2>&1";
// logに情報を追加
reclog("getepg:: BS".BS_EPG_CHANNEL." EPG取得用TSファイルの保存開始");
exec( $cmdline );
// logに情報を追加
reclog("getepg:: BS".BS_EPG_CHANNEL." EPG取得用TSファイルの保存完了");

//EPG番組表更新
$cmdline = INSTALL_PATH."/storeProgram.php BS ".$temp_data_bs;
$bs_proc = epgrec_exec( $cmdline );
// チューナーのチャンネル切り替えの為の待ち時間を追加
sleep((int)$settings->rec_switch_time);
}

// CS
if ($settings->cs_rec_flg != 0) {
$num = DBRecord::countRecords( RESERVE_TBL, "WHERE complete = '0' AND (type = 'BS' OR type = 'CS') AND endtime > now() AND starttime < addtime( now(), '00:03:05')" );
if($num < $settings->bs_tuners && check_file($temp_data_cs1)) {

$cmdline = "CHANNEL=".CS1_EPG_CHANNEL." DURATION=120 TYPE=CS TUNER=0 MODE=0 OUTPUT=".$temp_data_cs1." ".DO_RECORD . " >/dev/null 2>&1";
// logに情報を追加
reclog("getepg:: CS".CS1_EPG_CHANNEL." EPG取得用TSファイルの保存開始");
exec( $cmdline );
// logに情報を追加
reclog("getepg:: CS".CS1_EPG_CHANNEL." EPG取得用TSファイルの保存完了");

//EPG番組表更新
$cmdline = INSTALL_PATH."/storeProgram.php CS1 ".$temp_data_cs1;
$cs1_proc = epgrec_exec($cmdline);
// チューナーのチャンネル切り替えの為の待ち時間を追加
sleep((int)$settings->rec_switch_time);
}

$num = DBRecord::countRecords( RESERVE_TBL, "WHERE complete = '0' AND (type = 'BS' OR type = 'CS') AND endtime > now() AND starttime < addtime( now(), '00:03:05')" );
if( ($num < $settings->bs_tuners) && check_file($temp_data_cs2) ) {
$cmdline = "CHANNEL=".CS2_EPG_CHANNEL." DURATION=120 TYPE=CS TUNER=0 MODE=0 OUTPUT=".$temp_data_cs2." ".DO_RECORD . " >/dev/null 2>&1";
// logに情報を追加
reclog("getepg:: CS".CS2_EPG_CHANNEL." EPG取得用TSファイルの保存開始");
exec( $cmdline );
// logに情報を追加
reclog("getepg:: CS".CS2_EPG_CHANNEL." EPG取得用TSファイルの保存完了");

//EPG番組表更新
$cmdline = INSTALL_PATH."/storeProgram.php CS2 ".$temp_data_cs2;
$cs2_proc = epgrec_exec( $cmdline );
// チューナーのチャンネル切り替えの為の待ち時間を追加
sleep((int)$settings->rec_switch_time);
}
}
}

// 地上波を処理する
if( $settings->gr_tuners != 0 ) {
foreach( $GR_CHANNEL_MAP as $key=>$value ){
// 録画重複チェック
$num = DBRecord::countRecords( RESERVE_TBL, "WHERE complete = '0' AND type = 'GR' AND endtime > now() AND starttime < addtime( now(), '00:01:10')" );
if($num < $settings->gr_tuners && check_file($temp_data_gr.$value."")) {
$cmdline = "CHANNEL=".$value." DURATION=60 TYPE=GR TUNER=0 MODE=0 OUTPUT=".$temp_data_gr.$value." ".DO_RECORD . " >/dev/null 2>&1";
// logに情報を追加
reclog("getepg:: 地上波GR".$value." EPG取得用TSファイルの保存開始");
exec( $cmdline );
// logに情報を追加
reclog("getepg:: 地上波GR".$value." EPG取得用TSファイルの保存完了");

//EPG番組表更新
$cmdline = INSTALL_PATH."/storeProgram.php GR ".$temp_data_gr.$value." ".$key;
$gr_procs[] = epgrec_exec( $cmdline );
// チューナーのチャンネル切り替えの為の待ち時間を追加
sleep((int)$settings->rec_switch_time);
}
}
}

// 終了を待つ
// 一時的にdefunctするがまあいいや
$counter = 0;
do {
sleep(1);

$counter = 0;
if( count($gr_procs) != 0 ) {
foreach( $gr_procs as $proc ) {
$status = proc_get_status( $proc );
if( $status['running'] ) $counter++;
}
}

if( $bs_proc !== false ){
$status = proc_get_status($bs_proc);
if( $status['running'] ) $counter++;
}

if( $cs1_proc !== false ){
$status = proc_get_status($bs_proc);
if( $status['running'] ) $counter++;
}

if( $cs2_proc !== false ){
$status = proc_get_status($bs_proc);
if( $status['running'] ) $counter++;
}

} while( $counter != 0 );


garbageClean(); // 不要プログラム削除
doKeywordReservation(); // キーワード予約

reclog( "EPG更新終了" ); // 追加

if( intval($settings->use_power_reduce) != 0 ) {
if( file_exists(INSTALL_PATH. "/settings/wakeupvars.xml") ) {
$wakeupvars_text = file_get_contents( INSTALL_PATH. "/settings/wakeupvars.xml" );
$wakeupvars = new SimpleXMLElement($wakeupvars_text);

// getepg終了時を書込み
$wakeupvars->getepg_time = time();
// 起動理由を調べる
if( strcasecmp( "getepg", $wakeupvars->reason ) == 0 ) {
// 1時間以内に録画はないか?
$count = DBRecord::countRecords( RESERVE_TBL, " WHERE complete <> '1' AND starttime < addtime( now(), '01:00:00') AND endtime > now()" );
if( $count != 0 ) { // 録画があるなら録画起動にして終了
$wakeupvars->reason = "reserve";
}
else {
exec( $settings->shutdown . " -h +".$settings->wakeup_before );
}
}
$wakeupvars->asXML(INSTALL_PATH. "/settings/wakeupvars.xml");
}
}
exit();
?>
現在or今から15分以内に予約録画がある場合はEPG更新をスルー


それぞれを改造or作成し、それぞれの場所に置いてください。
PCの起動時やスリープ復帰時のrecpt1http版の起動やdaemon化は『recpt1 http版 怒られながら入れてみる』あたりを参照

また、killでsudo使うので、visudoでapacheに権限をあげてください。
apache ALL=(ALL) NOPASSWD: /usr/bin/kill とかかな。→visudo参照

do-record.shでkillしてすぐに録画用にrecpt1が走ってるけど今のところチューナーの切り替え等で問題は出てないです。
録画の開始が遅れることも特にないです。
EPGrecUNAに移ったほうがいいのかもしれないけれど、これで更に不具合も一個減ったしこのままでもいっかな~
自己責任でどうぞ。
スポンサーサイト

PageTop

コメント

 ※
 ※
管理者にだけ表示を許可する
  ※ 必須項目です

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。