chinachuで自動エンコード

chinachuで録画が終了したタイミングで、自動的にエンコードを行うスクリプトを作りました。
ディスカバリーチャンネル等では、同じ番組の同じエピソードが複数回放送される事がありますが、
そのような場合は、2回目からはエンコせずに終了する機能を持ちます。

動作概要:
ChinachuのConfig.jsonに
“recordedCommand”: “./recCheck.sh”,
を追記することにより、録画終了時にrecCheck.shが呼ばるようになります。
recCheck.sh内ではchinachuのAPIをコールし、現在迄に録画した全ての番組情報を取得します。
また、recCheck.shは今回録画した番組の情報をJSON形式で受け取り、
これら2つの情報をrecCheck.jsに渡します。
recCheck.jsは女子小学生です。

嘘です。
recChheck.jsは、今回録画した番組の情報と過去の録画情報を比較し、
番組名と番組詳細が一致した場合は、何もせずに終了します。
(コード内のコメントを削除することにより、終了前に録画したtsファイルを削除することもできます。)

上記チェックで新規録画番組と判定された場合は、
番組ごとの録画オプション設定を行います。

コード中のサンプルの例では、
・番組名(finishedObj.title)に”名車再生”の文字が含まれる場合 →
名車再生クラシックカーディーラーズは、二ヶ国語番組なので、英語の音声(右チャンネル)音声を削除したうえで、モノラル化します。
・番組フルタイトル(finishedObj.fullTitle)に”【映】”が含まれる場合 →
映画は、ffmpegのプリセットslowを使い、ビットレート7MBpsでエンコードします。

また、エンコード作業自身の負荷が録画プロセスに影響を及ぼさぬ用に
ffmpeg実行時の優先度を下げています。
また、コード中のコメントを削除すれば、通常の優先度でエンコードすることもできます。
エンコード終了時にログファイルを残しますので、エラー時の原因究明に使って下さい。
ログファイルの保存場所はrecChech.sh内に設定があります。

recCheck.sh / recCheck.js共にファイル内のコメントに注意事項がありますので、
よくお読みの上で、自己責任にて導入して下さい。

それと、recCheck.sh/js自身の実行権限と、ログファイル、エンコ済みファイル倉庫の書き込み権限にも注意。
当たり前ですが、大事な録画ファイルが消えても当方は一切関知できませんので、よろちくね。

ZIPでクレって人は↓から
http://sonic-labo.xsrv.jp/gosogoso/wp-content/uploads/2015/11/recCheck.zip

#!/bin/sh

# author katsuwo. 
#sonic-laboの屋号でフリーランスプログラマーしてます。お仕事お待ちしてます。
#http://sonic-labo.com/


#ログインアカウント ブラウザでchinachuのページを表示する時のアカウントと同一の物を指定(※)
user=アカウント名
passwd=パスワード

#recorded objectを得る IPは各自の環境に合わせて変更の事
query=`curl -s --user ${user}:${passwd} http://192.168.10.111:10772/api/recorded.json`

#logFile
time=`date +%s`
logExt=".log"

#下記の例は/mnt/HDD2/log以下にログファイルを作成。保存ディレクトリに書き込み許可を忘れずに(※)
logFile="/mnt/HDD2/log/log"$time$logExt

#node実行  nodeの実行パスは各自の環境に合わせて変更の事。chinachuの実行パス以下の.naveに在ります(※)
/home/chinachu/chinachu/.nave/node recCheck.js "${query}" "${2}" 2> $logFile
var fs = require('fs');
var child_process = require('child_process').execSync;


//ログファイルに録画した番組情報を出力
console.error("-----------------番組情報-------------------\n");
console.error(process.argv[3] + '\n');
console.error("--------------------------------------------\n");

//引数チェック
//if (process.argv.length <4) return;
 
//エンコ済みファイル倉庫(最後に"/"必須(※)
var encodedDir = "/mnt/HDD2/";

//録画した番組のオブジェクトを得る
var finishedObj = JSON.parse(process.argv[3]);

//録画履歴のオブジェクトを得る
var recordedObj = JSON.parse(process.argv[2]); 

//過去の録画情報と今回の録画情報を比較する
for(var i in recordedObj) {

	//タイトルと詳細が一致した場合
	if (recordedObj.title == finishedObj.title &&
		recordedObj.detail == finishedObj.detail){

		//何もせず終了
		console.error("this movie is already encoded.\nNothing to do.");

		//元ファイルを削除して終了
//		fs.unlinkSync(finishedObj.recorded);
//		console.error("this movie is already encoded.\nDelete source file.");

		return;
	}
}

//------------------------
//エンコる
//------------------------
var recOpt = "";

//番組タイトルから録画オプションを決める(※)
//タイトルに"名車再生が含まれる時は・・・
if (finishedObj.title.indexOf("名車再生") != -1 ){

	//名車再生クラシックカーディーラーズは、音声左チャンネルのみ使用
	recOpt = ' -af "pan=0x3:c0=c0:c1=c0"';
}

//フルタイトルに
else if (finishedObj.fullTitle.indexOf("【映】") != -1 ){

	//映画はビットレート指定& preset slow
	recOpt = "  -b:v 7000k -preset slow ";
}


//var ffmpeg = __dirname + "/usr/bin/ffmpeg";				//←通常の優先度でエンコする
var ffmpeg = "nice -n 15 " + __dirname + "/usr/bin/ffmpeg"; //←システム全体の負荷を考慮し、エンコの優先度を落とす

//ffmpegの入力ファイルオプション
var optIn = ' -i ' + '"' + finishedObj.recorded + '"';

//出力ファイルの拡張子(先頭に"."必須)
var outExt = ".mp4";

//"/mnt/HDD2/ts/[151111-1355][GR25][PT2-T1]情報ライブ ミヤネ屋.ts",
// ↓ こんなんにする
//”[151111-1355][GR25][PT2-T1]情報ライブ ミヤネ屋"
var slashPos = finishedObj.recorded.lastIndexOf("/");
var tmpOutFile = finishedObj.recorded.slice(slashPos+1,finishedObj.recorded.length - 3);

//”[151111-1355][GR25][PT2-T1]情報ライブ ミヤネ屋"
// ↓ こんなんにする
//”エンコ済みファイル倉庫パス/[151111-1355][GR25][PT2-T1]情報ライブ ミヤネ屋.mp4"
var outFile = " " + '"' + encodedDir + tmpOutFile + outExt + '"';

//コーデック指定オプション(先頭に" "(空白)必須)
var codecOpt = " -vcodec libx264";

//エンコ実行文字列
var execString = ffmpeg + optIn + codecOpt + recOpt + outFile;

console.error("------------ffmpeg execute string-----------\n");
console.error(execString + '\n');
console.error("--------------------------------------------\n");

//ffmpeg起動
child_process(execString, function(err, stdout, stderr){
	
	//子プロセスでエラー時に記録
	var logText = "Error:" + err + "\n" + "stdout:" + stdout + "\n" + "stderr:" + stderr + "\n"; 
	console.error("--------------ffmpeg error------------------\n");
    console.error(logText + '\n');
	console.error("--------------------------------------------\n");
});
  • このエントリーをはてなブックマークに追加

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です