@danything/arib 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +82 -0
- package/README.md +65 -2
- package/dist/ait.d.ts +97 -0
- package/dist/ait.js +205 -0
- package/dist/aribtext-gaiji.d.ts +25 -0
- package/dist/aribtext-gaiji.js +69 -0
- package/dist/aribtext.d.ts +31 -0
- package/dist/aribtext.js +314 -0
- package/dist/b24-tables.d.ts +50 -0
- package/dist/b24-tables.js +410 -0
- package/dist/b24caption.d.ts +98 -0
- package/dist/b24caption.js +987 -0
- package/dist/bml-protocol.d.ts +143 -0
- package/dist/bml-protocol.js +12 -0
- package/dist/bml.d.ts +87 -0
- package/dist/bml.js +489 -0
- package/dist/bytes.d.ts +20 -0
- package/dist/bytes.js +45 -0
- package/dist/caption-text.d.ts +122 -0
- package/dist/caption-text.js +39 -0
- package/dist/drcs-smooth.d.ts +52 -0
- package/dist/drcs-smooth.js +163 -0
- package/dist/dsmcc.d.ts +92 -0
- package/dist/dsmcc.js +191 -0
- package/dist/eit.d.ts +316 -0
- package/dist/eit.js +708 -0
- package/dist/language.d.ts +7 -0
- package/dist/language.js +20 -0
- package/dist/multipart.d.ts +43 -0
- package/dist/multipart.js +194 -0
- package/dist/pes.d.ts +99 -0
- package/dist/pes.js +231 -0
- package/dist/psi.d.ts +169 -0
- package/dist/psi.js +497 -0
- package/dist/service-filter.d.ts +95 -0
- package/dist/service-filter.js +248 -0
- package/dist/synth-av.d.ts +51 -0
- package/dist/synth-av.js +298 -0
- package/dist/synth-caption.d.ts +38 -0
- package/dist/synth-caption.js +115 -0
- package/dist/synth.d.ts +183 -0
- package/dist/synth.js +508 -0
- package/package.json +30 -4
package/dist/eit.d.ts
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EIT を読む。番組表の中身そのもの。
|
|
3
|
+
*
|
|
4
|
+
* **denpa が自分で読む。** 番組表を誰かに聞きに行かないので、**チューナーが
|
|
5
|
+
* 空いているだけ並列に回せる**し、録画で開いているチャンネルのぶんはただで
|
|
6
|
+
* 手に入る ([agent.md](https://github.com/danything/denpa/blob/main/docs/agent.md))。
|
|
7
|
+
*
|
|
8
|
+
* 扱うのは2種類。
|
|
9
|
+
*
|
|
10
|
+
* - **EIT[p/f]** (table_id 0x4E) … いま流れている番組と次の番組。**放送に追従する。**
|
|
11
|
+
* 野球で延びた終了時刻はここに出る
|
|
12
|
+
* - **EIT[schedule]** (table_id 0x50〜0x5F) … 数日先までの番組表
|
|
13
|
+
*
|
|
14
|
+
* どちらも PID 0x0012 に流れてくる。
|
|
15
|
+
*/
|
|
16
|
+
interface EventAudio {
|
|
17
|
+
componentType: number;
|
|
18
|
+
langs: string[];
|
|
19
|
+
samplingRate?: number;
|
|
20
|
+
/**
|
|
21
|
+
* 放送が自分で付けた名前。**「主音声ステレオ」「解説ステレオ」。**
|
|
22
|
+
*
|
|
23
|
+
* 同じ構成の音声が2本ある番組 (解説放送・二重音声) は、種別も言語も同じに
|
|
24
|
+
* なるので**符号からは区別が付かない**。実機の日テレでは、どちらも
|
|
25
|
+
* `component_type=3 lang=jpn` で「ステレオ (日本語)」が2つ並んでいた。
|
|
26
|
+
* 見分けが付くものはここにしか無い
|
|
27
|
+
*/
|
|
28
|
+
text?: string;
|
|
29
|
+
/** 主音声か (`main_component_flag`)。**解説放送はこちらが立っていないほう** */
|
|
30
|
+
main?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** ジャンル。大分類 (`lv1`) と中分類 (`lv2`) の番号 */
|
|
33
|
+
export interface Genre {
|
|
34
|
+
lv1: number;
|
|
35
|
+
lv2: number;
|
|
36
|
+
}
|
|
37
|
+
export interface EitEvent {
|
|
38
|
+
serviceId: number;
|
|
39
|
+
transportStreamId: number;
|
|
40
|
+
originalNetworkId: number;
|
|
41
|
+
eventId: number;
|
|
42
|
+
/** 開始時刻 (epoch ms)。未定 (全ビット1) なら null */
|
|
43
|
+
startAt: number | null;
|
|
44
|
+
/** 尺 (ms)。未定なら null。番組表に入れられるのは決まっているものだけ */
|
|
45
|
+
duration: number | null;
|
|
46
|
+
isFree: boolean;
|
|
47
|
+
/** 1=まもなく 2=停止中 3=一時停止 4=放送中。p/f の「いま」を見分けるのに使う */
|
|
48
|
+
runningStatus: number;
|
|
49
|
+
name: string;
|
|
50
|
+
description: string;
|
|
51
|
+
/** 「出演者」などの見出し付き。extended_event_descriptor を繋ぎ直したもの */
|
|
52
|
+
extended: Record<string, string>;
|
|
53
|
+
/** content_descriptor の大分類・中分類 (ARIB STD-B10 付録 H) */
|
|
54
|
+
genres: Genre[];
|
|
55
|
+
audios: EventAudio[];
|
|
56
|
+
video: {
|
|
57
|
+
type: string | null;
|
|
58
|
+
resolution: string | null;
|
|
59
|
+
} | null;
|
|
60
|
+
/**
|
|
61
|
+
* **コピー禁止か** (デジタルコピー制御記述子)。禁止の番組は録らない (docs/data.md)。
|
|
62
|
+
*
|
|
63
|
+
* `null` は「この表は言っていない」。記述子は基本の表 (と p/f) に載り、詳細の表
|
|
64
|
+
* (0x58〜) には載らないので、詳細だけ届いた回で「禁止ではない」と上書きしないため
|
|
65
|
+
* (`EpgReader.merge`)
|
|
66
|
+
*/
|
|
67
|
+
copyNever: boolean | null;
|
|
68
|
+
}
|
|
69
|
+
export interface EitSection {
|
|
70
|
+
tableId: number;
|
|
71
|
+
serviceId: number;
|
|
72
|
+
transportStreamId: number;
|
|
73
|
+
originalNetworkId: number;
|
|
74
|
+
version: number;
|
|
75
|
+
sectionNumber: number;
|
|
76
|
+
lastSectionNumber: number;
|
|
77
|
+
/** このセグメント (8セクション単位) で実際に使われている最後のセクション */
|
|
78
|
+
segmentLastSectionNumber: number;
|
|
79
|
+
/** この局で使われている最後の table_id。番組表がどこまで先を持っているか */
|
|
80
|
+
lastTableId: number;
|
|
81
|
+
events: EitEvent[];
|
|
82
|
+
}
|
|
83
|
+
/** TDT / TOT が流れている PID。**放送の現在時刻** */
|
|
84
|
+
export declare const PID_TIME = 20;
|
|
85
|
+
/**
|
|
86
|
+
* TDT / TOT のセクションから**放送の実時刻**を読む。別のテーブルなら null。
|
|
87
|
+
*
|
|
88
|
+
* 頭3バイトのあとに MJD + BCD が5バイト。**TOT も同じ並び**で、後ろに
|
|
89
|
+
* 時差の記述子が付くだけなので同じに読める。
|
|
90
|
+
*
|
|
91
|
+
* データ放送 (`bml.ts` の `onTime`) が読み、BML の時計にします
|
|
92
|
+
*/
|
|
93
|
+
export declare function parseTimeTable(section: Uint8Array): number | null;
|
|
94
|
+
/**
|
|
95
|
+
* MJD + BCD の5バイトを epoch ms に直す。
|
|
96
|
+
*
|
|
97
|
+
* 全ビットが1なら「未定」。開始時刻が未定の番組は番組表に置けないので null で返す。
|
|
98
|
+
*/
|
|
99
|
+
export declare function parseMjdTime(data: Uint8Array, at: number): number | null;
|
|
100
|
+
/** BCD 3バイトの尺 (時分秒) を ms に。全ビット1なら「終了未定」 */
|
|
101
|
+
export declare function parseBcdDuration(data: Uint8Array, at: number): number | null;
|
|
102
|
+
/**
|
|
103
|
+
* EIT のセクションを1本読む。自局のもの以外は null。
|
|
104
|
+
*
|
|
105
|
+
* 壊れたセクションは `SectionAssembler` が CRC で落としているので、ここに来るのは
|
|
106
|
+
* 中身が揃っているものだけ。それでも長さの辻褄が合わないことはあるので、
|
|
107
|
+
* **読める番組まで返す**。
|
|
108
|
+
*/
|
|
109
|
+
export declare function parseEit(section: Uint8Array, options?: {
|
|
110
|
+
other?: boolean;
|
|
111
|
+
}): EitSection | null;
|
|
112
|
+
/**
|
|
113
|
+
* どこまで集まったかを数える。
|
|
114
|
+
*
|
|
115
|
+
* **これが無いと「もう十分」が分からない。** 何分開いておくかを決め打ちにすると、
|
|
116
|
+
* 早く揃った局でも待たされ、遅い局は取りこぼす。EIT は自分がどこまであるかを
|
|
117
|
+
* セクションの中で言っているので、それを数えれば足りる。
|
|
118
|
+
*
|
|
119
|
+
* セクションは**8本ずつのセグメント**に分かれていて、セグメントの中で実際に
|
|
120
|
+
* 使われている最後の番号が `segment_last_section_number`。使われていない番号は
|
|
121
|
+
* 永久に来ないので、そこまで揃えばそのセグメントは終わり。
|
|
122
|
+
*
|
|
123
|
+
* **過ぎた時間帯のセグメントは流れてこない** (`stale`)。空でも先頭の1本は必ず
|
|
124
|
+
* 来るものとして待っていた頃は、**どのチャンネルも例外なく上限まで
|
|
125
|
+
* 開きっぱなし**になっていた (実機14チャンネル、揃って離せたのは0本)。
|
|
126
|
+
*/
|
|
127
|
+
export declare class ScheduleProgress {
|
|
128
|
+
private readonly now;
|
|
129
|
+
/** `table_id` → 受け取ったセクション番号 */
|
|
130
|
+
private readonly seen;
|
|
131
|
+
/** `table_id:セグメント先頭` → そのセグメントの最後の番号 */
|
|
132
|
+
private readonly segmentLast;
|
|
133
|
+
/** `table_id` → 最後のセクション番号 */
|
|
134
|
+
private readonly lastSection;
|
|
135
|
+
private lastTableId;
|
|
136
|
+
/**
|
|
137
|
+
* `table_id` → 版。変わったらその表だけ数え直す。
|
|
138
|
+
*
|
|
139
|
+
* **版は `table_id` ごとに別々に振られる。** 番組表の1つの表 (sub_table) は
|
|
140
|
+
* `table_id` + 局 + TS で決まり、`version_number` はその単位で動く。
|
|
141
|
+
* 局に1つだけ持っていた頃は、**基本 (0x50〜) と詳細 (0x58〜) を行き来する
|
|
142
|
+
* たびに版が違って数えたものを全部捨てて**いた。揃ったと分かることが
|
|
143
|
+
* 二度と無いので、どのチャンネルも上限の10分 (`epgChannelTimeout`) まで開きっぱなしになる。
|
|
144
|
+
*/
|
|
145
|
+
private readonly version;
|
|
146
|
+
/**
|
|
147
|
+
* @param now いまの時刻。過ぎた時間帯を判断するのに使う。
|
|
148
|
+
* 時計を跨いで開いていることがあるので、値ではなく関数で受ける
|
|
149
|
+
*/
|
|
150
|
+
constructor(now?: () => number);
|
|
151
|
+
add(section: EitSection): void;
|
|
152
|
+
/**
|
|
153
|
+
* 使われている table_id を全部揃えられたか。
|
|
154
|
+
*
|
|
155
|
+
* **番号が飛ぶ。** 1つの `table_id` が受け持つのは4日ぶんで、基本は
|
|
156
|
+
* `0x50` から、詳細は `0x58` から始まる。日本の放送は8日ぶんなので、
|
|
157
|
+
* 実際に流れてくるのは `0x50` `0x51` と `0x58` `0x59` あたりだけで、
|
|
158
|
+
* **`0x52`〜`0x57` は永久に来ません**。
|
|
159
|
+
*
|
|
160
|
+
* `0x50` から `last_table_id` まで全部を待っていた頃は、詳細を積んでいる局が
|
|
161
|
+
* **一度も「揃った」にならず**、どのチャンネルも上限の10分 (`epgChannelTimeout`) まで開きっぱなしに
|
|
162
|
+
* なっていました (実機で、詳細の無い BS11 だけが早く閉じていた)。
|
|
163
|
+
*
|
|
164
|
+
* 見かけた表と、`last_table_id` が指す表だけを見ます。
|
|
165
|
+
*/
|
|
166
|
+
get complete(): boolean;
|
|
167
|
+
/** その表でまだ来ていない節。セグメントの先頭すら来ていなければ、先頭の番号を数える */
|
|
168
|
+
private holes;
|
|
169
|
+
/**
|
|
170
|
+
* そのセグメントの時間帯がもう過ぎているか。**過ぎたものは待たない。**
|
|
171
|
+
*
|
|
172
|
+
* セグメントは 0:00 から3時間ずつの枠で、`table_id` と節番号から
|
|
173
|
+
* それがいつの枠なのかが決まる — 基本は `0x50` が当日 0:00 から4日ぶん、
|
|
174
|
+
* `0x51` がその次の4日ぶん。詳細 (`0x58`〜) も同じ並びをもう一度たどる。
|
|
175
|
+
* 終わった枠は放送に乗らない (クラスの説明)。そのぶんの番組は、そこが未来だった数日前に取り込んである。
|
|
176
|
+
*/
|
|
177
|
+
private stale;
|
|
178
|
+
/**
|
|
179
|
+
* 何が足りないか。**上限まで開いても揃わなかったときに出す。**
|
|
180
|
+
*
|
|
181
|
+
* 揃ったかどうかしか分からなかった頃は、上限まで開きっぱなしになっている局を
|
|
182
|
+
* 見つけても**その先を追えなかった** — 電波が弱くて欠けているのか、
|
|
183
|
+
* こちらが来ない表を待っているのかで、直し方がまるで違う。
|
|
184
|
+
*/
|
|
185
|
+
report(): string;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 流れてくる TS を食べて番組を溜める。
|
|
189
|
+
*
|
|
190
|
+
* 局ごとに `ScheduleProgress` を持ち、**その物理チャンネルに入っている局が
|
|
191
|
+
* 全部揃ったら**読むのをやめられる。同じ番組が何度も来る (カルーセルなので) ので、
|
|
192
|
+
* event_id で上書きしていく。
|
|
193
|
+
*/
|
|
194
|
+
export declare class EpgReader {
|
|
195
|
+
private readonly now;
|
|
196
|
+
private readonly options;
|
|
197
|
+
private readonly sections;
|
|
198
|
+
private readonly packets;
|
|
199
|
+
private readonly progress;
|
|
200
|
+
/** `serviceId:eventId` → 番組。あとから来たもので上書きする */
|
|
201
|
+
private readonly events;
|
|
202
|
+
/** p/f で「いま流れている」と言われた番組。録画の延長追従はこれを見る */
|
|
203
|
+
readonly present: Map<number, EitEvent>;
|
|
204
|
+
/** `takeChanged` のあとに増えた・変わった番組 (`serviceId:eventId`) */
|
|
205
|
+
private readonly changed;
|
|
206
|
+
/** 最後に新しい局を見かけた時刻 (`other` のときだけ使う) */
|
|
207
|
+
private lastNewService;
|
|
208
|
+
/**
|
|
209
|
+
* @param now いまの時刻。局ごとの `ScheduleProgress` にそのまま渡す
|
|
210
|
+
* @param options.other ほかの TS の局の番組表も読む。ネットワーク全局ぶんを
|
|
211
|
+
* 1つの中継から先に入れるときに使う (`epg-collect.ts` の初回)
|
|
212
|
+
* @param options.settle `other` のとき、新しい局が出てこなくなってから閉じるまで (ms)
|
|
213
|
+
* @param options.expect `other` のとき、来るはずの局 (service_id)。全部見えて揃えば
|
|
214
|
+
* `settle` を待たずに閉じる。受信できない局が混ざっていれば `settle` で閉じる
|
|
215
|
+
*/
|
|
216
|
+
constructor(now?: () => number, options?: {
|
|
217
|
+
other?: boolean;
|
|
218
|
+
settle?: number;
|
|
219
|
+
expect?: readonly number[];
|
|
220
|
+
});
|
|
221
|
+
/** 任意の長さのバイト列を食わせる。番組が1つでも増えたら true */
|
|
222
|
+
feed(chunk: Uint8Array): boolean;
|
|
223
|
+
/**
|
|
224
|
+
* 溜めてあるものと混ぜる。**別の表で来るものを消し合わせない。**
|
|
225
|
+
*
|
|
226
|
+
* 番組表は2つの表に分かれて流れてくる。同じ event_id が両方に載っていて、
|
|
227
|
+
* **それぞれ自分のぶんの記述子しか持っていない**。
|
|
228
|
+
*
|
|
229
|
+
* - **基本** (table_id 0x50〜0x57) … タイトルと短い説明 (short_event_descriptor)
|
|
230
|
+
* - **詳細** (0x58〜0x5F) … 「番組内容」「出演者」など (extended_event_descriptor)
|
|
231
|
+
*
|
|
232
|
+
* あとから来たもので丸ごと置き換えていた頃は、**詳細のほうが後に届いた番組の
|
|
233
|
+
* タイトルが空になっていた**。実機では番組 23,000 件のうち 11,000 件が名無しで、
|
|
234
|
+
* うち 2,700 件は「タイトルは無いのに番組内容だけある」状態 — 詳細に上書きされた
|
|
235
|
+
* 跡そのもの。番組表には「(番組情報なし)」の列が並んでいた。
|
|
236
|
+
*
|
|
237
|
+
* **中身のあるほうを残す。** 書き換え (「[新]」が付く、誤字が直る) は
|
|
238
|
+
* 空でない値で来るので、これまでどおり新しいほうが勝つ。
|
|
239
|
+
*/
|
|
240
|
+
private merge;
|
|
241
|
+
/**
|
|
242
|
+
* p/f で「いま流れている」と言えるか。
|
|
243
|
+
*
|
|
244
|
+
* **`running_status` を当てにしきれない。** 4 (放送中) を入れてくる局も
|
|
245
|
+
* あれば、**0 (未定義) しか入れてこない局もある** — 実機の NHK は 74 節
|
|
246
|
+
* ぜんぶ 0 だった。4 だけを見ていると、そういう局では延長追従が丸ごと
|
|
247
|
+
* 効かなくなる (docs/agent.md)。
|
|
248
|
+
*
|
|
249
|
+
* そこで 0 のときは**節の番号で決める**。p/f は仕様で
|
|
250
|
+
* **section 0 が現在・section 1 が次**と決まっていて、こちらは局の都合で
|
|
251
|
+
* 変わらない。1 (まもなく) や 2 (停止中) は今までどおり入れない。
|
|
252
|
+
*/
|
|
253
|
+
private onAir;
|
|
254
|
+
/**
|
|
255
|
+
* 前に呼んでから増えた・変わった番組。**読みながら少しずつ保存する**ため
|
|
256
|
+
* (`epg-collect.ts`)。揃うまで待ってからまとめて書くと、全局読みの数分のあいだ
|
|
257
|
+
* 画面に何も出ない
|
|
258
|
+
*/
|
|
259
|
+
takeChanged(): EitEvent[];
|
|
260
|
+
/** 書けなかったぶんを、次の `takeChanged` でもう一度返す */
|
|
261
|
+
requeue(events: EitEvent[]): void;
|
|
262
|
+
/** 溜まった番組。開始時刻の順に並べて返す */
|
|
263
|
+
all(): EitEvent[];
|
|
264
|
+
/** 番組表を1つでも見かけた局 */
|
|
265
|
+
services(): number[];
|
|
266
|
+
/**
|
|
267
|
+
* 見かけた局が**全部**揃ったか。
|
|
268
|
+
*
|
|
269
|
+
* 「1局でも揃えば閉じる」にはしない。1つの物理チャンネルには複数の局が
|
|
270
|
+
* 入っていて (地上波なら MX1 と MX2)、先に揃ったほうで閉じると残りが
|
|
271
|
+
* 永久に埋まらない。
|
|
272
|
+
*/
|
|
273
|
+
get complete(): boolean;
|
|
274
|
+
/** 来るはずの局を教わっていて、それが全部見えたか */
|
|
275
|
+
private sawExpected;
|
|
276
|
+
/**
|
|
277
|
+
* 揃っていない局と、その理由。**上限まで開いてしまったときに出す。**
|
|
278
|
+
*
|
|
279
|
+
* 1局でも揃わなければチャンネルごと上限まで開き続けるので、
|
|
280
|
+
* 「どの局のせいか」が分からないと直しようがない。
|
|
281
|
+
*/
|
|
282
|
+
shortfall(): string[];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* **1局の「いま」と「次」(EIT[p/f]) を追う。** ライブで番組の切り替わりを知るのに使う。
|
|
286
|
+
*
|
|
287
|
+
* 番組表 (schedule) は数日先までの予定で、**延長や繰り下げには追いつかない**
|
|
288
|
+
* (局が送り直してくるのは後になってから)。p/f は放送そのものに追従していて、
|
|
289
|
+
* 野球が延びれば「いま」の尺が延び、終われば「次」が「いま」に繰り上がる。
|
|
290
|
+
*
|
|
291
|
+
* section 0 が「いま」、section 1 が「次」と決まっている (`EpgReader.onAir` と同じ)。
|
|
292
|
+
*
|
|
293
|
+
* **中身で比べる。** 書き換われば version が上がるはずだが、上げずに中身だけ替える
|
|
294
|
+
* 送り手を当てにしないよう、番組の番号・時刻・尺・タイトルで比べる。p/f は1局ぶん数百バイトが
|
|
295
|
+
* 数秒おきに来るだけなので、毎回読んでも軽い
|
|
296
|
+
*/
|
|
297
|
+
export declare class PresentFollowing {
|
|
298
|
+
private readonly serviceId;
|
|
299
|
+
private readonly sections;
|
|
300
|
+
/** section 0 (いま) と 1 (次) で最後に読んだ番組。来ていなければ null */
|
|
301
|
+
private readonly held;
|
|
302
|
+
/** 中身の印 (`mark`)。同じものが繰り返し来ても変わったと言わない */
|
|
303
|
+
private readonly marks;
|
|
304
|
+
/** @param serviceId 追う局 (放送が名乗っている service_id) */
|
|
305
|
+
constructor(serviceId: number);
|
|
306
|
+
/** いま流れている番組。まだ来ていない・放送が空けているなら null */
|
|
307
|
+
get present(): EitEvent | null;
|
|
308
|
+
/** 次の番組 */
|
|
309
|
+
get following(): EitEvent | null;
|
|
310
|
+
/**
|
|
311
|
+
* 188 バイトのパケットを1つ。**いまか次のどちらかが変わったら true**。
|
|
312
|
+
* 最初に読めたときも true (知らなかったものが分かった)
|
|
313
|
+
*/
|
|
314
|
+
feedPacket(packet: Uint8Array): boolean;
|
|
315
|
+
}
|
|
316
|
+
export {};
|