この記事は DTV Advent Calendar 2015 10日目の記事です。
前回、nodeでMPEG-2 TSを扱えるnode-aribts をつくったという話でしたが、実際にそれを使って何が出来るのか、サンプルを紹介したいと思います。
TSのドロップをチェックする
aribts.TsStreamは名前の通り、TSのストリームで、SIや情報などのイベントを発生させます。
ドロップはdropイベントで取得できます。
また、全体の情報はinfoイベントで取得できます。
以下のサンプルでは、ドロップの出力と、全体の情報の一覧を表示します。
"use strict";
const fs = require("fs");
const aribts = require("aribts");
const TsStream = aribts.TsStream;
const readStream = fs.createReadStream(process.argv[2]);
const tsStream = new TsStream();
readStream.pipe(tsStream);
tsStream.on("data", () => {});
tsStream.on("drop", pid => {
console.log(pid: 0x${("000" + pid.toString(16)).slice(-4)});
});
tsStream.on("info", data => {
console.log("");
console.log("info:");
Object.keys(data).forEach(key => {
console.log(0x${("000" + parseInt(key, 10).toString(16)).slice(-4)}: packet: ${data[key].packet}, drop: ${data[key].drop}, scrambling: ${data[key].scrambling});
});
});
現在の番組情報を取得する
時間や番組情報などはaribts.TsUtilを使うと簡単に処理できます。
tsUtil.add~を使うことによって、SIを追加し、それぞれ適切に処理してくれます。
例えば、時間はTDTまたはTOT、サービスはSDT、そして番組情報はEITを入力すると取得できるようになります。
以下のサンプルでは、最初から30秒後に現在の番組情報を出力します。
"use strict";
const fs = require("fs");
const util = require("util");
const aribts = require("aribts");
const TsStream = aribts.TsStream;
const TsUtil = aribts.TsUtil;
const readStream = fs.createReadStream(process.argv[2]);
const tsStream = new TsStream();
const tsUtil = new TsUtil();
var time = null;
var ids = null;
readStream.pipe(tsStream);
tsStream.on("data", () => {});
tsStream.on("eit", (pid, data) => {
tsUtil.addEit(pid, data);
if (time === null) {
if (tsUtil.isTime()) {
time = tsUtil.getTime();
} else {
return;
}
}
if (ids === null) {
if (tsUtil.isOriginalNetworkId() && tsUtil.isTransportStreamId() && tsUtil.isServiceIds()) {
ids = {
onid: tsUtil.getOriginalNetworkId(),
tsid: tsUtil.getTransportStreamId(),
sid: tsUtil.getServiceIds()[0]
};
} else {
return;
}
}
if (tsUtil.getTime().getTime() - time.getTime() < 30 * 1000) return;
if (!tsUtil.isPresent(ids.onid, ids.tsid, ids.sid)) return;
console.log(util.inspect(tsUtil.getPresent(ids.onid, ids.tsid, ids.sid), {depth: null}));
tsStream.removeAllListeners();
readStream.unpipe(tsStream);
tsStream.end();
});
tsStream.on("sdt", (pid, data) => {
tsUtil.addSdt(pid, data);
});
tsStream.on("tdt", (pid, data) => {
tsUtil.addTdt(pid, data);
});
tsStream.on("tot", (pid, data) => {
tsUtil.addTot(pid, data);
});
以下がサンプルの出力です。
{ table_id: 78,
version_number: 29,
event_id: 18974,
start_time: Thu Jan 15 2015 02:45:00 GMT+0900 (東京 (標準時)),
duration: 1800,
running_status: 0,
free_CA_mode: 0,
short_event:
{ table_id: 78,
version_number: 29,
ISO_639_language_code: 'jpn',
event_name: '[新]水曜アニメ・水もん ガールズ&パンツァー',
text: ' ' },
extended_event:
{ table_id: 78,
version_number: 29,
ISO_639_language_code: 'jpn',
items:
{ '◇番組内容': ' ',
'◇出演者': '西住 みほ: 渕上 舞rn武部 沙織: 茅野 愛衣rn五十鈴 華: 尾崎 真実rn秋山
優花里: 中上 育実rn冷泉 麻子: 井口 裕香',
'◇監督・演出': '監督:水島 努/構成・脚本:吉田玲子/キャラクター原案:島田フミカネ/キャラ
クターデザイン・総作画監督:杉本 功',
'◇制作': 'アニメーション制作:アクタス' },
text: '' },
component:
{ table_id: 78,
version_number: 29,
stream_content: 1,
component_type: 179,
component_tag: 0,
ISO_639_language_code: 'jpn',
text: '映像',
component_text: '映像1080i(1125i)、アスペクト比16:9 パンベクトルなし' },
content:
{ table_id: 78,
version_number: 29,
contents:
[ { content_nibble_level_1: 7,
content_nibble_level_2: 0,
user_nibble_1: 15,
user_nibble_2: 15,
content_nibble_level_1_text: 'アニメ/特撮',
content_nibble_level_2_text: '国内アニメ' } ] },
audio_component:
{ table_id: 78,
version_number: 29,
stream_content: 2,
component_type: 3,
component_tag: 16,
stream_type: 15,
simulcast_group_tag: 255,
ES_multi_lingual_flag: 0,
main_component_flag: 1,
quality_indicator: 1,
sampling_rate: 7,
ISO_639_language_code: 'jpn',
text_char: '日本語',
audio_mode_text: '2/0モード(ステレオ)',
quality_indicator_text: 'モード1',
sampling_rate_text: '48kHz' } }
まだまだですが…
まだ開発途中のため、バグがあったり、大幅な仕様変更もあるかもしれませんが、暖かい目で見ていただければと思います。
明日は、(私の大いなる圧力で)ろっとさんです。CATVの話らしいので気になる…
b25関連を実装するとはチャレンジャーだね