@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/dist/eit.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * 空いているだけ並列に回せる**し、録画で開いているチャンネルのぶんはただで
6
6
  * 手に入る ([agent.md](https://github.com/danything/denpa/blob/main/docs/agent.md))。
7
7
  *
8
- * 扱うのは2種類。
8
+ * 扱うのは 2 種類。
9
9
  *
10
10
  * - **EIT[p/f]** (table_id 0x4E) … いま流れている番組と次の番組。**放送に追従する。**
11
11
  * 野球で延びた終了時刻はここに出る
@@ -22,9 +22,9 @@ const SCHEDULE_ACTUAL_MIN = 0x50;
22
22
  /** 詳細 (extended) の表はここから。基本と同じ並びがもう一度始まる */
23
23
  const SCHEDULE_ACTUAL_EXTENDED = 0x58;
24
24
  const SCHEDULE_ACTUAL_MAX = 0x5f;
25
- /** セグメント1つが受け持つ時間。0:00 から3時間ずつ、1日8つ */
25
+ /** セグメント 1 つが受け持つ時間。0:00 から 3 時間ずつ、1 日 8 つ */
26
26
  const SEGMENT_SPAN = 3 * 3600_000;
27
- /** 1つの table_id が持つセグメントの数 (= 4日ぶん) */
27
+ /** 1 つの table_id が持つセグメントの数 (= 4 日ぶん) */
28
28
  const SEGMENTS_PER_TABLE = 32;
29
29
  const DESC_SHORT_EVENT = 0x4d;
30
30
  const DESC_EXTENDED_EVENT = 0x4e;
@@ -42,7 +42,7 @@ function isEitActual(tableId) {
42
42
  * 並びは自局のもの (0x50〜0x5F) と同じで、`OTHER_SHIFT` だけずれている。
43
43
  *
44
44
  * BS・CS はどの中継にもネットワーク全局ぶんが流れているが、**詳細はほぼ付かない**
45
- * (実測で BS 45 局のうち2局ぶん。denpa の docs/data.md)。いま/次 (0x4F) は読まない
45
+ * (実測で BS 45 局のうち 2 局ぶん。denpa の docs/data.md)。いま/次 (0x4F) は読まない
46
46
  */
47
47
  const SCHEDULE_OTHER_MIN = 0x60;
48
48
  const SCHEDULE_OTHER_MAX = 0x6f;
@@ -59,7 +59,7 @@ const TABLE_TOT = 0x73;
59
59
  /**
60
60
  * TDT / TOT のセクションから**放送の実時刻**を読む。別のテーブルなら null。
61
61
  *
62
- * 頭3バイトのあとに MJD + BCD が5バイト。**TOT も同じ並び**で、後ろに
62
+ * 頭 3 バイトのあとに MJD + BCD が 5 バイト。**TOT も同じ並び**で、後ろに
63
63
  * 時差の記述子が付くだけなので同じに読める。
64
64
  *
65
65
  * データ放送 (`bml.ts` の `onTime`) が読み、BML の時計にします
@@ -70,9 +70,9 @@ export function parseTimeTable(section) {
70
70
  return parseMjdTime(section, 3);
71
71
  }
72
72
  /**
73
- * MJD + BCD の5バイトを epoch ms に直す。
73
+ * MJD + BCD の 5 バイトを epoch ms に直す。
74
74
  *
75
- * 全ビットが1なら「未定」。開始時刻が未定の番組は番組表に置けないので null で返す。
75
+ * 全ビットが 1 なら「未定」。開始時刻が未定の番組は番組表に置けないので null で返す。
76
76
  */
77
77
  export function parseMjdTime(data, at) {
78
78
  if ([0, 1, 2, 3, 4].every((i) => data[at + i] === 0xff))
@@ -85,7 +85,7 @@ export function parseMjdTime(data, at) {
85
85
  JST_OFFSET;
86
86
  return seconds * 1000;
87
87
  }
88
- /** BCD 3バイトの尺 (時分秒) を ms に。全ビット1なら「終了未定」 */
88
+ /** BCD 3 バイトの尺 (時分秒) を ms に。全ビット 1 なら「終了未定」 */
89
89
  export function parseBcdDuration(data, at) {
90
90
  if (data[at] === 0xff && data[at + 1] === 0xff && data[at + 2] === 0xff)
91
91
  return null;
@@ -115,7 +115,7 @@ const VIDEO_CODEC = {
115
115
  5: "h.264",
116
116
  9: "h.265",
117
117
  };
118
- /** audio_component_descriptor の sampling_rate。3ビットの符号 */
118
+ /** audio_component_descriptor の sampling_rate。3 ビットの符号 */
119
119
  const SAMPLING_RATE = {
120
120
  1: 16000,
121
121
  2: 22050,
@@ -137,13 +137,22 @@ const lang = (data, at) => ascii(data, at, 3).toLowerCase();
137
137
  * 正しくは「音楽制作:ONE MUSIC」)。分割点は
138
138
  *
139
139
  * - **二バイト文字の途中**に来ることがある (片割れだけでは字にならない)
140
- * - **文字集合の状態を持ち越す** — G0〜G3 の指示も GL/GR の呼び出しも、
140
+ * - **文字集合の状態を持ち越す。** G0〜G3 の指示も GL/GR の呼び出しも、
141
141
  * 続きの側には書き直されない。前の状態のまま読む前提で送られてくる
142
142
  *
143
143
  * ので、部分だけを単独でデコードすると、そこから先が崩れます。
144
+ *
145
+ * **ただし見出しのある項目は、同じ見出しでも別の項目として最初の状態から読む。** 見出しが同じ
146
+ * 項目が 2 つ続けて来る局があり (BS日テレの「番組内容」)、2 つ目は最初の状態 (漢字) から読む前提で
147
+ * 送られている。1 つ目が英数字に切り替えたまま (`0e 21 3f` = LS1 のあと「!?」) 終わっていると、
148
+ * バイトのまま繋いだ頃は 2 つ目の漢字が英数字で出ていた (実機の「いずれ「6'MpNa>n」と8Fばれる」。
149
+ * 正しくは「いずれ「凶乱令嬢」と呼ばれる」)。項目ごとにデコードして、文字で繋ぐ
144
150
  */
145
151
  function readDescriptors(event, body) {
146
- /** 見出しごとの生バイト。**全部揃ってからデコードする** (Map なので見出しの出てきた順に並ぶ) */
152
+ /**
153
+ * 見出しごとの項目。項目はバイト列の部分の並びで、**項目の部分が全部揃ってからデコードする**
154
+ * (Map なので見出しの出てきた順に並ぶ)
155
+ */
147
156
  const pending = new Map();
148
157
  let lastHeading = "";
149
158
  for (const [tag, data] of descriptors(body)) {
@@ -166,16 +175,19 @@ function readDescriptors(event, body) {
166
175
  const textLength = data[at];
167
176
  const text = data.subarray(at + 1, at + 1 + textLength);
168
177
  at += 1 + textLength;
169
- // 見出しが空なら前の項目の続き。改行を挟まずそのまま繋ぐ
170
- const key = heading === "" ? lastHeading : heading;
171
- if (key === "")
178
+ // 見出しが空なら前の項目の続き (バイトのまま繋ぐ)。見出しがあれば、同じ見出しでも新しい項目
179
+ if (heading === "") {
180
+ if (lastHeading === "")
181
+ continue;
182
+ pending.get(lastHeading).at(-1).push(text);
172
183
  continue;
173
- const parts = pending.get(key);
174
- if (parts === undefined)
175
- pending.set(key, [text]);
184
+ }
185
+ const items = pending.get(heading);
186
+ if (items === undefined)
187
+ pending.set(heading, [[text]]);
176
188
  else
177
- parts.push(text);
178
- lastHeading = key;
189
+ items.push([text]);
190
+ lastHeading = heading;
179
191
  }
180
192
  break;
181
193
  }
@@ -195,7 +207,7 @@ function readDescriptors(event, body) {
195
207
  break;
196
208
  }
197
209
  /*
198
- * audio_component_descriptor (ARIB STD-B10 第2部)。
210
+ * audio_component_descriptor (ARIB STD-B10 第 2 部)。
199
211
  *
200
212
  * [0] reserved(4) stream_content(4)
201
213
  * [1] component_type … ステレオ・デュアルモノ…
@@ -230,7 +242,7 @@ function readDescriptors(event, body) {
230
242
  break;
231
243
  }
232
244
  /*
233
- * series_descriptor (ARIB STD-B10 第2部)。
245
+ * series_descriptor (ARIB STD-B10 第 2 部)。
234
246
  *
235
247
  * [0..1] series_id
236
248
  * [2] repeat_label(4) program_pattern(3) expire_date_valid_flag(1)
@@ -257,12 +269,14 @@ function readDescriptors(event, body) {
257
269
  break;
258
270
  }
259
271
  }
260
- // 全部揃ってからデコードする (分割点が二バイト文字や文字集合の途中に来るため)
261
- for (const [heading, parts] of pending)
262
- event.extended[heading] = decodeAribText(joinBytes(parts));
272
+ // 項目ごとに、部分が全部揃ってからデコードする (分割点が二バイト文字や文字集合の途中に来るため)
273
+ for (const [heading, items] of pending)
274
+ event.extended[heading] = items
275
+ .map((parts) => decodeAribText(joinBytes(parts)))
276
+ .join("");
263
277
  }
264
278
  /**
265
- * EIT のセクションを1本読む。自局のもの以外は null。
279
+ * EIT のセクションを 1 本読む。自局のもの以外は null。
266
280
  *
267
281
  * 壊れたセクションは `SectionAssembler` が CRC で落としているので、ここに来るのは
268
282
  * 中身が揃っているものだけ。それでも長さの辻褄が合わないことはあるので、
@@ -335,13 +349,13 @@ export function parseEit(section, options = {}) {
335
349
  * 早く揃った局でも待たされ、遅い局は取りこぼす。EIT は自分がどこまであるかを
336
350
  * セクションの中で言っているので、それを数えれば足りる。
337
351
  *
338
- * セクションは**8本ずつのセグメント**に分かれていて、セグメントの中で実際に
352
+ * セクションは**8 本ずつのセグメント**に分かれていて、セグメントの中で実際に
339
353
  * 使われている最後の番号が `segment_last_section_number`。使われていない番号は
340
354
  * 永久に来ないので、そこまで揃えばそのセグメントは終わり。
341
355
  *
342
- * **過ぎた時間帯のセグメントは流れてこない** (`stale`)。空でも先頭の1本は必ず
356
+ * **過ぎた時間帯のセグメントは流れてこない** (`stale`)。空でも先頭の 1 本は必ず
343
357
  * 来るものとして待っていた頃は、**どのチャンネルも例外なく上限まで
344
- * 開きっぱなし**になっていた (実機14チャンネル、揃って離せたのは0本)。
358
+ * 開きっぱなし**になっていた (実機 14 チャンネル、揃って離せたのは 0 本)。
345
359
  */
346
360
  export class ScheduleProgress {
347
361
  now;
@@ -355,11 +369,11 @@ export class ScheduleProgress {
355
369
  /**
356
370
  * `table_id` → バージョン。変わったらその表だけ数え直す。
357
371
  *
358
- * **バージョンは `table_id` ごとに別々に振られる。** 番組表の1つの表 (sub_table) は
372
+ * **バージョンは `table_id` ごとに別々に振られる。** 番組表の 1 つの表 (sub_table) は
359
373
  * `table_id` + 局 + TS で決まり、`version_number` はその単位で動く。
360
- * 局に1つだけ持っていた頃は、**基本 (0x50〜) と詳細 (0x58〜) を行き来する
374
+ * 局に 1 つだけ持っていた頃は、**基本 (0x50〜) と詳細 (0x58〜) を行き来する
361
375
  * たびにバージョンが違って数えたものを全部捨てて**いた。揃ったと分かることが
362
- * 二度と無いので、どのチャンネルも上限の10分 (denpa の `epgChannelTimeout`) まで開きっぱなしになる。
376
+ * 二度と無いので、どのチャンネルも上限の 10 分 (denpa の `epgChannelTimeout`) まで開きっぱなしになる。
363
377
  */
364
378
  version = new Map();
365
379
  /**
@@ -370,7 +384,7 @@ export class ScheduleProgress {
370
384
  this.now = now;
371
385
  }
372
386
  add(section) {
373
- // p/f は番組表の完成度とは関係ない (いつでも2番組しか無い)
387
+ // p/f は番組表の完成度とは関係ない (いつでも 2 番組しか無い)
374
388
  if (section.tableId < SCHEDULE_ACTUAL_MIN)
375
389
  return;
376
390
  if (section.version !== this.version.get(section.tableId)) {
@@ -392,13 +406,13 @@ export class ScheduleProgress {
392
406
  /**
393
407
  * 使われている table_id を全部揃えられたか。
394
408
  *
395
- * **番号が飛ぶ。** 1つの `table_id` が受け持つのは4日ぶんで、基本は
396
- * `0x50` から、詳細は `0x58` から始まる。日本の放送は8日ぶんなので、
409
+ * **番号が飛ぶ。** 1 つの `table_id` が受け持つのは 4 日ぶんで、基本は
410
+ * `0x50` から、詳細は `0x58` から始まる。日本の放送は 8 日ぶんなので、
397
411
  * 実際に流れてくるのは `0x50` `0x51` と `0x58` `0x59` あたりだけで、
398
412
  * **`0x52`〜`0x57` は永久に来ません**。
399
413
  *
400
414
  * `0x50` から `last_table_id` まで全部を待っていた頃は、詳細を積んでいる局が
401
- * **一度も「揃った」にならず**、どのチャンネルも上限の10分 (denpa の `epgChannelTimeout`) まで開きっぱなしに
415
+ * **一度も「揃った」にならず**、どのチャンネルも上限の 10 分 (denpa の `epgChannelTimeout`) まで開きっぱなしに
402
416
  * なっていました (実機で、詳細の無い BS11 だけが早く閉じていた)。
403
417
  *
404
418
  * 見かけた表と、`last_table_id` が指す表だけを見ます。
@@ -438,9 +452,9 @@ export class ScheduleProgress {
438
452
  /**
439
453
  * そのセグメントの時間帯がもう過ぎているか。**過ぎたものは待たない。**
440
454
  *
441
- * セグメントは 0:00 から3時間ずつの枠で、`table_id` と節番号から
442
- * それがいつの枠なのかが決まる — 基本は `0x50` が当日 0:00 から4日ぶん、
443
- * `0x51` がその次の4日ぶん。詳細 (`0x58`〜) も同じ並びをもう一度たどる。
455
+ * セグメントは 0:00 から 3 時間ずつの枠で、`table_id` と節番号から
456
+ * それがいつの枠なのかが決まる。基本は `0x50` が当日 0:00 から 4 日ぶん、
457
+ * `0x51` がその次の 4 日ぶん。詳細 (`0x58`〜) も同じ並びをもう一度たどる。
444
458
  * 終わった枠は放送に乗らない (クラスの説明)。そのぶんの番組は、そこが未来だった数日前に取り込んである。
445
459
  */
446
460
  stale(tableId, start) {
@@ -457,7 +471,7 @@ export class ScheduleProgress {
457
471
  * 何が足りないか。**上限まで開いても揃わなかったときに出す。**
458
472
  *
459
473
  * 揃ったかどうかしか分からなかった頃は、上限まで開きっぱなしになっている局を
460
- * 見つけても**その先を追えなかった** — 電波が弱くて欠けているのか、
474
+ * 見つけても**その先を追えなかった。** 電波が弱くて欠けているのか、
461
475
  * こちらが来ない表を待っているのかで、直し方がまるで違う。
462
476
  */
463
477
  report() {
@@ -482,7 +496,7 @@ export class ScheduleProgress {
482
496
  }
483
497
  const hex = (value) => `0x${value.toString(16)}`;
484
498
  /**
485
- * 流れてくる TS を食べて番組を溜める。
499
+ * 流れてくる TS を読んで番組を溜める。
486
500
  *
487
501
  * 局ごとに `ScheduleProgress` を持ち、**その物理チャンネルに入っている局が
488
502
  * 全部揃ったら**読むのをやめられる。同じ番組が何度も来る (カルーセルなので) ので、
@@ -505,7 +519,7 @@ export class EpgReader {
505
519
  /**
506
520
  * @param now いまの時刻。局ごとの `ScheduleProgress` にそのまま渡す
507
521
  * @param options.other ほかの TS の局の番組表も読む。ネットワーク全局ぶんを
508
- * 1つの中継から先に入れるときに使う (denpa の `epg-collect.ts` の初回)
522
+ * 1 つの中継から先に入れるときに使う (denpa の `epg-collect.ts` の初回)
509
523
  * @param options.settle `other` のとき、新しい局が出てこなくなってから閉じるまで (ms)
510
524
  * @param options.expect `other` のとき、来るはずの局 (service_id)。全部見えて揃えば
511
525
  * `settle` を待たずに閉じる。受信できない局が混ざっていれば `settle` で閉じる
@@ -514,7 +528,7 @@ export class EpgReader {
514
528
  this.now = now;
515
529
  this.options = options;
516
530
  }
517
- /** 任意の長さのバイト列を食わせる。番組が1つでも増えたら true */
531
+ /** 任意の長さのバイト列を渡す。番組が 1 つでも増えたら true */
518
532
  feed(chunk) {
519
533
  let added = false;
520
534
  for (const packet of this.packets.feed(chunk)) {
@@ -547,7 +561,7 @@ export class EpgReader {
547
561
  /**
548
562
  * 溜めてあるものと混ぜる。**別の表で来るものを消し合わせない。**
549
563
  *
550
- * 番組表は2つの表に分かれて流れてくる。同じ event_id が両方に載っていて、
564
+ * 番組表は 2 つの表に分かれて流れてくる。同じ event_id が両方に載っていて、
551
565
  * **それぞれ自分のぶんの記述子しか持っていない**。
552
566
  *
553
567
  * - **基本** (table_id 0x50〜0x57) … タイトルと短い説明 (short_event_descriptor)
@@ -555,7 +569,7 @@ export class EpgReader {
555
569
  *
556
570
  * あとから来たもので丸ごと置き換えていた頃は、**詳細のほうが後に届いた番組の
557
571
  * タイトルが空になっていた**。実機では番組 23,000 件のうち 11,000 件が名無しで、
558
- * うち 2,700 件は「タイトルは無いのに番組内容だけある」状態 — 詳細に上書きされた
572
+ * うち 2,700 件は「タイトルは無いのに番組内容だけある」状態で、詳細に上書きされた
559
573
  * 跡そのもの。番組表には「(番組情報なし)」の列が並んでいた。
560
574
  *
561
575
  * **中身のあるほうを残す。** 書き換え (「[新]」が付く、誤字が直る) は
@@ -589,7 +603,7 @@ export class EpgReader {
589
603
  * p/f で「いま流れている」と言えるか。
590
604
  *
591
605
  * **`running_status` を当てにしきれない。** 4 (放送中) を入れてくる局も
592
- * あれば、**0 (未定義) しか入れてこない局もある** — 実機の NHK は 74 節
606
+ * あれば、**0 (未定義) しか入れてこない局もある。** 実機の NHK は 74 節
593
607
  * ぜんぶ 0 だった。4 だけを見ていると、そういう局では延長追従が丸ごと
594
608
  * 効かなくなる (denpa の docs/data.md)。
595
609
  *
@@ -621,14 +635,14 @@ export class EpgReader {
621
635
  all() {
622
636
  return [...this.events.values()].sort((a, b) => (a.startAt ?? 0) - (b.startAt ?? 0));
623
637
  }
624
- /** 番組表を1つでも見かけた局 */
638
+ /** 番組表を 1 つでも見かけた局 */
625
639
  services() {
626
640
  return [...this.progress.keys()];
627
641
  }
628
642
  /**
629
643
  * 見かけた局が**全部**揃ったか。
630
644
  *
631
- * 「1局でも揃えば閉じる」にはしない。1つの物理チャンネルには複数の局が
645
+ * 「1 局でも揃えば閉じる」にはしない。1 つの物理チャンネルには複数の局が
632
646
  * 入っていて (地上波なら MX1 と MX2)、先に揃ったほうで閉じると残りが
633
647
  * 永久に埋まらない。
634
648
  */
@@ -638,7 +652,7 @@ export class EpgReader {
638
652
  /*
639
653
  * ほかの TS の局まで読むときは、**来るはずの局が全部見えるか、しばらく新しい局が
640
654
  * 出てこないことも待つ。** 局ごとに流れてくる順はばらばらで、見かけた局が
641
- * 揃っただけではまだ1度も来ていない局を置いていく。来るはずの局を知っていれば
655
+ * 揃っただけではまだ 1 度も来ていない局を置いていく。来るはずの局を知っていれば
642
656
  * すぐ閉じられる (WebTS.app・Mirakurun と同じ)
643
657
  */
644
658
  if (this.options.other === true &&
@@ -652,7 +666,7 @@ export class EpgReader {
652
666
  }
653
667
  return true;
654
668
  }
655
- /** 来るはずの局を教わっていて、それが全部見えたか */
669
+ /** 来るはずの局 (`expect`) が渡されていて、それが全部見えたか */
656
670
  sawExpected() {
657
671
  const expect = this.options.expect ?? [];
658
672
  return (expect.length > 0 &&
@@ -661,7 +675,7 @@ export class EpgReader {
661
675
  /**
662
676
  * 揃っていない局と、その理由。**上限まで開いてしまったときに出す。**
663
677
  *
664
- * 1局でも揃わなければチャンネルごと上限まで開き続けるので、
678
+ * 1 局でも揃わなければチャンネルごと上限まで開き続けるので、
665
679
  * 「どの局のせいか」が分からないと直しようがない。
666
680
  */
667
681
  shortfall() {
@@ -674,7 +688,7 @@ export class EpgReader {
674
688
  }
675
689
  }
676
690
  /**
677
- * **1局の「いま」と「次」(EIT[p/f]) を追う。** ライブで番組の切り替わりを知るのに使う。
691
+ * **1 局の「いま」と「次」(EIT[p/f]) を追う。** ライブで番組の切り替わりを知るのに使う。
678
692
  *
679
693
  * 番組表 (schedule) は数日先までの予定で、**延長や繰り下げには追いつかない**
680
694
  * (局が送り直してくるのは後になってから)。p/f は放送そのものに追従していて、
@@ -683,7 +697,7 @@ export class EpgReader {
683
697
  * section 0 が「いま」、section 1 が「次」と決まっている (`EpgReader.onAir` と同じ)。
684
698
  *
685
699
  * **中身で比べる。** 書き換われば version が上がるはずだが、上げずに中身だけ替える
686
- * 送り手を当てにしないよう、番組の番号・時刻・尺・タイトルで比べる。p/f は1局ぶん数百バイトが
700
+ * 送り手を当てにしないよう、番組の番号・時刻・尺・タイトルで比べる。p/f は 1 局ぶん数百バイトが
687
701
  * 数秒おきに来るだけなので、毎回読んでも軽い
688
702
  */
689
703
  export class PresentFollowing {
@@ -706,7 +720,7 @@ export class PresentFollowing {
706
720
  return this.held[1];
707
721
  }
708
722
  /**
709
- * 188 バイトのパケットを1つ。**いまか次のどちらかが変わったら true**。
723
+ * 188 バイトのパケットを 1 つ。**いまか次のどちらかが変わったら true**。
710
724
  * 最初に読めたときも true (知らなかったものが分かった)
711
725
  */
712
726
  feedPacket(packet) {
@@ -732,7 +746,7 @@ export class PresentFollowing {
732
746
  return changed;
733
747
  }
734
748
  }
735
- /** 変わったかどうかを見る中身。**番号・時刻・尺・タイトルだけ** — 番組表に写して画面に出るもの */
749
+ /** 変わったかどうかを見る中身。**番号・時刻・尺・タイトルだけ** (番組表に写して画面に出るもの) */
736
750
  function markOf(event) {
737
751
  return `${event.eventId}:${event.startAt}:${event.duration}:${event.name}`;
738
752
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * ISO 639-2 のうち日本の放送で出てくるもの。
3
3
  *
4
- * **音声も字幕も同じ表を使う** — 字幕と音声で別に持っていた頃は
5
- * 4つ足りず、同じ放送の音声が「イタリア語」、字幕が「ita」と出る形になっていた
4
+ * **音声も字幕も同じ表を使う。** 字幕と音声で別に持っていた頃は
5
+ * 4 つ足りず、同じ放送の音声が「イタリア語」、字幕が「ita」と出る形になっていた
6
6
  */
7
7
  export declare const LANGUAGE: Record<string, string>;
package/dist/language.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * ISO 639-2 のうち日本の放送で出てくるもの。
3
3
  *
4
- * **音声も字幕も同じ表を使う** — 字幕と音声で別に持っていた頃は
5
- * 4つ足りず、同じ放送の音声が「イタリア語」、字幕が「ita」と出る形になっていた
4
+ * **音声も字幕も同じ表を使う。** 字幕と音声で別に持っていた頃は
5
+ * 4 つ足りず、同じ放送の音声が「イタリア語」、字幕が「ita」と出る形になっていた
6
6
  */
7
7
  export const LANGUAGE = {
8
8
  jpn: "日本語",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * モジュールの中身を読む。**ヘッダ + 空行 + 本体** の形式 (STD-B24 第二編 第9章) で、
2
+ * モジュールの中身を読む。**ヘッダ + 空行 + 本体** の形式 (STD-B24 第二編 第 9 章) で、
3
3
  * 多くは `multipart/mixed` に BML と画像がまとめて入っている。
4
4
  *
5
5
  * Content-Type: multipart/mixed; boundary=XXX
@@ -21,7 +21,7 @@ export interface EntityHeader {
21
21
  name: string;
22
22
  value: string;
23
23
  }
24
- /** 読んだ中身。`multipart/mixed` なら `parts` に1つずつ入る */
24
+ /** 読んだ中身。`multipart/mixed` なら `parts` に 1 つずつ入る */
25
25
  export interface Entity {
26
26
  headers: EntityHeader[];
27
27
  body: Uint8Array;
@@ -30,12 +30,12 @@ export interface Entity {
30
30
  /**
31
31
  * `type/subtype; a=b; c="d"` を読む。名前は小文字にそろえ、元の綴りも残す。
32
32
  *
33
- * **引数の途中で崩れていても、読めたところまでは返す** — 型と下位型が分かれば
33
+ * **引数の途中で崩れていても、読めたところまでは返す。** 型と下位型が分かれば
34
34
  * 読み方は決まる。型すら読めなければ null
35
35
  */
36
36
  export declare function parseMediaType(text: string): MediaType | null;
37
37
  /**
38
- * 中身を1つ読む。**ヘッダの終わり (空行) が無いものは null** — どこからが本体か
38
+ * 中身を 1 つ読む。**ヘッダの終わり (空行) が無いものは null。** どこからが本体か
39
39
  * 分からない。`multipart/mixed` なら中までデコードする (入れ子も同じ形式)。
40
40
  *
41
41
  * @param part multipart の中の部品か。部品はヘッダの行でちょうど終わってよい (下の説明)
package/dist/multipart.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * モジュールの中身を読む。**ヘッダ + 空行 + 本体** の形式 (STD-B24 第二編 第9章) で、
2
+ * モジュールの中身を読む。**ヘッダ + 空行 + 本体** の形式 (STD-B24 第二編 第 9 章) で、
3
3
  * 多くは `multipart/mixed` に BML と画像がまとめて入っている。
4
4
  *
5
5
  * Content-Type: multipart/mixed; boundary=XXX
@@ -29,7 +29,7 @@ function isTokenChar(char) {
29
29
  /**
30
30
  * `type/subtype; a=b; c="d"` を読む。名前は小文字にそろえ、元の綴りも残す。
31
31
  *
32
- * **引数の途中で崩れていても、読めたところまでは返す** — 型と下位型が分かれば
32
+ * **引数の途中で崩れていても、読めたところまでは返す。** 型と下位型が分かれば
33
33
  * 読み方は決まる。型すら読めなければ null
34
34
  */
35
35
  export function parseMediaType(text) {
@@ -112,7 +112,7 @@ function find(haystack, needle, from) {
112
112
  return -1;
113
113
  }
114
114
  /**
115
- * 中身を1つ読む。**ヘッダの終わり (空行) が無いものは null** — どこからが本体か
115
+ * 中身を 1 つ読む。**ヘッダの終わり (空行) が無いものは null。** どこからが本体か
116
116
  * 分からない。`multipart/mixed` なら中までデコードする (入れ子も同じ形式)。
117
117
  *
118
118
  * @param part multipart の中の部品か。部品はヘッダの行でちょうど終わってよい (下の説明)
@@ -160,8 +160,8 @@ export function readEntity(data, part = false) {
160
160
  return { headers, body, parts };
161
161
  }
162
162
  /**
163
- * 区切りで切る。**閉じの区切り (`--XXX--`) まで揃っていないものは捨てる** —
164
- * 最後の1つがどこで終わるか分からない
163
+ * 区切りで切る。**閉じの区切り (`--XXX--`) まで揃っていないものは捨てる。**
164
+ * 最後の 1 つがどこで終わるか分からない
165
165
  */
166
166
  function splitParts(body, boundary) {
167
167
  const open = encoder.encode(`--${boundary}\r\n`);
@@ -176,7 +176,7 @@ function splitParts(body, boundary) {
176
176
  if (end === -1)
177
177
  return null;
178
178
  const after = end + next.length;
179
- // `--` が続けば閉じ、CRLF なら次の1つ。どちらでもなければ本体の中の似た並び
179
+ // `--` が続けば閉じ、CRLF なら次の 1 つ。どちらでもなければ本体の中の似た並び
180
180
  const close = body[after] === 0x2d && body[after + 1] === 0x2d;
181
181
  if (!close && (body[after] !== CR || body[after + 1] !== LF)) {
182
182
  from = end + 1;
package/dist/pes.d.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  /**
2
- * **1局に絞った TS から、映像と音声の PES を取り出す** (denpa のライブを変換せずに送る経路。docs/stream.md#放送そのままmpeg-2を送る)。
2
+ * **1 局に絞った TS から、映像と音声の PES を取り出す** (denpa のライブを変換せずに送る経路。docs/stream.md#放送そのまま mpeg-2 を送る)。
3
3
  *
4
4
  * エンコードする経路ではここを ffmpeg がやっていた。変換せずに送ると TS がそのままブラウザへ来るので、
5
5
  * 映像も音声も WASM のデコーダ (denpa の `wasm/decoder.c`) に渡す前に、
6
- * こちらで PES に戻す。サーバが1局に絞ってある (`ServiceFilter`) ので、PAT に
7
- * 載っている局は1つだけ — その PMT を読んで、映像1本と音声 (並んだ順) を取り出す。
6
+ * こちらで PES に戻す。サーバが 1 局に絞ってある (`ServiceFilter`) ので、PAT に
7
+ * 載っている局は 1 つだけなので、その PMT を読んで、映像 1 本と音声 (並んだ順) を取り出す。
8
8
  *
9
9
  * DOM も WASM も触らないので、ここだけ単体で確かめられる (`pes.test.ts`)。
10
10
  */
11
11
  /** PTS・PCR の刻み (90kHz)。denpa の取り決めの時刻もこの刻み (docs/stream.md#websocket-プロトコル) */
12
12
  export declare const CLOCK = 90000;
13
- /** PTS の一周 (33ビット)。26.5 時間 */
13
+ /** PTS の一周 (33 ビット)。26.5 時間 */
14
14
  export declare const WRAP: number;
15
15
  export interface Pes {
16
16
  pid: number;
@@ -22,12 +22,12 @@ export interface Pes {
22
22
  /** PES の中身 (ES) */
23
23
  data: Uint8Array;
24
24
  }
25
- /** PMT から分かったこと。**音声は並んだ順** — 画面の「何本目の音声」(`AudioTrack.stream`) と揃う */
25
+ /** PMT から分かったこと。**音声は並んだ順** (画面の「何本目の音声」`AudioTrack.stream` と揃う) */
26
26
  export interface Streams {
27
27
  video: number | null;
28
28
  audio: number[];
29
29
  }
30
- /** 5バイトの PTS / DTS を読む (ISO/IEC 13818-1 2.4.3.7) */
30
+ /** 5 バイトの PTS / DTS を読む (ISO/IEC 13818-1 2.4.3.7) */
31
31
  export declare function readStamp(data: Uint8Array, at: number): number;
32
32
  /** PES の頭を読んで中身を切り出す。**壊れていれば null** (頭の 00 00 01 が無いなど) */
33
33
  export declare function parsePes(data: Uint8Array): {
@@ -36,19 +36,19 @@ export declare function parsePes(data: Uint8Array): {
36
36
  data: Uint8Array;
37
37
  } | null;
38
38
  /**
39
- * TS を食わせて PES を吐く。**選局し直したら作り直す** (前の局の切れ端を持ち越さない)。
39
+ * TS を渡すと PES を返す。**選局し直したら作り直す** (前の局の切れ端を持ち越さない)。
40
40
  *
41
- * 映像は長さ 0 (次の頭で終わりが分かる) なので1枚ぶん遅れて出るが、貯めの中に収まる。
41
+ * 映像は長さ 0 (次の頭で終わりが分かる) なので 1 枚ぶん遅れて出るが、貯めの中に収まる。
42
42
  * 音声は長さが書いてあるので揃った時点で出す
43
43
  */
44
44
  export declare class PesDemuxer {
45
45
  private readonly packets;
46
- /** 絞ってあるので局は1つだけのはず。万一複数あっても先頭を採る */
46
+ /** 絞ってあるので局は 1 つだけのはず。万一複数あっても先頭を採る */
47
47
  private readonly pmt;
48
48
  private readonly partial;
49
49
  /** いま分かっている ES。**変わったら `feed` の返りで知らせる** */
50
50
  streams: Streams;
51
- /** デコードする音声の PID。**選ばれた1本だけ**組み立てる (他は捨てる) */
51
+ /** デコードする音声の PID。**選ばれた 1 本だけ**組み立てる (他は捨てる) */
52
52
  audioPid: number | null;
53
53
  /** 何本目の音声を取り出すか (`AudioTrack.stream`)。無ければ先頭に落とす */
54
54
  audioIndex: number;
@@ -71,13 +71,13 @@ export interface AdtsFrame {
71
71
  pts: number;
72
72
  sampleRate: number;
73
73
  channels: number;
74
- /** このコマの長さ (90kHz)。AAC は1コマ 1024 標本 */
74
+ /** このコマの長さ (90kHz)。AAC は 1 コマ 1024 標本 */
75
75
  duration: number;
76
76
  }
77
77
  /**
78
78
  * PES の中身を ADTS のコマに割る。**コマは PES をまたぐことがある**ので、余りは持ち越す。
79
79
  *
80
- * 時刻は PES の PTS を頭のコマに付け、続くコマには1コマぶんずつ足す。持ち越した
80
+ * 時刻は PES の PTS を頭のコマに付け、続くコマには 1 コマぶんずつ足す。持ち越した
81
81
  * 余りから始まるコマは、前の続きの時刻になる
82
82
  */
83
83
  export declare class AdtsSplitter {
@@ -87,7 +87,7 @@ export declare class AdtsSplitter {
87
87
  reset(): void;
88
88
  }
89
89
  /**
90
- * **33ビットで一周する時刻を、手元の物差しの近くへ伸ばす。**
90
+ * **33 ビットで一周する時刻を、手元の物差しの近くへ伸ばす。**
91
91
  *
92
92
  * PTS は 26.5 時間で 0 に戻る。受け側は「いま鳴らしている時刻」を一周をまたいでも
93
93
  * 増え続ける数で持つので、届いた時刻は**それにいちばん近い周**に置き直して比べる
package/dist/pes.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * **1局に絞った TS から、映像と音声の PES を取り出す** (denpa のライブを変換せずに送る経路。docs/stream.md#放送そのままmpeg-2を送る)。
2
+ * **1 局に絞った TS から、映像と音声の PES を取り出す** (denpa のライブを変換せずに送る経路。docs/stream.md#放送そのまま mpeg-2 を送る)。
3
3
  *
4
4
  * エンコードする経路ではここを ffmpeg がやっていた。変換せずに送ると TS がそのままブラウザへ来るので、
5
5
  * 映像も音声も WASM のデコーダ (denpa の `wasm/decoder.c`) に渡す前に、
6
- * こちらで PES に戻す。サーバが1局に絞ってある (`ServiceFilter`) ので、PAT に
7
- * 載っている局は1つだけ — その PMT を読んで、映像1本と音声 (並んだ順) を取り出す。
6
+ * こちらで PES に戻す。サーバが 1 局に絞ってある (`ServiceFilter`) ので、PAT に
7
+ * 載っている局は 1 つだけなので、その PMT を読んで、映像 1 本と音声 (並んだ順) を取り出す。
8
8
  *
9
9
  * DOM も WASM も触らないので、ここだけ単体で確かめられる (`pes.test.ts`)。
10
10
  */
@@ -12,12 +12,12 @@ import { concatBytes, u16 } from "./bytes.js";
12
12
  import { PACKET, packetPid, PacketStream, PID_PAT, pmtStreams, PmtTracker, } from "./psi.js";
13
13
  /** PTS・PCR の刻み (90kHz)。denpa の取り決めの時刻もこの刻み (docs/stream.md#websocket-プロトコル) */
14
14
  export const CLOCK = 90_000;
15
- /** PTS の一周 (33ビット)。26.5 時間 */
15
+ /** PTS の一周 (33 ビット)。26.5 時間 */
16
16
  export const WRAP = 2 ** 33;
17
17
  /** PMT の stream_type。**放送の映像は MPEG-2、音声は ADTS の AAC** (ARIB STD-B32) */
18
18
  const STREAM_MPEG2 = 0x02;
19
19
  const STREAM_AAC = 0x0f;
20
- /** 5バイトの PTS / DTS を読む (ISO/IEC 13818-1 2.4.3.7) */
20
+ /** 5 バイトの PTS / DTS を読む (ISO/IEC 13818-1 2.4.3.7) */
21
21
  export function readStamp(data, at) {
22
22
  return (((data[at] >> 1) & 0x07) * 2 ** 30 +
23
23
  (data[at + 1] << 22) +
@@ -44,19 +44,19 @@ export function parsePes(data) {
44
44
  /** 長さの分からない PES (映像) の入れ物の最初の大きさ。1 コマの多くはこれに収まる */
45
45
  const PES_START = 64 * 1024;
46
46
  /**
47
- * TS を食わせて PES を吐く。**選局し直したら作り直す** (前の局の切れ端を持ち越さない)。
47
+ * TS を渡すと PES を返す。**選局し直したら作り直す** (前の局の切れ端を持ち越さない)。
48
48
  *
49
- * 映像は長さ 0 (次の頭で終わりが分かる) なので1枚ぶん遅れて出るが、貯めの中に収まる。
49
+ * 映像は長さ 0 (次の頭で終わりが分かる) なので 1 枚ぶん遅れて出るが、貯めの中に収まる。
50
50
  * 音声は長さが書いてあるので揃った時点で出す
51
51
  */
52
52
  export class PesDemuxer {
53
53
  packets = new PacketStream();
54
- /** 絞ってあるので局は1つだけのはず。万一複数あっても先頭を採る */
54
+ /** 絞ってあるので局は 1 つだけのはず。万一複数あっても先頭を採る */
55
55
  pmt = new PmtTracker();
56
56
  partial = new Map();
57
57
  /** いま分かっている ES。**変わったら `feed` の返りで知らせる** */
58
58
  streams = { video: null, audio: [] };
59
- /** デコードする音声の PID。**選ばれた1本だけ**組み立てる (他は捨てる) */
59
+ /** デコードする音声の PID。**選ばれた 1 本だけ**組み立てる (他は捨てる) */
60
60
  audioPid = null;
61
61
  /** 何本目の音声を取り出すか (`AudioTrack.stream`)。無ければ先頭に落とす */
62
62
  audioIndex = 0;
@@ -173,7 +173,7 @@ export const ADTS_RATES = [
173
173
  /**
174
174
  * PES の中身を ADTS のコマに割る。**コマは PES をまたぐことがある**ので、余りは持ち越す。
175
175
  *
176
- * 時刻は PES の PTS を頭のコマに付け、続くコマには1コマぶんずつ足す。持ち越した
176
+ * 時刻は PES の PTS を頭のコマに付け、続くコマには 1 コマぶんずつ足す。持ち越した
177
177
  * 余りから始まるコマは、前の続きの時刻になる
178
178
  */
179
179
  export class AdtsSplitter {
@@ -208,7 +208,7 @@ export class AdtsSplitter {
208
208
  data: buffer.slice(at, at + length),
209
209
  pts: this.next,
210
210
  sampleRate: rate,
211
- // 0 は「中身に書いてある」(PCE)。放送のデュアルモノはここに来るので、2本とみなす
211
+ // 0 は「中身に書いてある」(PCE)。放送のデュアルモノはここに来るので、2 本とみなす
212
212
  channels: channels === 0 ? 2 : channels,
213
213
  duration,
214
214
  });
@@ -230,7 +230,7 @@ export class AdtsSplitter {
230
230
  }
231
231
  }
232
232
  /**
233
- * **33ビットで一周する時刻を、手元の物差しの近くへ伸ばす。**
233
+ * **33 ビットで一周する時刻を、手元の物差しの近くへ伸ばす。**
234
234
  *
235
235
  * PTS は 26.5 時間で 0 に戻る。受け側は「いま鳴らしている時刻」を一周をまたいでも
236
236
  * 増え続ける数で持つので、届いた時刻は**それにいちばん近い周**に置き直して比べる