@torrent-tv/proxy 2.15.3 → 2.17.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/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/server.js +6 -12
- package/services/hls-session-manager.js +91 -0
- package/services/host-load.js +154 -0
- package/services/hwaccel.js +1502 -1248
- package/test/encode-slope.test.js +46 -0
- package/test/host-load.test.js +68 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The slope that turns ffmpeg's progress reports into a preset's speed.
|
|
3
|
+
*
|
|
4
|
+
* Written against the faults a review found in it on 2026-08-15, each of which
|
|
5
|
+
* would have opened the quality ladder rather than closing it: a window of no
|
|
6
|
+
* width at all, and a position ffmpeg reports as the smallest signed 64-bit
|
|
7
|
+
* integer when it has none yet.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import test from "node:test";
|
|
12
|
+
|
|
13
|
+
import { slopeOf } from "../services/hwaccel.js";
|
|
14
|
+
|
|
15
|
+
const at = (wallSec, outSec) => ({ wallSec, outSec });
|
|
16
|
+
|
|
17
|
+
test("a steady run measures its own speed", () => {
|
|
18
|
+
assert.equal(slopeOf([at(1, 10), at(2, 14)]), 4);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("a window of no width is refused, however tempting the numbers", () => {
|
|
22
|
+
// Two reports a millisecond apart: 0.042 s of video over 0.001 s of clock is
|
|
23
|
+
// 42x, on a host that may be doing 3x.
|
|
24
|
+
assert.equal(slopeOf([at(1.0, 10), at(1.001, 10.042)], 0.2), null);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("a run that produced nothing between two reports says nothing", () => {
|
|
28
|
+
assert.equal(slopeOf([at(1, 10), at(3, 10)]), null);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("one report is not a measurement", () => {
|
|
32
|
+
assert.equal(slopeOf([at(1, 10)]), null);
|
|
33
|
+
assert.equal(slopeOf([]), null);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("an impossible speed is a fault, not a fast machine", () => {
|
|
37
|
+
// Nothing encodes 640x360 five thousand times realtime; a reading that says
|
|
38
|
+
// so is a measurement fault, and letting it through raises the bar every
|
|
39
|
+
// ladder decision is taken from.
|
|
40
|
+
assert.equal(slopeOf([at(1, 0), at(2, 5000)]), null);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("the narrowest allowed window is honoured", () => {
|
|
44
|
+
assert.equal(slopeOf([at(1.0, 10), at(1.3, 11)], 0.5), null);
|
|
45
|
+
assert.ok(slopeOf([at(1.0, 10), at(1.6, 12)], 0.5) > 0);
|
|
46
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The arithmetic that turns two readings of the machine into shares.
|
|
3
|
+
*
|
|
4
|
+
* The readings themselves are files this host may or may not have; what is
|
|
5
|
+
* tested here is what is DERIVED from them, because that is where a wrong
|
|
6
|
+
* number would quietly become a wrong conclusion about why an encoder is slow.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import test from "node:test";
|
|
11
|
+
|
|
12
|
+
import { readProcessCpuSeconds, readSystemCpu, sampleHost, shareOfMachine } from "../services/host-load.js";
|
|
13
|
+
|
|
14
|
+
test("a process using one core of four for a second reports a quarter of the machine", () => {
|
|
15
|
+
const before = { takenAt: 1_000, processCpuSeconds: 10, system: null };
|
|
16
|
+
const after = { takenAt: 2_000, processCpuSeconds: 11, system: null };
|
|
17
|
+
const share = shareOfMachine(before, after, 4);
|
|
18
|
+
assert.equal(share?.elapsedSec, 1);
|
|
19
|
+
assert.equal(share?.processShare, 0.25);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("a process using every core reports the whole machine", () => {
|
|
23
|
+
const share = shareOfMachine(
|
|
24
|
+
{ takenAt: 0, processCpuSeconds: 0, system: null },
|
|
25
|
+
{ takenAt: 2_000, processCpuSeconds: 8, system: null },
|
|
26
|
+
4
|
|
27
|
+
);
|
|
28
|
+
assert.equal(share?.processShare, 1);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("waiting for a disk is counted apart from working", () => {
|
|
32
|
+
const before = { takenAt: 0, processCpuSeconds: null, system: { busySeconds: 100, idleSeconds: 900, iowaitSeconds: 10 } };
|
|
33
|
+
const after = { takenAt: 1_000, processCpuSeconds: null, system: { busySeconds: 101, idleSeconds: 902, iowaitSeconds: 11 } };
|
|
34
|
+
const share = shareOfMachine(before, after, 4);
|
|
35
|
+
assert.equal(share?.systemShare, 0.25);
|
|
36
|
+
assert.equal(share?.iowaitShare, 0.25);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("two readings taken at the same instant say nothing rather than dividing by zero", () => {
|
|
40
|
+
assert.equal(shareOfMachine({ takenAt: 5, processCpuSeconds: 1, system: null }, { takenAt: 5, processCpuSeconds: 2, system: null }, 4), null);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("a missing reading leaves that share unknown, not zero", () => {
|
|
44
|
+
const share = shareOfMachine(
|
|
45
|
+
{ takenAt: 0, processCpuSeconds: null, system: null },
|
|
46
|
+
{ takenAt: 1_000, processCpuSeconds: 1, system: null },
|
|
47
|
+
4
|
|
48
|
+
);
|
|
49
|
+
assert.equal(share?.processShare, null);
|
|
50
|
+
assert.equal(share?.systemShare, null);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("a process that does not exist reports nothing at all", async () => {
|
|
54
|
+
assert.equal(await readProcessCpuSeconds(0), null);
|
|
55
|
+
assert.equal(await readProcessCpuSeconds(-1), null);
|
|
56
|
+
// A pid far above any real one on this machine.
|
|
57
|
+
assert.equal(await readProcessCpuSeconds(4_000_000), null);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("on a host without /proc the readings are null and the sampler still answers", async () => {
|
|
61
|
+
// This runs on Linux in CI and on Windows here; both must be safe. What is
|
|
62
|
+
// asserted is the SHAPE — a reading is either a number or null, never a throw.
|
|
63
|
+
const system = await readSystemCpu();
|
|
64
|
+
assert.ok(system === null || typeof system.busySeconds === "number");
|
|
65
|
+
const sample = await sampleHost(null);
|
|
66
|
+
assert.equal(typeof sample.takenAt, "number");
|
|
67
|
+
assert.equal(sample.processCpuSeconds, null);
|
|
68
|
+
});
|