@torrent-tv/proxy 2.99.18 → 2.99.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.99.18",
3
+ "version": "2.99.20",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
package/server.js CHANGED
@@ -15,6 +15,7 @@ import { handleHealthGet } from "./routes/health/get.js";
15
15
  import { handleMediaGet } from "./routes/media/get.js";
16
16
  import { ProbeRequests } from "./services/media/ProbeRequests.js";
17
17
  import { IndexMemory } from "./services/storage/IndexMemory.js";
18
+ import { LARGEST_GROWTH_BYTES } from "./services/media/container/PacketRecords.js";
18
19
  import { probePackets } from "./services/media/probe-packets.js";
19
20
  import { trackChoicesOf } from "./services/viewer/segment-demands.js";
20
21
  import { PlaybackProjection } from "./services/torrent/PlaybackProjection.js";
@@ -770,6 +771,7 @@ export async function startProxyServer({
770
771
  failed: (request, error) => logger.warn(`media request=${request.key} probe failed: ${error?.message ?? error}`)
771
772
  });
772
773
  const indexMemory = new IndexMemory({
774
+ growthBytes: LARGEST_GROWTH_BYTES,
773
775
  reviseBudget: () => { void outputParts.machineBudget.revise("memory", "media metadata").catch(error => logger.warn(`packet index budget: ${error.message}`)); },
774
776
  changed: () => { mediaReads.memoryChanged(); probeReads.memoryChanged(); outputParts.encodeInputs?.memoryChanged(); }
775
777
  });
@@ -680,6 +680,26 @@ export class MatroskaContainer extends Container {
680
680
  return cues.points.some(point => point.positions.some(position => !video || position.track === video.trackNumber));
681
681
  }
682
682
 
683
+ /**
684
+ * Whether `statement` is answered from what this container has already
685
+ * read, so it may be answered beside a read of the same file in progress
686
+ * (`ContainerOrchestrator.inspect`), as an AVI's are. The picture's
687
+ * ranges are arithmetic over the Cues once they are read; asked behind a
688
+ * soundtrack's packet walk in the file's one queue, the picture's next
689
+ * input after a seek was ready only after the sound's, one piece every
690
+ * 7-8 s, where the two had been prepared side by side every 2 s (r57 against
691
+ * r50, torrent-tv/meta#178).
692
+ *
693
+ * @param {string} statement
694
+ * @returns {boolean}
695
+ */
696
+ answersWithoutReading(statement) {
697
+ if (statement === "media-info") return this.mediaInfo?.durationSeconds != null;
698
+ if (statement === "source-navigation") return this.#cues !== undefined && this.#tracks !== null;
699
+ if (statement === "source-ranges") return this.#sourceSeekPoints !== null;
700
+ return false;
701
+ }
702
+
683
703
  async readMappedSourceRanges(interval) { return this.readSourceRanges(interval); }
684
704
 
685
705
  /**
@@ -9,6 +9,8 @@ const BLOCK_BYTES = 65536;
9
9
  // Matroska soundtrack read in stretches: 144 tables of one 25-minute film held
10
10
  // 18.9 MB for 3.7 MB of records (r47 reproduced, torrent-tv/meta#178).
11
11
  const FIRST_BLOCK_BYTES = 4096;
12
+ /** The most one record can make a table take at once: a block of records and one of addresses. */
13
+ export const LARGEST_GROWTH_BYTES = 2 * BLOCK_BYTES;
12
14
  const ADDRESS_BYTES = 8;
13
15
  const HEADER_BYTES = 56;
14
16
 
@@ -7,18 +7,35 @@ export class IndexMemory {
7
7
  #revise;
8
8
  #changed;
9
9
  #revisionQueued = false;
10
+ #growthBytes;
10
11
 
11
- constructor({ reviseBudget, changed }) {
12
+ /**
13
+ * @param {object} params
14
+ * @param {() => void} params.reviseBudget
15
+ * @param {() => void} params.changed
16
+ * @param {number} [params.growthBytes] - What one growth of a table can
17
+ * take at most, kept free beyond what is held while anything is held. A
18
+ * table grows a block at a time, each twice the last; allowed exactly what
19
+ * it held, each growth was refused first and its whole read tried again:
20
+ * a soundtrack piece after a seek was refused three times and ready after
21
+ * 53.7 s (r58, torrent-tv/meta#178).
22
+ */
23
+ constructor({ reviseBudget, changed, growthBytes = 0 }) {
12
24
  this.#revise = reviseBudget;
13
25
  this.#changed = changed;
26
+ this.#growthBytes = growthBytes;
14
27
  }
15
28
 
16
29
  held() { return this.#held; }
17
30
  packetBytes() { return this.#packetBytes; }
18
31
  wanted() {
32
+ const short = [...this.#files.values()].reduce((sum, file) => sum + Math.max(0, file.needed - file.held), 0);
33
+ return this.#held + Math.max(short, this.#held > 0 ? this.#growthBytes : 0);
34
+ }
35
+ /** What is held and asked for, without the margin kept for growth. */
36
+ required() {
19
37
  return this.#held + [...this.#files.values()].reduce((sum, file) => sum + Math.max(0, file.needed - file.held), 0);
20
38
  }
21
- required() { return this.wanted(); }
22
39
 
23
40
  allow(bytes) {
24
41
  const allowed = Math.max(0, bytes);