@torrent-tv/proxy 2.100.15 → 2.101.0

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/bin/cli.js CHANGED
@@ -90,6 +90,7 @@ program
90
90
  .option("--no-port-mapping", "Disable automatic UPnP/NAT-PMP port mapping")
91
91
  .option("--delivery-sink", "Serve /api/delivery-sink, a torrent-free byte stream for delivery testing")
92
92
  .option("--pin-preset <name>", "Encode every software picture at this libx264 preset only, for runs that must be compared at one quality (off by default)")
93
+ .option("--input-stretch-bytes <bytes>", "Size every original-input stretch to this many bytes instead of copy rate times open, for runs that compare input sizes; memory, downloaded bytes and the plan still bound it (off by default)")
93
94
  .option("--heap-snapshots", "Write a heap snapshot of a thread whose memory reaches a new high-water; each one stops that thread while it is written (off by default)")
94
95
  .option("--profile-start <seconds>", "Profile the CPU of the main thread and the torrent thread for this many seconds from the first source opened, written beside the state (off by default)")
95
96
  .option(
@@ -399,6 +400,7 @@ try {
399
400
  profileStartSeconds: Number(options.profileStart) || 0,
400
401
  heapSnapshots: options.heapSnapshots === true,
401
402
  pinnedPreset: typeof options.pinPreset === "string" && options.pinPreset.trim() ? options.pinPreset.trim() : null,
403
+ inputStretchBytes: Number(options.inputStretchBytes) > 0 ? Math.floor(Number(options.inputStretchBytes)) : null,
402
404
  // Late-bound the same way `webRtcManager` is below: the torrent pool is
403
405
  // built inside `startProxyServer`, before `dataChannelHandler` — the
404
406
  // thing that actually owns a channel to push down — exists.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.100.15",
3
+ "version": "2.101.0",
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
@@ -134,6 +134,9 @@ export async function startProxyServer({
134
134
  // The one software preset every picture is encoded at, for runs compared at
135
135
  // one quality; null leaves the choice to the machine.
136
136
  pinnedPreset = null,
137
+ // The size every original-input stretch is given in place of copy rate
138
+ // times open, for runs that compare input sizes; null keeps the rule.
139
+ inputStretchBytes = null,
137
140
  // What viewers' connections carry beyond the film, per byte of film; the
138
141
  // transport counts it and is built after this server, so it is late-bound.
139
142
  serviceShare = () => null,
@@ -854,6 +857,7 @@ export async function startProxyServer({
854
857
  let sourcePreparation;
855
858
  const outputParts = wireOutputs({
856
859
  pinnedPreset,
860
+ inputStretchBytes,
857
861
  indexMemory,
858
862
  serviceShare,
859
863
  readMetadataActivity: () => containerOrchestrator.activity(),
@@ -62,10 +62,20 @@ export class EncodeInputs {
62
62
  * @type {(output: object, from: number, to: number, input: object) => void}
63
63
  */
64
64
  #stretchCopied;
65
+ /**
66
+ * A stretch size the operator named for comparison runs
67
+ * (`--input-stretch-bytes`), in place of copy rate times open; null keeps
68
+ * the measured rule. Only the target changes: memory, downloaded bytes and
69
+ * the plan's bound still end a stretch (torrent-tv/meta#182).
70
+ *
71
+ * @type {number | null}
72
+ */
73
+ #fixedStretchBytes;
65
74
 
66
75
  constructor({ resolve, readRanges, heldRanges = null, reviseBudget, changed, failed, capacity = () => null, urgent = () => true,
67
- rankAt = () => null, openOf = () => null, log = () => {}, now = Date.now, stretchCopied = () => {} }) {
76
+ rankAt = () => null, openOf = () => null, log = () => {}, now = Date.now, stretchCopied = () => {}, stretchBytes = null }) {
68
77
  this.#stretchCopied = stretchCopied;
78
+ this.#fixedStretchBytes = Number.isSafeInteger(stretchBytes) && stretchBytes > 0 ? stretchBytes : null;
69
79
  this.#openOf = openOf;
70
80
  this.#resolve = resolve;
71
81
  this.#read = readRanges;
@@ -344,6 +354,10 @@ export class EncodeInputs {
344
354
  #sizingFor(output) {
345
355
  const rate = middleOf(this.#copyRates);
346
356
  const open = this.#openOf(output);
357
+ if (this.#fixedStretchBytes !== null) {
358
+ return { bytes: this.#fixedStretchBytes, openMeasured: true, openSeconds: open?.seconds ?? null,
359
+ copyBytesPerMs: rate, fixed: true };
360
+ }
347
361
  return rate === null || !open ? null : { bytes: Math.floor(rate * open.seconds * 1000),
348
362
  openMeasured: open.measured, openSeconds: open.seconds, copyBytesPerMs: rate };
349
363
  }
@@ -607,7 +621,7 @@ export class EncodeInputs {
607
621
  if (result.kind === "result") {
608
622
  this.#log(`encode input selection of ${addressOf(output)}: ${JSON.stringify({
609
623
  from, requestedTo: request.to, serves, floor, targetEnd, chosenEnd: end,
610
- targetBytes: target, minimumBytes: minimum, inputBytes: result.bytes,
624
+ targetBytes: target, targetFixed: sizing?.fixed === true, minimumBytes: minimum, inputBytes: result.bytes,
611
625
  copyBytesPerMs: sizing?.copyBytesPerMs ?? null, openSeconds: sizing?.openSeconds ?? null,
612
626
  openMeasured: sizing?.openMeasured ?? null, reservations, probes
613
627
  })}`);
@@ -195,6 +195,9 @@ export function wireOutputs({
195
195
  // A software preset every picture is encoded at, for runs compared at one
196
196
  // quality (`--pin-preset`); null leaves the choice to the machine.
197
197
  pinnedPreset = null,
198
+ // A size every original-input stretch is given in place of copy rate
199
+ // times open (`--input-stretch-bytes`); null keeps the rule.
200
+ inputStretchBytes = null,
198
201
  // What every encoder this host may use was qualified and measured to do at
199
202
  // startup, by kind (`encode/calibration.js`). Takes the place of the one
200
203
  // array above, which a test may still hand in on its own.
@@ -1097,6 +1100,7 @@ export function wireOutputs({
1097
1100
  readRanges: readEncodeRanges,
1098
1101
  heldRanges: readEncodeHeldRanges,
1099
1102
  stretchCopied,
1103
+ stretchBytes: inputStretchBytes,
1100
1104
  reviseBudget: () => parts.machineBudget.revise("memory", "admitted encode inputs"),
1101
1105
  capacity: () => parts.machineBudget.capacityOf("memory"),
1102
1106
  // How long this output's input takes to open, from the one owner of start
@@ -1120,6 +1124,9 @@ export function wireOutputs({
1120
1124
  parts.serving.invalidateWaits(output);
1121
1125
  }
1122
1126
  }) : null);
1127
+ if (parts.encodeInputs && inputStretchBytes) {
1128
+ logger.info(`encode input: every original-input stretch sized to ${inputStretchBytes} bytes (--input-stretch-bytes)`);
1129
+ }
1123
1130
  // One owner of the disk, and the list of what takes it lives with the owner.
1124
1131
  parts.machineBudget = wireMachineBudget({
1125
1132
  segmentStore: parts.segmentStore,