@danything/arib 1.2.0 → 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 +22 -22
- package/dist/psi.js +25 -25
- 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 +16 -16
- package/dist/synth.js +27 -27
- package/package.json +1 -1
package/dist/psi.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TS の土台 (パケットの切り出し・セクションの組み立て・PAT/PMT) と、局の一覧。
|
|
3
3
|
* 局の一覧はチャンネルスキャンで「この物理チャンネルに何が入っているか」を知るために使い、
|
|
4
|
-
* 読むのは NIT と SDT の2つ。
|
|
4
|
+
* 読むのは NIT と SDT の 2 つ。
|
|
5
5
|
*
|
|
6
|
-
* - NIT (PID 0x0010) … ネットワークID と、地上波ならリモコン番号。衛星はネットワークの全部の TS
|
|
6
|
+
* - NIT (PID 0x0010) … ネットワーク ID と、地上波ならリモコン番号。衛星はネットワークの全部の TS
|
|
7
7
|
* (TSID・周波数・サービスの一覧) が載っている (`NitReader`)
|
|
8
|
-
* - SDT (PID 0x0011) … その TS に入っているサービスのIDと種別。衛星はほかの TS のぶん
|
|
8
|
+
* - SDT (PID 0x0011) … その TS に入っているサービスの ID と種別。衛星はほかの TS のぶん
|
|
9
9
|
* (SDT[other]) も流れている (`SdtReader`)
|
|
10
10
|
*
|
|
11
11
|
* 局名も SDT から読む。ARIB の文字符号は独自だが、番組表を自分で集めるなら
|
|
@@ -34,9 +34,9 @@ export declare const SERVICE_TYPES: Set<number>;
|
|
|
34
34
|
/**
|
|
35
35
|
* セクション本体に CRC32 を付けて仕上げる。`section_length` も実長に直す。
|
|
36
36
|
*
|
|
37
|
-
* **書く側が2つある。** PAT を書き直して流す `service-filter.ts` と、
|
|
37
|
+
* **書く側が 2 つある。** PAT を書き直して流す `service-filter.ts` と、
|
|
38
38
|
* 偽の放送を組み立てる `synth.ts`。長さの直し方を間違えると読む側が黙って
|
|
39
|
-
* 捨てるだけなので、1箇所に置く。
|
|
39
|
+
* 捨てるだけなので、1 箇所に置く。
|
|
40
40
|
*/
|
|
41
41
|
export declare function withCrc(body: number[]): Uint8Array;
|
|
42
42
|
export interface Service {
|
|
@@ -60,26 +60,26 @@ export interface NetworkInfo {
|
|
|
60
60
|
*
|
|
61
61
|
* セクションは TS パケットをまたいで運ばれ、パケットの切れ目とは無関係な
|
|
62
62
|
* 位置で終わる。payload_unit_start_indicator と pointer_field を見て
|
|
63
|
-
* 頭を合わせ、section_length ぶん溜まったら1
|
|
63
|
+
* 頭を合わせ、section_length ぶん溜まったら 1 本として返す。
|
|
64
64
|
*/
|
|
65
65
|
export declare class SectionAssembler {
|
|
66
66
|
private readonly pid;
|
|
67
67
|
private readonly crc;
|
|
68
68
|
private buffer;
|
|
69
69
|
/**
|
|
70
|
-
* @param pid 読むPID
|
|
70
|
+
* @param pid 読む PID
|
|
71
71
|
* @param crc CRC の見方。
|
|
72
|
-
* `always` … 末尾4バイトを CRC32 とみなして必ず確かめる (PSI はこちら)
|
|
72
|
+
* `always` … 末尾 4 バイトを CRC32 とみなして必ず確かめる (PSI はこちら)
|
|
73
73
|
* `syntax` … `section_syntax_indicator` が立っているときだけ確かめる。
|
|
74
74
|
* DSM-CC は立っていないと末尾が CRC ではなく Checksum なので、
|
|
75
75
|
* いつも確かめると**全部捨ててしまう**
|
|
76
76
|
*/
|
|
77
77
|
constructor(pid: number, crc?: "always" | "syntax");
|
|
78
78
|
/**
|
|
79
|
-
* パケットを1
|
|
79
|
+
* パケットを 1 つ渡す。組み上がったセクションを返す。
|
|
80
80
|
*
|
|
81
81
|
* 返りは**読むだけ**にすること。何も組み上がらないとき (ほとんどのパケット) は
|
|
82
|
-
* 使い回しの空配列を返す
|
|
82
|
+
* 使い回しの空配列を返す (関係ないパケットのたびに配列を作っていた)
|
|
83
83
|
*/
|
|
84
84
|
feed(packet: Uint8Array): readonly Uint8Array[];
|
|
85
85
|
private append;
|
|
@@ -91,7 +91,7 @@ export declare function findSync(data: Uint8Array, from?: number, until?: number
|
|
|
91
91
|
* 任意の長さで届くバイト列を 188 バイトのパケットに切り分ける。
|
|
92
92
|
*
|
|
93
93
|
* 頭が必ずパケットの先頭とは限らず、電波が弱いと途中で数バイト落ちる。
|
|
94
|
-
* ずれたままだと**以降ずっと1パケットも読めなくなる**ので、頭が 0x47 でなければ
|
|
94
|
+
* ずれたままだと**以降ずっと 1 パケットも読めなくなる**ので、頭が 0x47 でなければ
|
|
95
95
|
* 取り直す。普段は先頭が 0x47 なので、探しに行くのはずれたときだけ。
|
|
96
96
|
*
|
|
97
97
|
* **出すパケットは渡された塊の上の窓** (写しではない。写すと録画の処理の 1/3 を食う)。
|
|
@@ -104,8 +104,8 @@ export declare class PacketStream {
|
|
|
104
104
|
feed(chunk: Uint8Array): Generator<Uint8Array>;
|
|
105
105
|
}
|
|
106
106
|
/**
|
|
107
|
-
* PAT から1つの局の PMT を追う。`serviceId` を渡さなければ PAT の最初の局
|
|
108
|
-
* (1局に絞った TS
|
|
107
|
+
* PAT から 1 つの局の PMT を追う。`serviceId` を渡さなければ PAT の最初の局
|
|
108
|
+
* (1 局に絞った TS を渡すところ)。PAT で PMT の PID が替われば組み立て直す
|
|
109
109
|
*/
|
|
110
110
|
export declare class PmtTracker {
|
|
111
111
|
private readonly serviceId?;
|
|
@@ -114,7 +114,7 @@ export declare class PmtTracker {
|
|
|
114
114
|
/** 追っている PMT の PID。PAT を読むまでは null。替わったかは呼ぶ前後で比べる */
|
|
115
115
|
pid: number | null;
|
|
116
116
|
constructor(serviceId?: number | undefined);
|
|
117
|
-
/** パケットを1つ (`pid` はその PID)。組み上がった PMT のセクションを返す */
|
|
117
|
+
/** パケットを 1 つ (`pid` はその PID)。組み上がった PMT のセクションを返す */
|
|
118
118
|
feed(packet: Uint8Array, pid: number): readonly Uint8Array[];
|
|
119
119
|
}
|
|
120
120
|
/** 記述子の並びを (tag, 中身) に切り分ける */
|
|
@@ -124,8 +124,8 @@ export declare const DESC_DIGITAL_COPY_CONTROL = 193;
|
|
|
124
124
|
/**
|
|
125
125
|
* デジタルコピー制御記述子の中身 (タグと長さを除いたもの) から、**コピー禁止か**を読む。
|
|
126
126
|
*
|
|
127
|
-
* 先頭2ビットの digital_recording_control_data が 11 なら禁止
|
|
128
|
-
* (00 コピー可、01 事業者定義、10 1世代のみ)。禁止の番組は録らない
|
|
127
|
+
* 先頭 2 ビットの digital_recording_control_data が 11 なら禁止
|
|
128
|
+
* (00 コピー可、01 事業者定義、10 1 世代のみ)。禁止の番組は録らない
|
|
129
129
|
* ([data.md](https://github.com/danything/denpa/blob/main/docs/data.md)「コピー禁止の番組は録らない」)
|
|
130
130
|
*/
|
|
131
131
|
export declare function isCopyNever(data: Uint8Array): boolean;
|
|
@@ -142,13 +142,13 @@ export declare function pmtProgramInfo(section: Uint8Array): Uint8Array;
|
|
|
142
142
|
* だけ**にして、選り分けは呼ぶ側に置いてあります。
|
|
143
143
|
*/
|
|
144
144
|
export declare function pmtStreams(section: Uint8Array): Generator<[number, number, Uint8Array]>;
|
|
145
|
-
/** PAT から `サービスID → PMT の PID`。サービス0 は NIT なので飛ばす */
|
|
145
|
+
/** PAT から `サービスID → PMT の PID`。サービス 0 は NIT なので飛ばす */
|
|
146
146
|
export declare function parsePat(section: Uint8Array): Map<number, number>;
|
|
147
147
|
/**
|
|
148
148
|
* SDT のサービスの並びを (service_id, 記述子の並び) に切り分ける。
|
|
149
149
|
*
|
|
150
|
-
* **読む側が2つある。** 局名 (`parseSdt`) とロゴの対応 (denpa の `ts/logo.ts`) で、
|
|
151
|
-
* 欲しい記述子が違うだけで歩き方は同じ。並びの読み方をここ1箇所に置く。
|
|
150
|
+
* **読む側が 2 つある。** 局名 (`parseSdt`) とロゴの対応 (denpa の `ts/logo.ts`) で、
|
|
151
|
+
* 欲しい記述子が違うだけで歩き方は同じ。並びの読み方をここ 1 箇所に置く。
|
|
152
152
|
*/
|
|
153
153
|
export declare function sdtServices(section: Uint8Array): Generator<[number, Uint8Array]>;
|
|
154
154
|
/** SDT からサービスの一覧を読む。自分の TS のものだけ */
|
|
@@ -212,7 +212,7 @@ export interface NitSection {
|
|
|
212
212
|
/** NIT のセクションを 1 つ読む。actual (0x40) と other (0x41) のどちらも */
|
|
213
213
|
export declare function parseNitSection(section: Uint8Array): NitSection | null;
|
|
214
214
|
/**
|
|
215
|
-
* NIT からネットワークIDとリモコン番号、他の TS の顔ぶれを読む。**セクション 1 つぶん。**
|
|
215
|
+
* NIT からネットワーク ID とリモコン番号、他の TS の顔ぶれを読む。**セクション 1 つぶん。**
|
|
216
216
|
* スキャンで「どのネットワークか」を知るにはこれで足りる。ネットワークの全部の TS が要るなら `NitReader`
|
|
217
217
|
*/
|
|
218
218
|
export declare function parseNit(section: Uint8Array): NetworkInfo | null;
|
|
@@ -287,7 +287,7 @@ export interface FoundService extends Service {
|
|
|
287
287
|
remoteControlKeyId: number | null;
|
|
288
288
|
}
|
|
289
289
|
/**
|
|
290
|
-
* 流れてくる TS
|
|
290
|
+
* 流れてくる TS を読んで、NIT と SDT が揃うまで待つ。
|
|
291
291
|
*
|
|
292
292
|
* Mirakurun のスキャンと同じで、**両方**揃って初めてそのチャンネルを
|
|
293
293
|
* 「受信できた」とみなす。SDT だけ取れても、どのネットワークのものか
|
|
@@ -300,7 +300,7 @@ export declare class ServiceReader {
|
|
|
300
300
|
network: NetworkInfo | null;
|
|
301
301
|
transport: TransportInfo | null;
|
|
302
302
|
get complete(): boolean;
|
|
303
|
-
/**
|
|
303
|
+
/** 任意の長さのバイト列を渡す。揃ったら true */
|
|
304
304
|
feed(chunk: Uint8Array): boolean;
|
|
305
305
|
/** 録るに値するサービスだけ。リモコン番号は NIT のものを配る */
|
|
306
306
|
services(): FoundService[];
|
package/dist/psi.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TS の土台 (パケットの切り出し・セクションの組み立て・PAT/PMT) と、局の一覧。
|
|
3
3
|
* 局の一覧はチャンネルスキャンで「この物理チャンネルに何が入っているか」を知るために使い、
|
|
4
|
-
* 読むのは NIT と SDT の2つ。
|
|
4
|
+
* 読むのは NIT と SDT の 2 つ。
|
|
5
5
|
*
|
|
6
|
-
* - NIT (PID 0x0010) … ネットワークID と、地上波ならリモコン番号。衛星はネットワークの全部の TS
|
|
6
|
+
* - NIT (PID 0x0010) … ネットワーク ID と、地上波ならリモコン番号。衛星はネットワークの全部の TS
|
|
7
7
|
* (TSID・周波数・サービスの一覧) が載っている (`NitReader`)
|
|
8
|
-
* - SDT (PID 0x0011) … その TS に入っているサービスのIDと種別。衛星はほかの TS のぶん
|
|
8
|
+
* - SDT (PID 0x0011) … その TS に入っているサービスの ID と種別。衛星はほかの TS のぶん
|
|
9
9
|
* (SDT[other]) も流れている (`SdtReader`)
|
|
10
10
|
*
|
|
11
11
|
* 局名も SDT から読む。ARIB の文字符号は独自だが、番組表を自分で集めるなら
|
|
@@ -54,7 +54,7 @@ const CRC32_TABLE = (() => {
|
|
|
54
54
|
}
|
|
55
55
|
return table;
|
|
56
56
|
})();
|
|
57
|
-
/** MPEG-2 の CRC32。セクション末尾の4バイトを含めて回すと 0 になる */
|
|
57
|
+
/** MPEG-2 の CRC32。セクション末尾の 4 バイトを含めて回すと 0 になる */
|
|
58
58
|
function crc32(data) {
|
|
59
59
|
let crc = 0xffffffff;
|
|
60
60
|
for (const byte of data) {
|
|
@@ -66,9 +66,9 @@ function crc32(data) {
|
|
|
66
66
|
/**
|
|
67
67
|
* セクション本体に CRC32 を付けて仕上げる。`section_length` も実長に直す。
|
|
68
68
|
*
|
|
69
|
-
* **書く側が2つある。** PAT を書き直して流す `service-filter.ts` と、
|
|
69
|
+
* **書く側が 2 つある。** PAT を書き直して流す `service-filter.ts` と、
|
|
70
70
|
* 偽の放送を組み立てる `synth.ts`。長さの直し方を間違えると読む側が黙って
|
|
71
|
-
* 捨てるだけなので、1箇所に置く。
|
|
71
|
+
* 捨てるだけなので、1 箇所に置く。
|
|
72
72
|
*/
|
|
73
73
|
export function withCrc(body) {
|
|
74
74
|
const section = Uint8Array.from(body);
|
|
@@ -87,16 +87,16 @@ const NONE = Object.freeze([]);
|
|
|
87
87
|
*
|
|
88
88
|
* セクションは TS パケットをまたいで運ばれ、パケットの切れ目とは無関係な
|
|
89
89
|
* 位置で終わる。payload_unit_start_indicator と pointer_field を見て
|
|
90
|
-
* 頭を合わせ、section_length ぶん溜まったら1
|
|
90
|
+
* 頭を合わせ、section_length ぶん溜まったら 1 本として返す。
|
|
91
91
|
*/
|
|
92
92
|
export class SectionAssembler {
|
|
93
93
|
pid;
|
|
94
94
|
crc;
|
|
95
95
|
buffer = new Uint8Array(0);
|
|
96
96
|
/**
|
|
97
|
-
* @param pid 読むPID
|
|
97
|
+
* @param pid 読む PID
|
|
98
98
|
* @param crc CRC の見方。
|
|
99
|
-
* `always` … 末尾4バイトを CRC32 とみなして必ず確かめる (PSI はこちら)
|
|
99
|
+
* `always` … 末尾 4 バイトを CRC32 とみなして必ず確かめる (PSI はこちら)
|
|
100
100
|
* `syntax` … `section_syntax_indicator` が立っているときだけ確かめる。
|
|
101
101
|
* DSM-CC は立っていないと末尾が CRC ではなく Checksum なので、
|
|
102
102
|
* いつも確かめると**全部捨ててしまう**
|
|
@@ -106,10 +106,10 @@ export class SectionAssembler {
|
|
|
106
106
|
this.crc = crc;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
-
* パケットを1
|
|
109
|
+
* パケットを 1 つ渡す。組み上がったセクションを返す。
|
|
110
110
|
*
|
|
111
111
|
* 返りは**読むだけ**にすること。何も組み上がらないとき (ほとんどのパケット) は
|
|
112
|
-
* 使い回しの空配列を返す
|
|
112
|
+
* 使い回しの空配列を返す (関係ないパケットのたびに配列を作っていた)
|
|
113
113
|
*/
|
|
114
114
|
feed(packet) {
|
|
115
115
|
// トランスポートエラーが立っているものは信用しない
|
|
@@ -173,7 +173,7 @@ export class SectionAssembler {
|
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
175
|
* 同期が取れているとみなすのに必要な連続パケット数。
|
|
176
|
-
* 1つだけでは中身のたまたまの 0x47 を頭と誤認する
|
|
176
|
+
* 1 つだけでは中身のたまたまの 0x47 を頭と誤認する
|
|
177
177
|
*/
|
|
178
178
|
const CONFIRM = 3;
|
|
179
179
|
/** `from` 以降 `until` の手前までで、188 間隔に 0x47 が続くところを探す。無ければ -1 (denpa の `seek.ts` も使う) */
|
|
@@ -191,7 +191,7 @@ export function findSync(data, from = 0, until = data.length) {
|
|
|
191
191
|
* 任意の長さで届くバイト列を 188 バイトのパケットに切り分ける。
|
|
192
192
|
*
|
|
193
193
|
* 頭が必ずパケットの先頭とは限らず、電波が弱いと途中で数バイト落ちる。
|
|
194
|
-
* ずれたままだと**以降ずっと1パケットも読めなくなる**ので、頭が 0x47 でなければ
|
|
194
|
+
* ずれたままだと**以降ずっと 1 パケットも読めなくなる**ので、頭が 0x47 でなければ
|
|
195
195
|
* 取り直す。普段は先頭が 0x47 なので、探しに行くのはずれたときだけ。
|
|
196
196
|
*
|
|
197
197
|
* **出すパケットは渡された塊の上の窓** (写しではない。写すと録画の処理の 1/3 を食う)。
|
|
@@ -205,7 +205,7 @@ export class PacketStream {
|
|
|
205
205
|
/*
|
|
206
206
|
* 前の残り (`rest`) と塊を繋いだ並びの上を歩く。位置 `at` はその並びでの位置。
|
|
207
207
|
* 繋ぐのは**残りに頭があるパケットを読むのに要るぶんだけ** (頭を探すのに
|
|
208
|
-
* 3パケットぶん先まで見る)
|
|
208
|
+
* 3 パケットぶん先まで見る)
|
|
209
209
|
*/
|
|
210
210
|
const split = this.rest.length;
|
|
211
211
|
const total = split + chunk.length;
|
|
@@ -267,8 +267,8 @@ export class PacketStream {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
/**
|
|
270
|
-
* PAT から1つの局の PMT を追う。`serviceId` を渡さなければ PAT の最初の局
|
|
271
|
-
* (1局に絞った TS
|
|
270
|
+
* PAT から 1 つの局の PMT を追う。`serviceId` を渡さなければ PAT の最初の局
|
|
271
|
+
* (1 局に絞った TS を渡すところ)。PAT で PMT の PID が替われば組み立て直す
|
|
272
272
|
*/
|
|
273
273
|
export class PmtTracker {
|
|
274
274
|
serviceId;
|
|
@@ -279,7 +279,7 @@ export class PmtTracker {
|
|
|
279
279
|
constructor(serviceId) {
|
|
280
280
|
this.serviceId = serviceId;
|
|
281
281
|
}
|
|
282
|
-
/** パケットを1つ (`pid` はその PID)。組み上がった PMT のセクションを返す */
|
|
282
|
+
/** パケットを 1 つ (`pid` はその PID)。組み上がった PMT のセクションを返す */
|
|
283
283
|
feed(packet, pid) {
|
|
284
284
|
if (pid === PID_PAT) {
|
|
285
285
|
for (const section of this.pat.feed(packet)) {
|
|
@@ -314,8 +314,8 @@ export const DESC_DIGITAL_COPY_CONTROL = 0xc1;
|
|
|
314
314
|
/**
|
|
315
315
|
* デジタルコピー制御記述子の中身 (タグと長さを除いたもの) から、**コピー禁止か**を読む。
|
|
316
316
|
*
|
|
317
|
-
* 先頭2ビットの digital_recording_control_data が 11 なら禁止
|
|
318
|
-
* (00 コピー可、01 事業者定義、10 1世代のみ)。禁止の番組は録らない
|
|
317
|
+
* 先頭 2 ビットの digital_recording_control_data が 11 なら禁止
|
|
318
|
+
* (00 コピー可、01 事業者定義、10 1 世代のみ)。禁止の番組は録らない
|
|
319
319
|
* ([data.md](https://github.com/danything/denpa/blob/main/docs/data.md)「コピー禁止の番組は録らない」)
|
|
320
320
|
*/
|
|
321
321
|
export function isCopyNever(data) {
|
|
@@ -351,7 +351,7 @@ export function* pmtStreams(section) {
|
|
|
351
351
|
at += 5 + infoLength;
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
|
-
/** PAT から `サービスID → PMT の PID`。サービス0 は NIT なので飛ばす */
|
|
354
|
+
/** PAT から `サービスID → PMT の PID`。サービス 0 は NIT なので飛ばす */
|
|
355
355
|
export function parsePat(section) {
|
|
356
356
|
const programs = new Map();
|
|
357
357
|
if (section[0] !== TABLE_PAT)
|
|
@@ -368,8 +368,8 @@ export function parsePat(section) {
|
|
|
368
368
|
/**
|
|
369
369
|
* SDT のサービスの並びを (service_id, 記述子の並び) に切り分ける。
|
|
370
370
|
*
|
|
371
|
-
* **読む側が2つある。** 局名 (`parseSdt`) とロゴの対応 (denpa の `ts/logo.ts`) で、
|
|
372
|
-
* 欲しい記述子が違うだけで歩き方は同じ。並びの読み方をここ1箇所に置く。
|
|
371
|
+
* **読む側が 2 つある。** 局名 (`parseSdt`) とロゴの対応 (denpa の `ts/logo.ts`) で、
|
|
372
|
+
* 欲しい記述子が違うだけで歩き方は同じ。並びの読み方をここ 1 箇所に置く。
|
|
373
373
|
*/
|
|
374
374
|
export function* sdtServices(section) {
|
|
375
375
|
let at = 11;
|
|
@@ -531,7 +531,7 @@ export function parseNitSection(section) {
|
|
|
531
531
|
};
|
|
532
532
|
}
|
|
533
533
|
/**
|
|
534
|
-
* NIT からネットワークIDとリモコン番号、他の TS の顔ぶれを読む。**セクション 1 つぶん。**
|
|
534
|
+
* NIT からネットワーク ID とリモコン番号、他の TS の顔ぶれを読む。**セクション 1 つぶん。**
|
|
535
535
|
* スキャンで「どのネットワークか」を知るにはこれで足りる。ネットワークの全部の TS が要るなら `NitReader`
|
|
536
536
|
*/
|
|
537
537
|
export function parseNit(section) {
|
|
@@ -720,7 +720,7 @@ export class SdtReader {
|
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
722
|
/**
|
|
723
|
-
* 流れてくる TS
|
|
723
|
+
* 流れてくる TS を読んで、NIT と SDT が揃うまで待つ。
|
|
724
724
|
*
|
|
725
725
|
* Mirakurun のスキャンと同じで、**両方**揃って初めてそのチャンネルを
|
|
726
726
|
* 「受信できた」とみなす。SDT だけ取れても、どのネットワークのものか
|
|
@@ -735,7 +735,7 @@ export class ServiceReader {
|
|
|
735
735
|
get complete() {
|
|
736
736
|
return this.network !== null && this.transport !== null;
|
|
737
737
|
}
|
|
738
|
-
/**
|
|
738
|
+
/** 任意の長さのバイト列を渡す。揃ったら true */
|
|
739
739
|
feed(chunk) {
|
|
740
740
|
for (const packet of this.packets.feed(chunk)) {
|
|
741
741
|
if (this.network === null) {
|
package/dist/service-filter.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 物理チャンネル丸ごとの TS から、1つの局のぶんだけを抜き出す。
|
|
2
|
+
* 物理チャンネル丸ごとの TS から、1 つの局のぶんだけを抜き出す。
|
|
3
3
|
*
|
|
4
4
|
* エージェントは**中身を読まずに素の TS を流す**ので
|
|
5
5
|
* ([agent.md](https://github.com/danything/denpa/blob/main/docs/agent.md))、選り分けるのは denpa の仕事。
|
|
6
6
|
*
|
|
7
|
-
* **これをやらないと1つの録画に複数の番組が入る。** 実機の TOKYO MX は
|
|
8
|
-
* 1本の TS に MX1 と MX2 を載せていて、丸ごと保存すると ffprobe が2つの
|
|
7
|
+
* **これをやらないと 1 つの録画に複数の番組が入る。** 実機の TOKYO MX は
|
|
8
|
+
* 1 本の TS に MX1 と MX2 を載せていて、丸ごと保存すると ffprobe が 2 つの
|
|
9
9
|
* プログラムを返す (これで CM 検出の fps を読み違えたことがある)。
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* 残すものは次のとおり。
|
|
12
12
|
*
|
|
13
|
-
* - **PAT** … その局1つだけに**書き直して**出す。丸ごと通すと ffmpeg には
|
|
13
|
+
* - **PAT** … その局 1 つだけに**書き直して**出す。丸ごと通すと ffmpeg には
|
|
14
14
|
* 相変わらず複数のプログラムが見える
|
|
15
15
|
* - **PMT と、そこに載っている ES** … 映像・音声・字幕。ECM も (掛かったまま
|
|
16
16
|
* 録れたものを後から復号するのに要る)
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* 落とすもの: 他局の PMT と ES、そして詰め物 (PID 0x1FFF)。
|
|
21
21
|
*/
|
|
22
22
|
/**
|
|
23
|
-
* 局1つぶんに絞る。
|
|
23
|
+
* 局 1 つぶんに絞る。
|
|
24
24
|
*
|
|
25
25
|
* PAT と PMT を読むまでは**何も出さない**。どの PID がその局のものか決まらないためで、
|
|
26
26
|
* どちらも 100ms ごとに流れてくるので待つのは一瞬。**待つ間に届いたものは取っておき**、PMT を読んだら
|
|
@@ -44,15 +44,15 @@ export declare class ServiceFilter {
|
|
|
44
44
|
/** PMT を読む前に届いた、局の分からないパケット (写したもの)。届いた順 */
|
|
45
45
|
private held;
|
|
46
46
|
constructor(serviceId: number);
|
|
47
|
-
/** その局の PMT を読めたか。読めるまで映像は1バイトも出ない (届いたものは取っておく) */
|
|
47
|
+
/** その局の PMT を読めたか。読めるまで映像は 1 バイトも出ない (届いたものは取っておく) */
|
|
48
48
|
get ready(): boolean;
|
|
49
49
|
/**
|
|
50
50
|
* **いま流れているものがコピー禁止か** (最後に読んだ PMT のデジタルコピー制御記述子)。
|
|
51
|
-
* 番組全体 (1つめのループ) と ES ごと (2つめのループ) のどちらかが禁止なら禁止。
|
|
51
|
+
* 番組全体 (1 つめのループ) と ES ごと (2 つめのループ) のどちらかが禁止なら禁止。
|
|
52
52
|
* PMT を読むまでは false。
|
|
53
53
|
*
|
|
54
54
|
* 録画はこれを見て、禁止のあいだは保存しない (denpa の `recorder.ts`)。番組表が古い・無いときの備え。
|
|
55
|
-
*
|
|
55
|
+
* 絞り方には効かせない。ライブは保存しないので、禁止の番組もそのまま観られる
|
|
56
56
|
*/
|
|
57
57
|
get copyNever(): boolean;
|
|
58
58
|
/**
|
|
@@ -60,21 +60,21 @@ export declare class ServiceFilter {
|
|
|
60
60
|
*
|
|
61
61
|
* これが変わったら ffmpeg を作り直す (`StreamsWatch`)。ffmpeg は起きたときの並びのまま
|
|
62
62
|
* 音声・字幕を選んでいるので、番組が替わって音声の本数や字幕の PID が変わると追従しない。
|
|
63
|
-
* データ放送などのセクション (0x0D など)
|
|
63
|
+
* データ放送などのセクション (0x0D など) は入れない。番組ごとに増減しても ffmpeg には関係ない
|
|
64
64
|
*/
|
|
65
65
|
get streams(): string | null;
|
|
66
66
|
/**
|
|
67
67
|
* **中継の番号 (transport_stream_id)。** PAT を読むまでは null。
|
|
68
68
|
*
|
|
69
69
|
* 絞るのに要るわけではありません。**データ放送が受信機に訊いてくる**ので
|
|
70
|
-
*
|
|
70
|
+
* 覚えておきます。テレ朝の TVerリンクは `browser.getProgramID(4)` で
|
|
71
71
|
* これを取り、TVer のサーバへそのまま送る。`null` のまま渡すと文字の
|
|
72
72
|
* "null" が飛んで、あちらが断り、画面には `DT-RE` とだけ出ます
|
|
73
73
|
* ([server/live.ts](https://github.com/danything/denpa/blob/main/src/lib/server/live.ts) の `programInfo`)
|
|
74
74
|
*/
|
|
75
75
|
get transportStreamId(): number | null;
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* 任意の長さのバイト列を渡すと、残すぶんを返す。
|
|
78
78
|
*
|
|
79
79
|
* 落とした PID の連続性カウンタは飛ぶが、**残す PID は元のまま**なので
|
|
80
80
|
* 読む側から見て抜けは無い。自分で作るのは PAT だけで、そこは自前で数える。
|
|
@@ -93,10 +93,10 @@ export declare class ServiceFilter {
|
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
95
|
* **映像・音声・字幕の並びが変わったか** (`ServiceFilter.streams`) を見る。最初に読んだ並びを覚え、変わったら
|
|
96
|
-
* 1回だけ true を返して新しい並びを覚え直す。
|
|
96
|
+
* 1 回だけ true を返して新しい並びを覚え直す。
|
|
97
97
|
*
|
|
98
98
|
* 並びを決め打ちで起こした ffmpeg (`-map`) は、番組が替わって音声の本数や字幕の PID が変わっても追従しない。
|
|
99
|
-
*
|
|
99
|
+
* 変わったら起こし直す。使うのはライブと追っかけのエンコード (denpa の `server/live.ts` の `Session.pump`)、MPEG-2 をそのまま
|
|
100
100
|
* 流す経路の字幕 (`Session.runRaw`・`recordingCaptions`)
|
|
101
101
|
*/
|
|
102
102
|
export declare class StreamsWatch {
|
package/dist/service-filter.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 物理チャンネル丸ごとの TS から、1つの局のぶんだけを抜き出す。
|
|
2
|
+
* 物理チャンネル丸ごとの TS から、1 つの局のぶんだけを抜き出す。
|
|
3
3
|
*
|
|
4
4
|
* エージェントは**中身を読まずに素の TS を流す**ので
|
|
5
5
|
* ([agent.md](https://github.com/danything/denpa/blob/main/docs/agent.md))、選り分けるのは denpa の仕事。
|
|
6
6
|
*
|
|
7
|
-
* **これをやらないと1つの録画に複数の番組が入る。** 実機の TOKYO MX は
|
|
8
|
-
* 1本の TS に MX1 と MX2 を載せていて、丸ごと保存すると ffprobe が2つの
|
|
7
|
+
* **これをやらないと 1 つの録画に複数の番組が入る。** 実機の TOKYO MX は
|
|
8
|
+
* 1 本の TS に MX1 と MX2 を載せていて、丸ごと保存すると ffprobe が 2 つの
|
|
9
9
|
* プログラムを返す (これで CM 検出の fps を読み違えたことがある)。
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* 残すものは次のとおり。
|
|
12
12
|
*
|
|
13
|
-
* - **PAT** … その局1つだけに**書き直して**出す。丸ごと通すと ffmpeg には
|
|
13
|
+
* - **PAT** … その局 1 つだけに**書き直して**出す。丸ごと通すと ffmpeg には
|
|
14
14
|
* 相変わらず複数のプログラムが見える
|
|
15
15
|
* - **PMT と、そこに載っている ES** … 映像・音声・字幕。ECM も (掛かったまま
|
|
16
16
|
* 録れたものを後から復号するのに要る)
|
|
@@ -25,7 +25,7 @@ const PID_NULL = 0x1fff;
|
|
|
25
25
|
/**
|
|
26
26
|
* 局に関係なく残す PID。**どれも数十バイト/秒**で、落として得るものが無い。
|
|
27
27
|
*
|
|
28
|
-
* CDT (ロゴ) はここに入れない。録画に要らないうえ、衛星では数百KBのカルーセルが
|
|
28
|
+
* CDT (ロゴ) はここに入れない。録画に要らないうえ、衛星では数百 KB のカルーセルが
|
|
29
29
|
* 流れてくる。ロゴを取得するのは録画の外でやる (denpa の logo.ts)
|
|
30
30
|
*/
|
|
31
31
|
const KEEP = new Set([
|
|
@@ -43,7 +43,7 @@ const DESC_CA = 0x09;
|
|
|
43
43
|
* BS の中継丸ごと (52Mbit/s) でも 7,000 個ほど。来ない (局を読み違えた) ときに抱え込み続けないよう、超えたら古いほうから捨てる
|
|
44
44
|
*/
|
|
45
45
|
const HOLD_MOST = 8192;
|
|
46
|
-
/** 1つの局に絞った PAT を組み立てる */
|
|
46
|
+
/** 1 つの局に絞った PAT を組み立てる */
|
|
47
47
|
function buildPat(transportStreamId, version, serviceId, pmtPid) {
|
|
48
48
|
const body = [
|
|
49
49
|
TABLE_PAT,
|
|
@@ -66,7 +66,7 @@ function buildPat(transportStreamId, version, serviceId, pmtPid) {
|
|
|
66
66
|
];
|
|
67
67
|
return withCrc(body);
|
|
68
68
|
}
|
|
69
|
-
/** セクション1本を TS パケット1つに詰める。PAT は小さいので必ず収まる */
|
|
69
|
+
/** セクション 1 本を TS パケット 1 つに詰める。PAT は小さいので必ず収まる */
|
|
70
70
|
function packet(pid, section, counter) {
|
|
71
71
|
const out = new Uint8Array(PACKET).fill(0xff);
|
|
72
72
|
out[0] = SYNC;
|
|
@@ -83,7 +83,7 @@ function packet(pid, section, counter) {
|
|
|
83
83
|
*/
|
|
84
84
|
const MEDIA_STREAMS = new Set([0x02, 0x1b, 0x24, 0x03, 0x04, 0x0f, 0x11, 0x06]);
|
|
85
85
|
/**
|
|
86
|
-
* 局1つぶんに絞る。
|
|
86
|
+
* 局 1 つぶんに絞る。
|
|
87
87
|
*
|
|
88
88
|
* PAT と PMT を読むまでは**何も出さない**。どの PID がその局のものか決まらないためで、
|
|
89
89
|
* どちらも 100ms ごとに流れてくるので待つのは一瞬。**待つ間に届いたものは取っておき**、PMT を読んだら
|
|
@@ -109,17 +109,17 @@ export class ServiceFilter {
|
|
|
109
109
|
constructor(serviceId) {
|
|
110
110
|
this.serviceId = serviceId;
|
|
111
111
|
}
|
|
112
|
-
/** その局の PMT を読めたか。読めるまで映像は1バイトも出ない (届いたものは取っておく) */
|
|
112
|
+
/** その局の PMT を読めたか。読めるまで映像は 1 バイトも出ない (届いたものは取っておく) */
|
|
113
113
|
get ready() {
|
|
114
114
|
return this.own.size > 0;
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
117
|
* **いま流れているものがコピー禁止か** (最後に読んだ PMT のデジタルコピー制御記述子)。
|
|
118
|
-
* 番組全体 (1つめのループ) と ES ごと (2つめのループ) のどちらかが禁止なら禁止。
|
|
118
|
+
* 番組全体 (1 つめのループ) と ES ごと (2 つめのループ) のどちらかが禁止なら禁止。
|
|
119
119
|
* PMT を読むまでは false。
|
|
120
120
|
*
|
|
121
121
|
* 録画はこれを見て、禁止のあいだは保存しない (denpa の `recorder.ts`)。番組表が古い・無いときの備え。
|
|
122
|
-
*
|
|
122
|
+
* 絞り方には効かせない。ライブは保存しないので、禁止の番組もそのまま観られる
|
|
123
123
|
*/
|
|
124
124
|
get copyNever() {
|
|
125
125
|
return this.copyNeverNow;
|
|
@@ -129,7 +129,7 @@ export class ServiceFilter {
|
|
|
129
129
|
*
|
|
130
130
|
* これが変わったら ffmpeg を作り直す (`StreamsWatch`)。ffmpeg は起きたときの並びのまま
|
|
131
131
|
* 音声・字幕を選んでいるので、番組が替わって音声の本数や字幕の PID が変わると追従しない。
|
|
132
|
-
* データ放送などのセクション (0x0D など)
|
|
132
|
+
* データ放送などのセクション (0x0D など) は入れない。番組ごとに増減しても ffmpeg には関係ない
|
|
133
133
|
*/
|
|
134
134
|
get streams() {
|
|
135
135
|
return this.streamsNow;
|
|
@@ -138,7 +138,7 @@ export class ServiceFilter {
|
|
|
138
138
|
* **中継の番号 (transport_stream_id)。** PAT を読むまでは null。
|
|
139
139
|
*
|
|
140
140
|
* 絞るのに要るわけではありません。**データ放送が受信機に訊いてくる**ので
|
|
141
|
-
*
|
|
141
|
+
* 覚えておきます。テレ朝の TVerリンクは `browser.getProgramID(4)` で
|
|
142
142
|
* これを取り、TVer のサーバへそのまま送る。`null` のまま渡すと文字の
|
|
143
143
|
* "null" が飛んで、あちらが断り、画面には `DT-RE` とだけ出ます
|
|
144
144
|
* ([server/live.ts](https://github.com/danything/denpa/blob/main/src/lib/server/live.ts) の `programInfo`)
|
|
@@ -147,7 +147,7 @@ export class ServiceFilter {
|
|
|
147
147
|
return this.tsid;
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
150
|
-
*
|
|
150
|
+
* 任意の長さのバイト列を渡すと、残すぶんを返す。
|
|
151
151
|
*
|
|
152
152
|
* 落とした PID の連続性カウンタは飛ぶが、**残す PID は元のまま**なので
|
|
153
153
|
* 読む側から見て抜けは無い。自分で作るのは PAT だけで、そこは自前で数える。
|
|
@@ -185,7 +185,7 @@ export class ServiceFilter {
|
|
|
185
185
|
/** PMT を読む前のパケットを取っておく。**写す** (パケットは届いた塊の上の窓。`PacketStream`) */
|
|
186
186
|
hold(ts) {
|
|
187
187
|
this.held.push(ts.slice());
|
|
188
|
-
// 溢れたら古い半分を捨てる (1つずつ捨てると、来ないあいだずっと詰め直すことになる)
|
|
188
|
+
// 溢れたら古い半分を捨てる (1 つずつ捨てると、来ないあいだずっと詰め直すことになる)
|
|
189
189
|
if (this.held.length > HOLD_MOST)
|
|
190
190
|
this.held = this.held.slice(this.held.length - HOLD_MOST / 2);
|
|
191
191
|
}
|
|
@@ -246,10 +246,10 @@ export class ServiceFilter {
|
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
248
248
|
* **映像・音声・字幕の並びが変わったか** (`ServiceFilter.streams`) を見る。最初に読んだ並びを覚え、変わったら
|
|
249
|
-
* 1回だけ true を返して新しい並びを覚え直す。
|
|
249
|
+
* 1 回だけ true を返して新しい並びを覚え直す。
|
|
250
250
|
*
|
|
251
251
|
* 並びを決め打ちで起こした ffmpeg (`-map`) は、番組が替わって音声の本数や字幕の PID が変わっても追従しない。
|
|
252
|
-
*
|
|
252
|
+
* 変わったら起こし直す。使うのはライブと追っかけのエンコード (denpa の `server/live.ts` の `Session.pump`)、MPEG-2 をそのまま
|
|
253
253
|
* 流す経路の字幕 (`Session.runRaw`・`recordingCaptions`)
|
|
254
254
|
*/
|
|
255
255
|
export class StreamsWatch {
|
package/dist/synth-av.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* **本物の MPEG-2 映像と AAC 音声を、ffmpeg 無しで組み立てる** (試験用)。
|
|
3
3
|
*
|
|
4
|
-
* denpa のライブを変換せずに送る経路 (docs/stream.md#放送そのままmpeg-2を送る) は、ブラウザが MPEG-2 をデコードして映像を出す
|
|
4
|
+
* denpa のライブを変換せずに送る経路 (docs/stream.md#放送そのまま mpeg-2 を送る) は、ブラウザが MPEG-2 をデコードして映像を出す
|
|
5
5
|
* ところまでが仕事で、そこを試すには**本当にデコードできる放送**が要る。偽エージェントの
|
|
6
6
|
* 放送は中身を 0xFF で埋めていて、デコードするものが無い。E2E のイメージには本物の ffmpeg も
|
|
7
7
|
* 入っていない (数十分かかる組み立てを避けている) ので、ここで小さく作る。
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
* - 映像 … 256x144 の**I フレームだけ**。マクロブロックごとに色 (DC) だけを置き、
|
|
10
10
|
* AC は持たない (EOB だけ)。コマごとに縞が流れるので、**映像が進んでいるか**を
|
|
11
11
|
* 画素で見分けられる。インタレの印も立て、輝度は上下のフィールドで別の時刻の映像にする (フィールド DCT)
|
|
12
|
-
* - 音声 … 48kHz ステレオの AAC-LC の**無音**を ADTS で。1コマ 7 バイト
|
|
12
|
+
* - 音声 … 48kHz ステレオの AAC-LC の**無音**を ADTS で。1 コマ 7 バイト
|
|
13
13
|
*
|
|
14
14
|
* 規格は ISO/IEC 13818-2 (映像) と 13818-7 / 14496-3 (AAC)。表の出どころは
|
|
15
15
|
* 各関数の頭に書いてある。
|
|
16
16
|
*/
|
|
17
|
-
/** 29.97 コマ/秒の1コマ (90kHz)。放送と同じ */
|
|
17
|
+
/** 29.97 コマ/秒の 1 コマ (90kHz)。放送と同じ */
|
|
18
18
|
export declare const FRAME_TICKS = 3003;
|
|
19
|
-
/** AAC の1コマ (1024 標本 @48kHz を 90kHz で) */
|
|
19
|
+
/** AAC の 1 コマ (1024 標本 @48kHz を 90kHz で) */
|
|
20
20
|
export declare const AUDIO_TICKS = 1920;
|
|
21
21
|
/**
|
|
22
|
-
* I フレームを1
|
|
22
|
+
* I フレームを 1 枚。**毎枚、系列ヘッダから書く。** どこから受け取っても頭からデコードできる
|
|
23
23
|
* (放送は GOP ごとに書く。試験ではその手間を省く)。
|
|
24
24
|
*
|
|
25
25
|
* @param n 何枚目か。色と time_code に使う
|
|
@@ -27,10 +27,10 @@ export declare const AUDIO_TICKS = 1920;
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function mpeg2Frame(n: number, color?: (col: number, row: number, n: number, field: 0 | 1) => [number, number, number]): Uint8Array;
|
|
29
29
|
/**
|
|
30
|
-
* AAC-LC の無音を1コマ、ADTS の頭付きで。48kHz・ステレオ (channel_configuration 2)。
|
|
30
|
+
* AAC-LC の無音を 1 コマ、ADTS の頭付きで。48kHz・ステレオ (channel_configuration 2)。
|
|
31
31
|
*
|
|
32
|
-
* 中身は CPE が1つ: 両耳とも `max_sfb = 0` (係数を1つも持たない) で、あとは END。
|
|
33
|
-
* 55 ビットなので7バイトに収まる (14496-3 の raw_data_block)
|
|
32
|
+
* 中身は CPE が 1 つ: 両耳とも `max_sfb = 0` (係数を 1 つも持たない) で、あとは END。
|
|
33
|
+
* 55 ビットなので 7 バイトに収まる (14496-3 の raw_data_block)
|
|
34
34
|
*/
|
|
35
35
|
export declare function silentAac(): Uint8Array;
|
|
36
36
|
/**
|