@danything/arib 2.5.0 → 2.5.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/dist/b24-tables.js +1 -0
- package/dist/bml-protocol.d.ts +7 -0
- package/dist/bml.d.ts +5 -0
- package/dist/bml.js +21 -3
- package/dist/eit.d.ts +2 -2
- package/dist/eit.js +1 -1
- package/dist/mmt-si.d.ts +10 -1
- package/dist/mmt-si.js +17 -4
- package/dist/pes.js +2 -3
- package/dist/psi.d.ts +5 -0
- package/dist/psi.js +5 -0
- package/package.json +1 -1
package/dist/b24-tables.js
CHANGED
|
@@ -501,4 +501,5 @@ export const DRCS_REPLACE = new Map([
|
|
|
501
501
|
['c42450812c184aee2ae01cc5e39ae957', 0x1f4fb], // denpa: ラジオ 📻 (72x72・16 階調)。テレ東 2026-11-01 のアニメの字幕で 1 本に 28 回
|
|
502
502
|
['06cb56043b9c4006bcfbe07cc831feaf', 0x1f50a], // denpa: 音の出ているスピーカー 🔊 (72x72・16 階調)。上と同じ番組で 4 回 (テレビ朝日・TBS のものと画像が違う)
|
|
503
503
|
['063c95566807d5e7b51ab706426bedf9', 0x1f4f1], // denpa: 携帯電話 📱 (72x72・16 階調)。上と同じ番組で 4 回 (NHK総合のものと画像が違う)
|
|
504
|
+
['44cbc7dc0af84f6ab857f00a9bc2560a', 0x1f4fa], // denpa: テレビ 📺 (72x72・16 階調)。日テレ 2026-11-14 のらんま1/2 の字幕で 1 本に 2 回 (テレビ朝日のテレビと画像が違う)
|
|
504
505
|
]);
|
package/dist/bml-protocol.d.ts
CHANGED
|
@@ -69,6 +69,13 @@ export interface ModuleFile {
|
|
|
69
69
|
export interface PMTMessage {
|
|
70
70
|
type: "pmt";
|
|
71
71
|
components: ComponentPMT[];
|
|
72
|
+
/**
|
|
73
|
+
* PMT にある音声 (stream_type 0x0f の AAC) の ES の部品タグを、PMT の順に並べたもの。**部品タグの無い ES は null で並ぶ**
|
|
74
|
+
* (bml.ts の `pmtAudios`)。`components` は部品タグの無い ES を落とすので、何本目の音声かはこちらで数える。
|
|
75
|
+
* 画面の再生 (pes.ts の `readPmt`) と ffmpeg の `0:a:<n>` も、部品タグに関係なく PMT の順に数える。
|
|
76
|
+
* これを足す前に録った `.bml.jsonl` の PMT には無い
|
|
77
|
+
*/
|
|
78
|
+
audios?: (number | null)[];
|
|
72
79
|
}
|
|
73
80
|
export interface ModuleDownloadedMessage {
|
|
74
81
|
type: "moduleDownloaded";
|
package/dist/bml.d.ts
CHANGED
|
@@ -33,6 +33,11 @@ export declare function parseBxmlInfo(data: Uint8Array): AdditionalAribBXMLInfo;
|
|
|
33
33
|
* `BmlDecoder` の外からも使う。denpa のライブは、カルーセルをデコードする前に入口の部品の自動起動の指定をこれで読む
|
|
34
34
|
*/
|
|
35
35
|
export declare function parsePmt(section: Uint8Array): ComponentPMT[];
|
|
36
|
+
/**
|
|
37
|
+
* PMT にある音声 (AAC) の ES の部品タグを、PMT の順に並べる (`PMTMessage.audios`)。**部品タグの無い ES は null で数に入れる。**
|
|
38
|
+
* `parsePmt` と違って落とさないので、何本目の音声かが画面の再生 (pes.ts の `readPmt`) と ffmpeg の `0:a:<n>` にそろう
|
|
39
|
+
*/
|
|
40
|
+
export declare function pmtAudios(section: Uint8Array): (number | null)[];
|
|
36
41
|
/**
|
|
37
42
|
* 1 局に絞った TS を渡すと、データ放送の通知が出てくる。
|
|
38
43
|
*
|
package/dist/bml.js
CHANGED
|
@@ -23,7 +23,7 @@ import { u16, u32 } from "./bytes.js";
|
|
|
23
23
|
import { dataEventIdOf, MAX_MODULE_SIZE, ModuleBuilder, parseDdb, parseDii, TABLE_DII, TABLE_STREAM_DESCRIPTOR, } from "./dsmcc.js";
|
|
24
24
|
import { parseTimeTable, PID_TIME } from "./eit.js";
|
|
25
25
|
import { parseMediaType, readEntity } from "./multipart.js";
|
|
26
|
-
import { descriptors, packetPid, PacketStream, pmtStreams, PmtTracker, SectionAssembler, } from "./psi.js";
|
|
26
|
+
import { descriptors, packetPid, PacketStream, pmtStreams, PmtTracker, SectionAssembler, STREAM_AAC, } from "./psi.js";
|
|
27
27
|
const DESC_STREAM_IDENTIFIER = 0x52;
|
|
28
28
|
/** データ符号化方式記述子 (STD-B10 第 2 部 6.2.20) */
|
|
29
29
|
const DESC_DATA_COMPONENT = 0xfd;
|
|
@@ -139,6 +139,23 @@ export function parsePmt(section) {
|
|
|
139
139
|
}
|
|
140
140
|
return components;
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* PMT にある音声 (AAC) の ES の部品タグを、PMT の順に並べる (`PMTMessage.audios`)。**部品タグの無い ES は null で数に入れる。**
|
|
144
|
+
* `parsePmt` と違って落とさないので、何本目の音声かが画面の再生 (pes.ts の `readPmt`) と ffmpeg の `0:a:<n>` にそろう
|
|
145
|
+
*/
|
|
146
|
+
export function pmtAudios(section) {
|
|
147
|
+
const audios = [];
|
|
148
|
+
for (const [streamType, , info] of pmtStreams(section)) {
|
|
149
|
+
if (streamType !== STREAM_AAC)
|
|
150
|
+
continue;
|
|
151
|
+
let componentId = null;
|
|
152
|
+
for (const [tag, descriptor] of descriptors(info))
|
|
153
|
+
if (tag === DESC_STREAM_IDENTIFIER && descriptor.length >= 1)
|
|
154
|
+
componentId = descriptor[0];
|
|
155
|
+
audios.push(componentId);
|
|
156
|
+
}
|
|
157
|
+
return audios;
|
|
158
|
+
}
|
|
142
159
|
/** `at` の下位 1 ビットと続く 4 バイトで 33 ビット (STC・NPT) */
|
|
143
160
|
const u33 = (data, at) => (data[at] & 1) * 0x100000000 + u32(data, at + 1);
|
|
144
161
|
/** ストリーム記述子 (table_id 0x3D)。NPT と イベントメッセージが載っている */
|
|
@@ -252,14 +269,15 @@ export class BmlDecoder {
|
|
|
252
269
|
const components = parsePmt(section);
|
|
253
270
|
if (components.length === 0)
|
|
254
271
|
return;
|
|
272
|
+
const audios = pmtAudios(section);
|
|
255
273
|
/*
|
|
256
274
|
* 放送は同じ表を何度も送る。**変わったときだけ配る。** 受け側は
|
|
257
275
|
* PMT が来るたびに画面を組み直すので、そのまま通すと出っ放しになる
|
|
258
276
|
*/
|
|
259
|
-
const shape = JSON.stringify(components);
|
|
277
|
+
const shape = JSON.stringify([components, audios]);
|
|
260
278
|
if (this.sent !== shape) {
|
|
261
279
|
this.sent = shape;
|
|
262
|
-
this.send({ type: "pmt", components });
|
|
280
|
+
this.send({ type: "pmt", components, audios });
|
|
263
281
|
}
|
|
264
282
|
for (const component of components) {
|
|
265
283
|
// カルーセルが流れているのは、BML の符号化方式が付いた ES だけ
|
package/dist/eit.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export interface EitEvent {
|
|
|
70
70
|
/** 尺 (ms)。未定なら null。番組表に入れられるのは決まっているものだけ */
|
|
71
71
|
duration: number | null;
|
|
72
72
|
isFree: boolean;
|
|
73
|
-
/** 1
|
|
73
|
+
/** 0=未定義 1=非実行中 2=数秒以内に開始 3=停止中 4=放送中 (STD-B10)。p/f の「いま」を見分けるのに使う */
|
|
74
74
|
runningStatus: number;
|
|
75
75
|
name: string;
|
|
76
76
|
description: string;
|
|
@@ -292,7 +292,7 @@ export declare class EpgReader {
|
|
|
292
292
|
*
|
|
293
293
|
* そこで 0 のときは**セクションの番号で決める**。p/f は仕様で
|
|
294
294
|
* **section 0 が現在・section 1 が次**と決まっていて、こちらは局の都合で
|
|
295
|
-
* 変わらない。1 (
|
|
295
|
+
* 変わらない。1〜3 (非実行中・数秒以内に開始・停止中) は今までどおり入れない。
|
|
296
296
|
*/
|
|
297
297
|
private onAir;
|
|
298
298
|
/**
|
package/dist/eit.js
CHANGED
|
@@ -652,7 +652,7 @@ export class EpgReader {
|
|
|
652
652
|
*
|
|
653
653
|
* そこで 0 のときは**セクションの番号で決める**。p/f は仕様で
|
|
654
654
|
* **section 0 が現在・section 1 が次**と決まっていて、こちらは局の都合で
|
|
655
|
-
* 変わらない。1 (
|
|
655
|
+
* 変わらない。1〜3 (非実行中・数秒以内に開始・停止中) は今までどおり入れない。
|
|
656
656
|
*/
|
|
657
657
|
onAir(section, event) {
|
|
658
658
|
if (event.runningStatus === 4)
|
package/dist/mmt-si.d.ts
CHANGED
|
@@ -172,12 +172,21 @@ export declare class TlvServiceReader {
|
|
|
172
172
|
private readonly streams;
|
|
173
173
|
/** package_id (= service_id) → MPT */
|
|
174
174
|
private readonly mpts;
|
|
175
|
+
/**
|
|
176
|
+
* TLV-NIT[actual]。番号・名前・セクションの番号は最初に来たセクションのもので、`streams` はこれまでに来た全部のセクションの
|
|
177
|
+
* TLV ストリーム (tlv_stream_id ごとに 1 つ。同じ tlv_stream_id は後に来たもので置き換える)
|
|
178
|
+
*/
|
|
175
179
|
network: TlvNetwork | null;
|
|
176
180
|
transport: MhSdt | null;
|
|
177
181
|
get complete(): boolean;
|
|
178
182
|
/** PLT が来て、そこにある package の MPT が全部 1 回は来たか。スキャンで、局ごとの CA_system_id が分かるまで少し長く読むのに使う */
|
|
179
183
|
get mptsKnown(): boolean;
|
|
180
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* 任意の長さのバイト列を渡す。揃ったら true。
|
|
186
|
+
*
|
|
187
|
+
* 読んだ表は渡されたチャンクの一部を指すことがあり、呼ぶ側はチャンクのバッファを使い回す。**記述子の並び (`descriptors`) と
|
|
188
|
+
* asset_id を持ち続ける MPT と TLV-NIT は、写してから読む**
|
|
189
|
+
*/
|
|
181
190
|
feed(chunk: Uint8Array): boolean;
|
|
182
191
|
/**
|
|
183
192
|
* 自分の TLV ストリーム。TLV-NIT[actual] のストリームのうち、PLT にある package (= service_id) をサービスリスト記述子に持つ最初の 1 つ。
|
package/dist/mmt-si.js
CHANGED
|
@@ -401,6 +401,10 @@ export class TlvServiceReader {
|
|
|
401
401
|
streams = new Map();
|
|
402
402
|
/** package_id (= service_id) → MPT */
|
|
403
403
|
mpts = new Map();
|
|
404
|
+
/**
|
|
405
|
+
* TLV-NIT[actual]。番号・名前・セクションの番号は最初に来たセクションのもので、`streams` はこれまでに来た全部のセクションの
|
|
406
|
+
* TLV ストリーム (tlv_stream_id ごとに 1 つ。同じ tlv_stream_id は後に来たもので置き換える)
|
|
407
|
+
*/
|
|
404
408
|
network = null;
|
|
405
409
|
transport = null;
|
|
406
410
|
get complete() {
|
|
@@ -411,24 +415,33 @@ export class TlvServiceReader {
|
|
|
411
415
|
return (this.plt !== null &&
|
|
412
416
|
this.plt.packages.every((entry) => this.mpts.has(entry.packageId)));
|
|
413
417
|
}
|
|
414
|
-
/**
|
|
418
|
+
/**
|
|
419
|
+
* 任意の長さのバイト列を渡す。揃ったら true。
|
|
420
|
+
*
|
|
421
|
+
* 読んだ表は渡されたチャンクの一部を指すことがあり、呼ぶ側はチャンクのバッファを使い回す。**記述子の並び (`descriptors`) と
|
|
422
|
+
* asset_id を持ち続ける MPT と TLV-NIT は、写してから読む**
|
|
423
|
+
*/
|
|
415
424
|
feed(chunk) {
|
|
416
425
|
for (const { table } of this.tables.feed(chunk)) {
|
|
417
426
|
const tableId = table[0];
|
|
418
427
|
if (tableId === TABLE_PLT)
|
|
419
428
|
this.plt = parsePlt(table) ?? this.plt;
|
|
420
429
|
else if (tableId === TABLE_MPT) {
|
|
421
|
-
const mpt = parseMpt(table);
|
|
430
|
+
const mpt = parseMpt(table.slice());
|
|
422
431
|
if (mpt !== null)
|
|
423
432
|
this.mpts.set(mpt.packageId, mpt);
|
|
424
433
|
}
|
|
425
434
|
else if (tableId === TABLE_TLV_NIT_ACTUAL) {
|
|
426
|
-
const network = parseTlvNit(table);
|
|
435
|
+
const network = parseTlvNit(table.slice());
|
|
427
436
|
if (network === null)
|
|
428
437
|
continue;
|
|
429
|
-
this.network ??= network;
|
|
430
438
|
for (const stream of network.streams)
|
|
431
439
|
this.streams.set(stream.tlvStreamId, stream);
|
|
440
|
+
// ネットワークの番号と名前は最初に来たセクションのもの。ストリームは来たセクションの全部
|
|
441
|
+
this.network = {
|
|
442
|
+
...(this.network ?? network),
|
|
443
|
+
streams: [...this.streams.values()],
|
|
444
|
+
};
|
|
432
445
|
}
|
|
433
446
|
else if (tableId === TABLE_MH_SDT_ACTUAL && this.transport === null)
|
|
434
447
|
this.transport = parseMhSdt(table);
|
package/dist/pes.js
CHANGED
|
@@ -9,14 +9,13 @@
|
|
|
9
9
|
* DOM も WASM も触らないので、ここだけ単体で確かめられる (`pes.test.ts`)。
|
|
10
10
|
*/
|
|
11
11
|
import { concatBytes, u16 } from "./bytes.js";
|
|
12
|
-
import { PACKET, packetPid, PacketStream, PID_PAT, pmtStreams, PmtTracker, } from "./psi.js";
|
|
12
|
+
import { PACKET, packetPid, PacketStream, PID_PAT, pmtStreams, PmtTracker, STREAM_AAC, } from "./psi.js";
|
|
13
13
|
/** PTS・PCR の刻み (90kHz)。denpa の取り決めの時刻もこの刻み (docs/stream.md#websocket-プロトコル) */
|
|
14
14
|
export const CLOCK = 90_000;
|
|
15
15
|
/** PTS の一周 (33 ビット)。26.5 時間 */
|
|
16
16
|
export const WRAP = 2 ** 33;
|
|
17
|
-
/** PMT の stream_type。**放送の映像は MPEG-2、音声は ADTS の AAC** (ARIB STD-B32) */
|
|
17
|
+
/** PMT の stream_type。**放送の映像は MPEG-2、音声は ADTS の AAC** (ARIB STD-B32。AAC は psi.ts の `STREAM_AAC`) */
|
|
18
18
|
const STREAM_MPEG2 = 0x02;
|
|
19
|
-
const STREAM_AAC = 0x0f;
|
|
20
19
|
/** 5 バイトの PTS / DTS を読む (ISO/IEC 13818-1 2.4.3.7) */
|
|
21
20
|
export function readStamp(data, at) {
|
|
22
21
|
return (((data[at] >> 1) & 0x07) * 2 ** 30 +
|
package/dist/psi.d.ts
CHANGED
|
@@ -120,6 +120,11 @@ export declare class PmtTracker {
|
|
|
120
120
|
export declare function descriptors(data: Uint8Array): Generator<[number, Uint8Array]>;
|
|
121
121
|
/** デジタルコピー制御記述子。EIT の番組ごとと PMT に入る */
|
|
122
122
|
export declare const DESC_DIGITAL_COPY_CONTROL = 193;
|
|
123
|
+
/**
|
|
124
|
+
* 音声の ES の stream_type (AAC。日本の放送の音声)。主音声の何本目かは、どこでもこの stream_type だけを PMT の順に数える
|
|
125
|
+
* (pes.ts の `readPmt`・bml.ts の `pmtAudios`・データ放送の主音声)。ffmpeg の `0:a:<n>` ともそろう
|
|
126
|
+
*/
|
|
127
|
+
export declare const STREAM_AAC = 15;
|
|
123
128
|
/**
|
|
124
129
|
* デジタルコピー制御記述子の中身 (タグと長さを除いたもの) から、**コピー禁止か**を読む。
|
|
125
130
|
*
|
package/dist/psi.js
CHANGED
|
@@ -314,6 +314,11 @@ export function* descriptors(data) {
|
|
|
314
314
|
}
|
|
315
315
|
/** デジタルコピー制御記述子。EIT の番組ごとと PMT に入る */
|
|
316
316
|
export const DESC_DIGITAL_COPY_CONTROL = 0xc1;
|
|
317
|
+
/**
|
|
318
|
+
* 音声の ES の stream_type (AAC。日本の放送の音声)。主音声の何本目かは、どこでもこの stream_type だけを PMT の順に数える
|
|
319
|
+
* (pes.ts の `readPmt`・bml.ts の `pmtAudios`・データ放送の主音声)。ffmpeg の `0:a:<n>` ともそろう
|
|
320
|
+
*/
|
|
321
|
+
export const STREAM_AAC = 0x0f;
|
|
317
322
|
/**
|
|
318
323
|
* デジタルコピー制御記述子の中身 (タグと長さを除いたもの) から、**コピー禁止か**を読む。
|
|
319
324
|
*
|