@danything/arib 1.0.2 → 1.2.1
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/README.md +13 -13
- package/dist/ait.d.ts +10 -10
- package/dist/ait.js +12 -12
- package/dist/aribtext-gaiji.d.ts +5 -5
- package/dist/aribtext-gaiji.js +7 -7
- package/dist/aribtext.d.ts +11 -11
- package/dist/aribtext.js +31 -31
- package/dist/b24-tables.d.ts +2 -2
- package/dist/b24-tables.js +2 -2
- package/dist/b24caption.d.ts +12 -12
- package/dist/b24caption.js +23 -23
- package/dist/bml-protocol.d.ts +4 -4
- package/dist/bml-protocol.js +2 -2
- package/dist/bml.d.ts +12 -12
- package/dist/bml.js +24 -24
- package/dist/bytes.d.ts +4 -4
- package/dist/bytes.js +4 -4
- package/dist/caption-text.d.ts +19 -19
- package/dist/caption-text.js +1 -1
- package/dist/drcs-smooth.d.ts +6 -6
- package/dist/drcs-smooth.js +5 -5
- package/dist/dsmcc.d.ts +11 -11
- package/dist/dsmcc.js +12 -12
- package/dist/eit.d.ts +38 -38
- package/dist/eit.js +68 -54
- package/dist/language.d.ts +2 -2
- package/dist/language.js +2 -2
- package/dist/multipart.d.ts +4 -4
- package/dist/multipart.js +6 -6
- package/dist/pes.d.ts +13 -13
- package/dist/pes.js +12 -12
- package/dist/psi.d.ts +160 -22
- package/dist/psi.js +308 -36
- package/dist/service-filter.d.ts +14 -14
- package/dist/service-filter.js +18 -18
- package/dist/synth-av.d.ts +8 -8
- package/dist/synth-av.js +14 -14
- package/dist/synth-caption.d.ts +6 -6
- package/dist/synth-caption.js +7 -7
- package/dist/synth.d.ts +43 -18
- package/dist/synth.js +89 -34
- package/package.json +1 -1
package/dist/synth.js
CHANGED
|
@@ -10,9 +10,17 @@ import { PACKET, SYNC, withCrc } from "./psi.js";
|
|
|
10
10
|
export { withCrc };
|
|
11
11
|
const be = (value) => [(value >> 8) & 0xff, value & 0xff];
|
|
12
12
|
const be32 = (value) => [...be(value >>> 16), ...be(value & 0xffff)];
|
|
13
|
-
/** セクションの頭8バイト (長さは `withCrc` が埋める)
|
|
14
|
-
function head(tableId, extension) {
|
|
15
|
-
return [
|
|
13
|
+
/** セクションの頭 8 バイト (長さは `withCrc` が埋める) */
|
|
14
|
+
function head(tableId, extension, part = {}) {
|
|
15
|
+
return [
|
|
16
|
+
tableId,
|
|
17
|
+
0x00,
|
|
18
|
+
0x00,
|
|
19
|
+
...be(extension),
|
|
20
|
+
0xc1 | (((part.version ?? 0) & 0x1f) << 1),
|
|
21
|
+
part.sectionNumber ?? 0,
|
|
22
|
+
part.lastSectionNumber ?? 0,
|
|
23
|
+
];
|
|
16
24
|
}
|
|
17
25
|
/** PCR の基準部 (90kHz) を適応フィールドに書く (旗は呼ぶ側)。拡張部 (27MHz の端数) は読む側が見ていないので 0 */
|
|
18
26
|
export function putPcr(packet, pcr) {
|
|
@@ -27,8 +35,8 @@ export function putPcr(packet, pcr) {
|
|
|
27
35
|
/**
|
|
28
36
|
* Unicode → JIS X 0208 の区点。**読む側の裏返し。**
|
|
29
37
|
*
|
|
30
|
-
* 表を抱え込まずに、EUC-JP のデコーダを1回だけ総当たりして作る
|
|
31
|
-
* (84区 × 94点 = 7896 文字)。テストと偽放送局からしか呼ばないので、
|
|
38
|
+
* 表を抱え込まずに、EUC-JP のデコーダを 1 回だけ総当たりして作る
|
|
39
|
+
* (84 区 × 94 点 = 7896 文字)。テストと偽放送局からしか呼ばないので、
|
|
32
40
|
* 最初に使うときまで作らない。
|
|
33
41
|
*/
|
|
34
42
|
let jis = null;
|
|
@@ -49,7 +57,7 @@ function jisTable() {
|
|
|
49
57
|
return jis;
|
|
50
58
|
}
|
|
51
59
|
/**
|
|
52
|
-
* 文字列を ARIB STD-B24 の8単位符号にする。
|
|
60
|
+
* 文字列を ARIB STD-B24 の 8 単位符号にする。
|
|
53
61
|
*
|
|
54
62
|
* 初期状態 (G0=漢字) から始めて、ASCII のところだけ英数集合へ切り替える。
|
|
55
63
|
* 本物の放送はもっと凝った切り替え方をするが、**読む側が同じ経路を通れば足りる**。
|
|
@@ -73,13 +81,13 @@ export function encodeAribText(text, half = false) {
|
|
|
73
81
|
out.push(0x1b, 0x24, 0x42, ...(half ? [0x8a] : []));
|
|
74
82
|
alnum = false;
|
|
75
83
|
const kuten = jisTable().get(char);
|
|
76
|
-
// 表に無い字は下駄で埋める (2区14点)。長さが変わらないので位置がずれない
|
|
84
|
+
// 表に無い字は下駄で埋める (2 区 14 点)。長さが変わらないので位置がずれない
|
|
77
85
|
out.push(...be(kuten ?? 0x222e));
|
|
78
86
|
}
|
|
79
87
|
return out;
|
|
80
88
|
}
|
|
81
89
|
/**
|
|
82
|
-
* 番組名・局名 (SI) に書く形式。**ASCII は中型 (MSZ)
|
|
90
|
+
* 番組名・局名 (SI) に書く形式。**ASCII は中型 (MSZ) で挟んで半角で読ませる。** 標準の大きさの
|
|
83
91
|
* 英数はテレビが全角で描く (読む側 `aribtext.ts` も全角にする)。全角の英数 (「Venue」) は
|
|
84
92
|
* 漢字の集合の字として書くので、読めば書いたとおりの文字列に戻る
|
|
85
93
|
*/
|
|
@@ -88,14 +96,16 @@ function encodeSiText(text) {
|
|
|
88
96
|
}
|
|
89
97
|
/** 言語の符号 "jpn" (ISO 639-2) */
|
|
90
98
|
const JPN = [0x6a, 0x70, 0x6e];
|
|
91
|
-
/** 長さ1バイトを頭に付けた文字列。SI の記述子はどこもこの形式 */
|
|
99
|
+
/** 長さ 1 バイトを頭に付けた文字列。SI の記述子はどこもこの形式 */
|
|
92
100
|
const sized = (text) => {
|
|
93
101
|
const body = encodeSiText(text);
|
|
94
102
|
return [body.length, ...body];
|
|
95
103
|
};
|
|
96
|
-
export function sdtSection(transportStreamId, originalNetworkId, services
|
|
104
|
+
export function sdtSection(transportStreamId, originalNetworkId, services,
|
|
105
|
+
/** `other` なら SDT[other] (0x46。ほかの TS のもの) */
|
|
106
|
+
options = {}) {
|
|
97
107
|
const body = [
|
|
98
|
-
...head(0x42, transportStreamId),
|
|
108
|
+
...head(options.other === true ? 0x46 : 0x42, transportStreamId, options),
|
|
99
109
|
...be(originalNetworkId),
|
|
100
110
|
0xff,
|
|
101
111
|
];
|
|
@@ -107,9 +117,9 @@ export function sdtSection(transportStreamId, originalNetworkId, services) {
|
|
|
107
117
|
}
|
|
108
118
|
return withCrc(body);
|
|
109
119
|
}
|
|
110
|
-
/** 2桁の10進を BCD の1バイトに */
|
|
120
|
+
/** 2 桁の 10 進を BCD の 1 バイトに */
|
|
111
121
|
const bcd = (value) => ((Math.floor(value / 10) << 4) | (value % 10)) & 0xff;
|
|
112
|
-
/** epoch ms → MJD + BCD の5バイト。放送の時刻は日本時間で書く */
|
|
122
|
+
/** epoch ms → MJD + BCD の 5 バイト。放送の時刻は日本時間で書く */
|
|
113
123
|
function mjdTime(at) {
|
|
114
124
|
const jst = Math.floor(at / 1000) + 9 * 3600;
|
|
115
125
|
const mjd = Math.floor(jst / 86400) + 40587;
|
|
@@ -121,7 +131,7 @@ function mjdTime(at) {
|
|
|
121
131
|
bcd(rest % 60),
|
|
122
132
|
];
|
|
123
133
|
}
|
|
124
|
-
/** ms → BCD 3バイトの尺 */
|
|
134
|
+
/** ms → BCD 3 バイトの尺 */
|
|
125
135
|
function bcdDuration(ms) {
|
|
126
136
|
const total = Math.floor(ms / 1000);
|
|
127
137
|
return [
|
|
@@ -131,11 +141,11 @@ function bcdDuration(ms) {
|
|
|
131
141
|
];
|
|
132
142
|
}
|
|
133
143
|
/**
|
|
134
|
-
* シリーズ記述子 (0xD5。ARIB STD-B10 第2部)。
|
|
144
|
+
* シリーズ記述子 (0xD5。ARIB STD-B10 第 2 部)。
|
|
135
145
|
*
|
|
136
146
|
* series_id(16) / repeat_label(4) program_pattern(3) expire_date_valid_flag(1) /
|
|
137
147
|
* expire_date(16) / episode_number(12) last_episode_number(12) / series_name_char。
|
|
138
|
-
* 有効期限は載せない (flag 0、日付は全ビット1)
|
|
148
|
+
* 有効期限は載せない (flag 0、日付は全ビット 1)
|
|
139
149
|
*/
|
|
140
150
|
function seriesDescriptor(series) {
|
|
141
151
|
const episode = series.episode ?? 0;
|
|
@@ -154,7 +164,7 @@ function seriesDescriptor(series) {
|
|
|
154
164
|
}
|
|
155
165
|
/**
|
|
156
166
|
* デジタルコピー制御記述子 (0xC1)。EIT の番組と PMT に載る。
|
|
157
|
-
* 中身は1バイトだけ: 記録制御 (2) 最大ビットレートの有無 (1) 部品ごとの制御の有無 (1) 出力の制御 (4)
|
|
167
|
+
* 中身は 1 バイトだけ: 記録制御 (2) 最大ビットレートの有無 (1) 部品ごとの制御の有無 (1) 出力の制御 (4)
|
|
158
168
|
*/
|
|
159
169
|
export function copyControlDescriptor(control) {
|
|
160
170
|
return [0xc1, 0x01, ((control & 0b11) << 6) | 0b0100];
|
|
@@ -193,7 +203,7 @@ function eventDescriptors(event) {
|
|
|
193
203
|
* simulcast_group_tag / フラグ / 言語 / **放送が付けた名前**。
|
|
194
204
|
*
|
|
195
205
|
* フラグは 多言語(1) 主音声(1) 品質(2) 標本化周波数(3) reserved(1)。
|
|
196
|
-
* 名前は、種別も言語も同じ音声が2本あるとき**唯一の見分け**になる
|
|
206
|
+
* 名前は、種別も言語も同じ音声が 2 本あるとき**唯一の見分け**になる
|
|
197
207
|
*/
|
|
198
208
|
const lang = [...(audio.lang ?? "jpn")].map((c) => c.charCodeAt(0));
|
|
199
209
|
const text = encodeSiText(audio.text ?? "");
|
|
@@ -235,21 +245,66 @@ export function eitSection(options) {
|
|
|
235
245
|
}
|
|
236
246
|
return withCrc(body);
|
|
237
247
|
}
|
|
238
|
-
|
|
239
|
-
|
|
248
|
+
/**
|
|
249
|
+
* NIT。TS ごとに `[TSID, ONID, [サービスID, 種別][], 足す記述子]`。
|
|
250
|
+
* 足す記述子は分配の記述子 (`satelliteDeliveryDescriptor`・`terrestrialDeliveryDescriptor`) など
|
|
251
|
+
*/
|
|
252
|
+
export function nitSection(networkId, remoteControlKeyId, streams,
|
|
253
|
+
/** `other` なら NIT[other] (0x41。ほかのネットワークのもの) */
|
|
254
|
+
options = {}) {
|
|
255
|
+
const body = [
|
|
256
|
+
...head(options.other === true ? 0x41 : 0x40, networkId, options),
|
|
257
|
+
...be(0xf000),
|
|
258
|
+
];
|
|
240
259
|
const loop = [];
|
|
241
|
-
for (const [transportStreamId, originalNetworkId, services] of streams) {
|
|
260
|
+
for (const [transportStreamId, originalNetworkId, services, extra,] of streams) {
|
|
242
261
|
const descriptors = [];
|
|
243
262
|
// TS information descriptor (0xCD)
|
|
244
263
|
if (remoteControlKeyId !== null)
|
|
245
264
|
descriptors.push(0xcd, 0x02, remoteControlKeyId, 0x00);
|
|
246
265
|
const serviceList = services.flatMap(([id, type]) => [...be(id), type]);
|
|
247
266
|
descriptors.push(0x41, serviceList.length, ...serviceList);
|
|
267
|
+
descriptors.push(...(extra ?? []));
|
|
248
268
|
loop.push(...be(transportStreamId), ...be(originalNetworkId), ...be(0xf000 | descriptors.length), ...descriptors);
|
|
249
269
|
}
|
|
250
270
|
body.push(...be(0xf000 | loop.length), ...loop);
|
|
251
271
|
return withCrc(body);
|
|
252
272
|
}
|
|
273
|
+
/** 10 進の整数を `digits` 桁の BCD のバイト列にする (桁が奇数なら最後の半バイトは 0) */
|
|
274
|
+
function bcdBytes(value, digits) {
|
|
275
|
+
const text = String(value).padStart(digits, "0");
|
|
276
|
+
const out = [];
|
|
277
|
+
for (let i = 0; i < digits; i += 2) {
|
|
278
|
+
out.push((Number(text[i]) << 4) | Number(text[i + 1] ?? 0));
|
|
279
|
+
}
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 衛星の分配の記述子 (0x43)。周波数は kHz、シンボルレートはシンボル/秒で渡す
|
|
284
|
+
* (BS-1 は 11727480 kHz・28860000)。東経 110 度・右旋・ISDB-S (変調 0x08) にしておく
|
|
285
|
+
*/
|
|
286
|
+
export function satelliteDeliveryDescriptor(frequency, symbolRate = 28_860_000) {
|
|
287
|
+
const symbol = bcdBytes(symbolRate / 100, 7);
|
|
288
|
+
return [
|
|
289
|
+
0x43,
|
|
290
|
+
11,
|
|
291
|
+
...bcdBytes(frequency / 10, 8),
|
|
292
|
+
...bcdBytes(1100, 4),
|
|
293
|
+
0x80 | (3 << 5) | 0x08,
|
|
294
|
+
symbol[0],
|
|
295
|
+
symbol[1],
|
|
296
|
+
symbol[2],
|
|
297
|
+
(symbol[3] & 0xf0) | 0x01,
|
|
298
|
+
];
|
|
299
|
+
}
|
|
300
|
+
/** 地上の分配の記述子 (0xFA)。周波数は Hz で渡す (1/7 MHz 単位に丸める) */
|
|
301
|
+
export function terrestrialDeliveryDescriptor(areaCode, frequencies) {
|
|
302
|
+
const body = [
|
|
303
|
+
...be((areaCode << 4) | (1 << 2) | 0x02),
|
|
304
|
+
...frequencies.flatMap((hz) => be(Math.round((hz * 7) / 1_000_000))),
|
|
305
|
+
];
|
|
306
|
+
return [0xfa, body.length, ...body];
|
|
307
|
+
}
|
|
253
308
|
/** セクションを TS パケットに詰める。頭のパケットには pointer_field が付く */
|
|
254
309
|
export function packetize(pid, section, counter = 0) {
|
|
255
310
|
const packets = [];
|
|
@@ -265,11 +320,11 @@ export function packetize(pid, section, counter = 0) {
|
|
|
265
320
|
}
|
|
266
321
|
return Uint8Array.from(packets);
|
|
267
322
|
}
|
|
268
|
-
/** 部品を1本のバイト列に繋ぐ。組んだパケットを流し込むときの糊 */
|
|
323
|
+
/** 部品を 1 本のバイト列に繋ぐ。組んだパケットを流し込むときの糊 */
|
|
269
324
|
export function stream(...parts) {
|
|
270
325
|
return joinBytes(parts);
|
|
271
326
|
}
|
|
272
|
-
/** PCR を1つ運ぶだけのパケット */
|
|
327
|
+
/** PCR を 1 つ運ぶだけのパケット */
|
|
273
328
|
export function pcrPacket(pid, seconds, counter = 0) {
|
|
274
329
|
const packet = new Uint8Array(PACKET).fill(0xff);
|
|
275
330
|
packet[0] = SYNC;
|
|
@@ -282,11 +337,11 @@ export function pcrPacket(pid, seconds, counter = 0) {
|
|
|
282
337
|
putPcr(packet, seconds * 90_000);
|
|
283
338
|
return packet;
|
|
284
339
|
}
|
|
285
|
-
/** 放送の実時刻 (TDT) を1パケットに。BML の `getCurrentDateTime` が見る */
|
|
340
|
+
/** 放送の実時刻 (TDT) を 1 パケットに。BML の `getCurrentDateTime` が見る */
|
|
286
341
|
export function tdtPacket(unixMs) {
|
|
287
342
|
return packetize(0x0014, Uint8Array.from([0x70, 0x70, 0x05, ...mjdTime(unixMs)]));
|
|
288
343
|
}
|
|
289
|
-
/** PAT。サービスID → PMT の PID */
|
|
344
|
+
/** PAT。サービス ID → PMT の PID */
|
|
290
345
|
export function patSection(programs, transportStreamId = 1) {
|
|
291
346
|
const body = head(0x00, transportStreamId);
|
|
292
347
|
for (const [serviceId, pmtPid] of programs) {
|
|
@@ -295,7 +350,7 @@ export function patSection(programs, transportStreamId = 1) {
|
|
|
295
350
|
return withCrc(body);
|
|
296
351
|
}
|
|
297
352
|
/**
|
|
298
|
-
* PMT。ロゴのカルーセルが乗る ES を1つだけ持たせる。
|
|
353
|
+
* PMT。ロゴのカルーセルが乗る ES を 1 つだけ持たせる。
|
|
299
354
|
* 目印は stream_identifier_descriptor (0x52) の component_tag
|
|
300
355
|
*/
|
|
301
356
|
export function pmtSection(serviceId, esPid, componentTag) {
|
|
@@ -322,7 +377,7 @@ export function pmtSection(serviceId, esPid, componentTag) {
|
|
|
322
377
|
* [service-filter.ts](service-filter.ts) を試すのに要る
|
|
323
378
|
*/
|
|
324
379
|
export function programMap(serviceId, pcrPid,
|
|
325
|
-
/** `[種別, PID]`。**3つ目は記述子**の並び (字幕の部品タグなど) */
|
|
380
|
+
/** `[種別, PID]`。**3 つ目は記述子**の並び (字幕の部品タグなど) */
|
|
326
381
|
streams, ecmPid,
|
|
327
382
|
/** 番組ぜんたいに掛かる記述子 (program_info) に足すもの。コピー制御 ({@link copyControlDescriptor}) など */
|
|
328
383
|
extra = []) {
|
|
@@ -354,7 +409,7 @@ export function bxmlDescriptor(options = {}) {
|
|
|
354
409
|
const { dataComponentId = 0x0c, entryPoint = true } = options;
|
|
355
410
|
const body = [
|
|
356
411
|
...be(dataComponentId),
|
|
357
|
-
// 伝送方式00 / 入口 / 自動起動 / 解像度0011 (960x540)
|
|
412
|
+
// 伝送方式 00 / 入口 / 自動起動 / 解像度 0011 (960x540)
|
|
358
413
|
...(entryPoint ? [0x33, 0x70] : [0x00, 0xff]),
|
|
359
414
|
0xf8, // dataEventId 0xF / event_section_flag
|
|
360
415
|
0xa0, // 即時取得あり / 蓄積不可 / 起動優先
|
|
@@ -365,7 +420,7 @@ export function bxmlDescriptor(options = {}) {
|
|
|
365
420
|
* 字幕の ES (stream_type 0x06) に付ける記述子。**字幕の目印。**
|
|
366
421
|
*
|
|
367
422
|
* 部品タグ (stream_identifier_descriptor。ふつうの字幕は 0x30〜0x37) と、データ符号化方式記述子の
|
|
368
|
-
* data_component_id 0x0008 (字幕)。続く1バイトの DMF・時刻制御モードは denpa も ffmpeg も見ない
|
|
423
|
+
* data_component_id 0x0008 (字幕)。続く 1 バイトの DMF・時刻制御モードは denpa も ffmpeg も見ない
|
|
369
424
|
*/
|
|
370
425
|
export function captionDescriptors(componentTag = 0x30) {
|
|
371
426
|
return [0x52, 0x01, componentTag, 0xfd, 0x03, 0x00, 0x08, 0x3d];
|
|
@@ -378,7 +433,7 @@ function dsmccSection(tableId, message) {
|
|
|
378
433
|
* DII。「このモジュールは何バイトで、名前は何か」を伝える。
|
|
379
434
|
*
|
|
380
435
|
* **複数のモジュールを載せられる。** 本物の BS はここに `LOGO-05` と
|
|
381
|
-
* `CS_LOGO-05` を並べて流していて (実機の `
|
|
436
|
+
* `CS_LOGO-05` を並べて流していて (実機の `BS15:16625` で確認)、1 つしか
|
|
382
437
|
* 載せられない作りでは CS を取りこぼす経路を試せない。
|
|
383
438
|
*/
|
|
384
439
|
export function diiSection(downloadId, blockSize, modules,
|
|
@@ -430,7 +485,7 @@ transactionId = 1) {
|
|
|
430
485
|
...rest,
|
|
431
486
|
]);
|
|
432
487
|
}
|
|
433
|
-
/** DDB。モジュールを割ったブロックを1つ運ぶ */
|
|
488
|
+
/** DDB。モジュールを割ったブロックを 1 つ運ぶ */
|
|
434
489
|
export function ddbSection(downloadId, moduleId, moduleVersion, blockNumber, block) {
|
|
435
490
|
return dsmccSection(0x3c, [
|
|
436
491
|
0x11,
|
|
@@ -461,7 +516,7 @@ export function logoModule(logoType, logos) {
|
|
|
461
516
|
}
|
|
462
517
|
/*
|
|
463
518
|
* --- データ放送のテストで使う定番の割り振り ---
|
|
464
|
-
* denpa の bml / data-timeline / recorded-bml の3つのテストが、同じ表と同じ組み立てを
|
|
519
|
+
* denpa の bml / data-timeline / recorded-bml の 3 つのテストが、同じ表と同じ組み立てを
|
|
465
520
|
* それぞれに書いていた。番号そのものに意味は無く、揃っていることに意味がある。
|
|
466
521
|
*/
|
|
467
522
|
export const BML_TS = {
|
|
@@ -472,7 +527,7 @@ export const BML_TS = {
|
|
|
472
527
|
downloadId: 0xf0000001,
|
|
473
528
|
componentTag: 0x40,
|
|
474
529
|
};
|
|
475
|
-
/** BML の ES が1本だけ載った PMT (`BML_TS` の割り振り) */
|
|
530
|
+
/** BML の ES が 1 本だけ載った PMT (`BML_TS` の割り振り) */
|
|
476
531
|
export function bmlPmt() {
|
|
477
532
|
return programMap(BML_TS.service, BML_TS.videoPid, [
|
|
478
533
|
[0x02, BML_TS.videoPid, [0x52, 0x01, 0x00]],
|
|
@@ -491,7 +546,7 @@ export function bmlHead() {
|
|
|
491
546
|
];
|
|
492
547
|
}
|
|
493
548
|
/**
|
|
494
|
-
* モジュール1つぶんの中身。**放送は multipart/mixed で複数のファイルを詰める。**
|
|
549
|
+
* モジュール 1 つぶんの中身。**放送は multipart/mixed で複数のファイルを詰める。**
|
|
495
550
|
* 本物と同じく、頭に Content-Type、境界で区切って各ファイルに Content-Location
|
|
496
551
|
*/
|
|
497
552
|
export function multipartModule(files) {
|