@torrent-tv/proxy 2.76.3 → 2.76.5
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/CHANGELOG.md +11 -0
- package/biome.json +32 -0
- package/package.json +1 -1
- package/services/encode/EncodePlan.js +3 -1
- package/services/encode/EncodeRun.js +21 -1
- package/services/encode/encode-run-state.js +67 -0
- package/services/hls-session-manager.js +80 -540
- package/services/orchestrators/EncodeOrchestrator.js +42 -3
- package/services/quality/EncodeCost.js +500 -0
- package/test/encode-cost.test.js +94 -0
- package/test/encode-orchestrator.test.js +31 -0
- package/test/encode-plan.test.js +33 -0
|
@@ -194,3 +194,34 @@ test("nothing wanted anywhere is said plainly", () => {
|
|
|
194
194
|
const { made } = orchestrator();
|
|
195
195
|
assert.match(made.describe(), /nothing wanted/);
|
|
196
196
|
});
|
|
197
|
+
|
|
198
|
+
test("a run adopted with no end holds the look-ahead, not the rest of the film", () => {
|
|
199
|
+
// A session's own encoder is handed to the plan rather than built by it, and
|
|
200
|
+
// it carries `to = -1` — no end. Claiming the film from there would leave a
|
|
201
|
+
// viewer further in with no encoder at all: they would wait for this run to
|
|
202
|
+
// encode its way to them, which on a long film is an hour. What bounds it is
|
|
203
|
+
// the look-ahead, because a run is suspended once it is that far in front of
|
|
204
|
+
// its viewer and produces nothing until somebody asks.
|
|
205
|
+
const { made } = orchestrator({ maxRuns: 2 });
|
|
206
|
+
made.lookaheadSegments = 30;
|
|
207
|
+
const adopted = {
|
|
208
|
+
from: 0,
|
|
209
|
+
to: -1,
|
|
210
|
+
head: 3,
|
|
211
|
+
isAlive: true,
|
|
212
|
+
isStopping: false,
|
|
213
|
+
speedX: 8,
|
|
214
|
+
stop() {
|
|
215
|
+
this.isAlive = false;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
made.adopt(PICTURE, adopted);
|
|
219
|
+
|
|
220
|
+
made.want({ claimant: "far", address: PICTURE, from: 200, to: 230 });
|
|
221
|
+
made.reconcile();
|
|
222
|
+
|
|
223
|
+
const runs = made.runsOn(PICTURE);
|
|
224
|
+
assert.equal(runs.length, 2, "the viewer further in got an encoder of their own");
|
|
225
|
+
assert.ok(adopted.isAlive, "and the adopted run was not stopped to make room");
|
|
226
|
+
assert.equal(runs.some((run) => run.from === 200), true, "started where that viewer is waiting");
|
|
227
|
+
});
|
package/test/encode-plan.test.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import test from "node:test";
|
|
11
11
|
import assert from "node:assert/strict";
|
|
12
12
|
import { CoverageMap } from "../services/encode/CoverageMap.js";
|
|
13
|
+
import { endOfRun } from "../services/encode/EncodeRun.js";
|
|
13
14
|
import { firstUnmetWant, planEncoders } from "../services/encode/EncodePlan.js";
|
|
14
15
|
|
|
15
16
|
/** A host that can afford two encoders, four-second segments, a cheap restart. */
|
|
@@ -243,3 +244,35 @@ test("the lowest thing a viewer is waiting for is reported, so a stalled plan is
|
|
|
243
244
|
coverage.markReadyAll([42, 43, 44]);
|
|
244
245
|
assert.equal(firstUnmetWant(coverage, [{ from: 40, to: 44 }]), null);
|
|
245
246
|
});
|
|
247
|
+
|
|
248
|
+
test("a run with no end is making what the viewers ahead of it are waiting for", () => {
|
|
249
|
+
// Field, 2026-09-05: an encoder was started and killed every five seconds,
|
|
250
|
+
// each producing 0-2 segments, for as long as anybody watched. A run given no
|
|
251
|
+
// end carries `to = -1`, and two places read that as a number instead of as
|
|
252
|
+
// "no end": the overlap test called its work unwanted, and the claim it made
|
|
253
|
+
// in the coverage map was one segment long, so the plan saw the rest of the
|
|
254
|
+
// film as free and started another encoder there.
|
|
255
|
+
const coverage = new CoverageMap({ segmentCount: 570 });
|
|
256
|
+
const run = { from: 0, to: -1, head: 3, speedX: 8, isAlive: true };
|
|
257
|
+
coverage.claim(run, run.from, endOfRun(run));
|
|
258
|
+
|
|
259
|
+
const actions = planEncoders({
|
|
260
|
+
coverage,
|
|
261
|
+
live: [run],
|
|
262
|
+
wanted: [{ from: 0, to: 30 }],
|
|
263
|
+
maxRuns: 2,
|
|
264
|
+
segmentSeconds: 4,
|
|
265
|
+
restartCostSec: 0.12
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
assert.deepEqual(
|
|
269
|
+
actions.filter((action) => action.type === "stop"),
|
|
270
|
+
[],
|
|
271
|
+
"nothing is stopped: it is making exactly what is wanted"
|
|
272
|
+
);
|
|
273
|
+
assert.deepEqual(
|
|
274
|
+
actions.filter((action) => action.type === "start"),
|
|
275
|
+
[],
|
|
276
|
+
"and nothing new is started over ground it already holds"
|
|
277
|
+
);
|
|
278
|
+
});
|