epgrec が内部で使っているepgdumpというプログラムが、なんか引数にontv codeというのをとるので、これはontv japanをスクレイピングしているのかと思っていたが、その割にはtsファイルのパスも必要だしどうなってるんだと思ってよくよくソースを読んでみたら、tsファイルを解析していることがわかった。日本の地上デジタル放送はMPEG-2 TSという形式が採られていて、動画データや音声データのほかに時刻情報やら番組情報やら、いろんなメタデータが付加されている。そこらへんの仕様がデジタル放送に使用する番組配列情報(ARIB STD-B10)というARIBが公開している資料に書かれているということなので、読んでみることにした。
MPEG-2 TSファイルの内容はNHKの資料や朋栄IBEの資料に詳しい。すなわち、TSファイルは188バイトのパケットを1単位として構成されていて、パケットの先頭4バイトがヘッダ、残り184バイトがアダプテーションフィールド(ヘッダを拡張したもの)とペイロード(情報本体)のどちらか、または両方となっている。パケットの先頭バイトは必ず0x47であり、ペイロードの中身が何であるかはPIDと呼ばれる13ビットのフィールドで分かる。一連の情報が複数のパケットに分割されることもあり、その場合の先頭パケットはPayload-unit start indicatorフラグが1かどうかで判断できる。パケットが欠落することもあるが、Countinuity indexという4バイトのフィールドがあり、もし欠落していたらこの値が飛ぶので判断できる(16パケット一度に飛んだ場合は判断できない)。
番組情報はEIT(Event Information Table)というテーブルに記述され、PIDは0x12, 0x26, 0x27である。EITテーブルには1つ以上のイベント(=テレビ番組ひとつひとつ)が含まれ、そのイベントにも1つ以上の記述子が含まれている。EITテーブルの定義はARIB STD-B10 第2部の表5-7にあるとおり、以下のようになっている。
フィールド名 | ビット数 |
---|---|
table_id | 8 |
section_syntax_indicator | 1 |
reserved_future_use | 1 |
reserved | 2 |
section_length | 12 |
service_id | 16 |
reserved | 2 |
version_number | 5 |
current_next_indicator | 1 |
section_number | 8 |
last_section_number | 8 |
transport_stream_id | 16 |
original_network_id | 16 |
segment_last_section_number | 8 |
last_table_id | 8 |
(以下繰り返し) | |
event_id | 16 |
start_time | 40 |
duration | 24 |
running_status | 3 |
free_CA_mode | 1 |
descriotors_loop_length | 12 |
<以下繰り返し> | |
descriotor | (2バイト目の数値+16) |
<以上繰り返し> | |
(以上繰り返し) | |
CRC | 32 |
イベントと記述子が複数あるため、一連のパケットのうちどこまでがひとかたまりなのかはsection_lengthの値を見ないと分からない。section_lengthの値は、section_lengthフィールドの後に何バイト続くかであることに注意する必要もある。各記述子は、共通して先頭1バイトが記述子タグ、2バイトが記述子長であるので、先頭2バイトを見ればどの種類の記述子が何バイト続くかが分かる。記述子長も、やはり記述子長フィールドの後に何バイト続くかの数値なので、記述子全体の長さはそれに+2したものになる。それぞれが何回繰り返されるかは、section_length、descriptors_loop_length、descriptor_lengthの値から求められる。パケットの途中でテーブルの記述が終わった場合は、残りが0xFFで埋められる。
どの記述子がどのテーブルにひもづいて登場しうるかはARIB STD-B10 第2部の表6-1に定義されており、EITでは短形式イベント記述子が必須、ほか数項目が任意となっている。短形式イベント記述子は番組名と番組内容を定義するもの(ARIB STD-B10 第1部 図6-32)である。epgdumpなどの既存のtsファイルパーサもこの記述子の内容を見て、どういう番組が何時から何時まで放送されるのか表示している。地デジテレビの番組表表示機能もおそらくこのフィールドを見ているのだろう。
ただ、このフィールドのデータがいまいち使えない。フォーマットが番組によってバラバラなのである。たとえば以下のような感じ (ARIB外字は既存のepgdumpの実装通りに展開):
番組名フィールドの値 | 番組記述フィールドの値 |
---|---|
逆境無頼カイジ -破戒録篇- 「熱風の到来」 | ▽3ヶ月間、耐えに耐え、正規の給料を手にするカイジたち45組!再び地下チンチロにて、にっくき大槻と掛け金上限無しの青天井勝負!!必勝を期して挑むカイジだが… |
DOG DAYS | #8「開戦の日」 |
プリティーリズム・オーロラドリーム「プリズムの輝きはいつもここに」【字】 | 母の日の企画のツアーに参加することとなったあいらとりずむ。そこで母親が遅れて寂しいのに虚勢を張る少女なつきと出会う。りずむは彼女に自分の姿を重ねるのだが…。 |
【字】アニメ もしドラ(10)「みなみは高校野球に感動した」 | この決勝戦に勝てば甲子園出場が決まる。みなみが駆けつけ声援を飛ばす中、一点リードされた九回裏ツーアウト、打席に立ったのは祐之助だった。程高野球部の運命は? |
【字】アニメ GIANT KILLING「#06」 | 【原作】ツジトモ,【脚本】川瀬敏文【監督】紅優【声】関智一,置鮎龍太郎,小野大輔,川島得愛,浅野真澄 |
Aチャンネル #07【字】 | 「夏祭り」女子高生4人のキュートでユルユルなハイスクールライフ! |
スイートプリキュア♪【デ】【字】 | 第13回「ムムム〜ン! セイレーンとハミィの秘密ニャ♪」ハミィが『幸福のメロディ』の歌い手になれたのはセイレーンのおかげ!?セイレーンの過去が明らかに!! |
ざっとみて以下のようなパターンがあるようである:
- サブタイトルを番組名フィールドに置くか、番組記述フィールドに置くか、表示しないか
- 話数を表示するか、しないか。表示する場合はどう表示するか
- その話の要約があるか、番組全体の要約(というかキャッチフレーズ)があるか
録画したアニメのファイルを管理するのに、タイトルと話数とサブタイトルはもっとも重要な要素だといえる。その重要な要素が、短形式イベント記述子からは体系だてて取得しにくい。しょぼいカレンダーなどの人力ソリューションは、おそらくそこら辺の問題からの需要も強いのだろう。ただし、しょぼいカレンダーのヘルプに「編集者が「視聴または録画するデータしか登録してはいけない」というルールがある」というとおり、必ずしもすべてのアニメ情報が配信されるとは限らない。最近だと、黄金の法とかはれときどきぶたの再放送などが配信されなかった。
なんかいい方法はないかとARIBのドキュメントを引き続き読み進めて行ったら、「シリーズ記述子」という便利そうなものが定義されていることが分かった。
この記述子は、シリーズ化された複数のイベントを識別するために用いる。個々のシリーズはシリーズ識別により識別される。受信機では、シリーズ化されたイベント群に対して一括の操作(予約等)を行う際に用いることができる。
シリーズ記述子は記述子タグ0xD5で定義され、以下のフィールドを持つ:
- シリーズ識別
- 再放送ラベル
- 編成パターン (週に1回放送とか、帯番組だとか)
- 有効期限フラグ
- 有効期限 (最終話が認識できなかった場合、ここで指定した日を過ぎたら放送終了とみなす)
- 話数
- 番組総数
- シリーズ名
こんな便利な情報が定義されているなら話は早い。再放送ラベルを見れば、「もしドラ」や「バクマン」の同じ話がなんども録画されるのを避けられるし、シリーズ名や話数が取れるので録画したファイルのネーミングに使える。(サブタイトルを定義するフィールドがないことに気づいたが、短形式イベント記述子から正規表現とか使って持ってこれないこともないだろう)
ということで、シリーズ記述子を捕まえるべく、TSファイルから記述子を取得するコードを書いてみた。
実行結果は以下のとおりである:
テーブル識別 | NHK | ETV | NTV | TBS | CX | EX | TX | MX | BSNTV | 中身 |
---|---|---|---|---|---|---|---|---|---|---|
0x004E | 78 | 118 | 79 | 79 | 39 | 119 | 118 | 234 | 78 | EIT(自ストリームの現在と次の番組) |
0x004F | 304 | EIT(他ストリームの現在と次の番組) | ||||||||
0x0050 | 62 | 113 | 138 | 56 | 103 | 155 | 162 | 192 | 188 | EIT(自ストリーム、スケジュール) |
0x0051 | 12 | 17 | 24 | 10 | 5 | 27 | 44 | 37 | 14 | EIT(自ストリーム、スケジュール) |
0x0058 | 9 | 27 | 30 | 73 | 34 | 18 | 17 | 43 | 19 | EIT(自ストリーム、スケジュール) |
0x0059 | 8 | 19 | 13 | 11 | 13 | 35 | 39 | 34 | 20 | EIT(自ストリーム、スケジュール) |
0x0060 | 1029 | EIT(他ストリーム、スケジュール) | ||||||||
0x0061 | 254 | EIT(他ストリーム、スケジュール) |
記述子タグ | NHK | ETV | NTV | TBS | CX | EX | TX | MX | BSNTV | 中身 |
---|---|---|---|---|---|---|---|---|---|---|
0x004D | 352 | 859 | 562 | 302 | 55 | 641 | 692 | 1050 | 4855 | 短形式イベント記述子 |
0x004E | 221 | 736 | 810 | 1772 | 423 | 597 | 809 | 487 | 74 | 拡張形式イベント記述子 |
0x0050 | 352 | 859 | 562 | 302 | 55 | 641 | 692 | 1050 | 4823 | コンポーネント記述子 |
0x0054 | 352 | 852 | 558 | 302 | 54 | 637 | 692 | 1042 | 4698 | コンテント記述子 |
0x00C1 | 352 | 859 | 562 | 302 | 55 | 641 | 692 | 1050 | 4811 | デジタルコピー制御記述子 |
0x00C4 | 363 | 910 | 572 | 302 | 55 | 660 | 708 | 1050 | 4945 | 音声コンポーネント記述子 |
0x00C7 | 144 | 240 | 922 | 461 | 48 | 1061 | 948 | 1050 | 1393 | データコンテンツ記述子 |
0x00CB | 56 | CA契約情報記述子 | ||||||||
0x00D6 | 511 | 1314 | 834 | 392 | 496 | 939 | 1202 | 836 | 5083 | イベントグループ記述子 |
なんということだ、シリーズ記述子がEITパケットに含まれていない!
ていうか、そういう記述子が含まれているなら既存の類似実装が見逃すはずがないのであった。たとえば、Rec10のepgdump/eit.cは、実際に配信されているコンテント記述子・コンポーネント記述子・音声コンポーネント記述子は値を取得している(738行目付近以降)が、シリーズ記述子はパースしたあとデータを取り込んでいない。
ということで、EPGデータは全放送データが含まれていて量はよいが内容が適切に表現されていないところがあって質が良くない。しょぼいカレンダーはフォーマットがしっかりしていて内容を再利用しやすいが配信されない番組がある。両者をおりまぜていい感じに使うのがよい。