@torrent-tv/proxy 2.89.5 → 2.89.6
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/package.json +1 -1
- package/test/auto-quality-step.test.js +762 -753
- package/test/decode-cost.test.js +475 -462
- package/test/format-keyed-outputs.test.js +78 -78
- package/test/helpers/manager.js +62 -57
- package/test/quality-variants.test.js +1270 -1257
- package/test/segment-judged-by-its-own-header.test.js +222 -221
- package/test/segment-serve-wiring.test.js +9 -3
- package/test/serving-existing-output.test.js +111 -105
- package/test/two-viewers-one-picture.test.js +508 -504
- package/test/viewer-requests-admission.test.js +92 -89
- package/test/viewing-generations.test.js +390 -390
|
@@ -1,105 +1,111 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file An output already made serves a viewer when the rules decided with the
|
|
3
|
-
* user 2026-09-16 allow it, through the paths a real request takes.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import test from "node:test";
|
|
7
|
-
import assert from "node:assert/strict";
|
|
8
|
-
import { writeFileSync } from "node:fs";
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import { managerWithOwnStore } from "./helpers/manager.js";
|
|
11
|
-
import { outputSpec } from "./helpers/output-spec.js";
|
|
12
|
-
import { SourceFile } from "../services/media/SourceFile.js";
|
|
13
|
-
import { Timeline } from "../services/encode/output/Timeline.js";
|
|
14
|
-
import { fmp4Format } from "../services/encode/segment-formats/fmp4.js";
|
|
15
|
-
import { Output } from "../services/encode/output/Output.js";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
manager.encodeRuns.
|
|
30
|
-
manager.
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
spec,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @file An output already made serves a viewer when the rules decided with the
|
|
3
|
+
* user 2026-09-16 allow it, through the paths a real request takes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { writeFileSync } from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { managerWithOwnStore } from "./helpers/manager.js";
|
|
11
|
+
import { outputSpec } from "./helpers/output-spec.js";
|
|
12
|
+
import { SourceFile } from "../services/media/SourceFile.js";
|
|
13
|
+
import { Timeline } from "../services/encode/output/Timeline.js";
|
|
14
|
+
import { fmp4Format } from "../services/encode/segment-formats/fmp4.js";
|
|
15
|
+
import { Output } from "../services/encode/output/Output.js";
|
|
16
|
+
import { qualityStateOf } from "../services/encode/quality/OutputQualityState.js";
|
|
17
|
+
|
|
18
|
+
const TORRENT = "torrent:11f0929918e2b5aa2e5b71ecdbe5c0f1a4bbf7d1";
|
|
19
|
+
|
|
20
|
+
function hostWithA1080pOutput(t) {
|
|
21
|
+
const { manager, store, cleanup } = managerWithOwnStore({
|
|
22
|
+
startupWaitMs: 0,
|
|
23
|
+
videoEncoder: { kind: "vaapi", name: "h264_vaapi", inputArgs: [] }
|
|
24
|
+
});
|
|
25
|
+
t.after(async () => {
|
|
26
|
+
await manager.lifecycle.disposeAll();
|
|
27
|
+
cleanup();
|
|
28
|
+
});
|
|
29
|
+
manager.encodeRuns.planEncodersNow = () => {};
|
|
30
|
+
manager.encodeRuns.planEncodersSoon = () => {};
|
|
31
|
+
manager.getCachedMediaInfo = () => ({ durationSeconds: 400, width: 1920, height: 1080, fps: 24 });
|
|
32
|
+
// The soundtrack the plan listed, at the rate the file states: a copy of it
|
|
33
|
+
// has a figure, so it stays a copy.
|
|
34
|
+
manager.getCachedAudioTracks = () => [{ index: 0, fileIndex: 0, sourceTrackIndex: 0, bitrateKbps: 128 }];
|
|
35
|
+
const spec = outputSpec({
|
|
36
|
+
sourceKey: TORRENT,
|
|
37
|
+
transcodeVideo: true,
|
|
38
|
+
transcodeAudio: false,
|
|
39
|
+
encoder: "h264_vaapi",
|
|
40
|
+
width: 1920,
|
|
41
|
+
height: 1080,
|
|
42
|
+
fps: 24,
|
|
43
|
+
cutGrid: "uniform"
|
|
44
|
+
});
|
|
45
|
+
const key = spec.toKey();
|
|
46
|
+
store.useFormat(key, fmp4Format);
|
|
47
|
+
// The piece at the start of the film is made.
|
|
48
|
+
writeFileSync(path.join(store.directoryFor(key), fmp4Format.segmentFileName(0)), Buffer.alloc(100));
|
|
49
|
+
const file = new SourceFile({ sourceKey: TORRENT, fileIndex: 0, name: "film.mkv" }).learn({ width: 1920, height: 1080, durationSeconds: 400 });
|
|
50
|
+
const made = {
|
|
51
|
+
id: spec.toName(),
|
|
52
|
+
spec,
|
|
53
|
+
get outputKey() { return this.spec.toKey(); },
|
|
54
|
+
file,
|
|
55
|
+
timeline: new Timeline({ boundaries: Array.from({ length: 101 }, (_, index) => index * 4), cutGrid: "uniform" }),
|
|
56
|
+
output: new Output({ encodeWidth: 1920, encodeHeight: 1080, outputFps: 24 }),
|
|
57
|
+
segmentFormat: fmp4Format,
|
|
58
|
+
useSyntheticPlaylist: true
|
|
59
|
+
};
|
|
60
|
+
manager.outputs.set(made.id, made);
|
|
61
|
+
// WHAT ITS ENCODER WAS SEEN DOING. Its first piece is made, so an encoder ran
|
|
62
|
+
// on it here; a viewer put on it now needs one again, and a place for one is
|
|
63
|
+
// asked by what one costs — with no measured cost the proxy refuses (roadmap
|
|
64
|
+
// item 97, step 14).
|
|
65
|
+
qualityStateOf(made).lastAloneSpeed = 2;
|
|
66
|
+
return { manager, made };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function request(over) {
|
|
70
|
+
return {
|
|
71
|
+
sourceKey: TORRENT,
|
|
72
|
+
fileIndex: 0,
|
|
73
|
+
fileName: "film.mkv",
|
|
74
|
+
transcodeVideo: true,
|
|
75
|
+
transcodeAudio: false,
|
|
76
|
+
segmentFormatId: "fmp4",
|
|
77
|
+
...over
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
test("the automatic choice is served by a better output whose piece at the viewer's position is made", async (t) => {
|
|
82
|
+
const { manager, made } = hostWithA1080pOutput(t);
|
|
83
|
+
const answered = await manager.viewerRequests.createOrGetSession(
|
|
84
|
+
request({ consumerId: "auto-viewer", targetWidth: 1280, targetHeight: 720 })
|
|
85
|
+
);
|
|
86
|
+
assert.equal(answered, made);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("a size picked by hand is not served by another size", async (t) => {
|
|
90
|
+
const { manager, made } = hostWithA1080pOutput(t);
|
|
91
|
+
let answered = null;
|
|
92
|
+
try {
|
|
93
|
+
answered = await manager.viewerRequests.createOrGetSession(
|
|
94
|
+
request({ consumerId: "picker", targetWidth: 1280, targetHeight: 720, exactSize: true })
|
|
95
|
+
);
|
|
96
|
+
} catch {
|
|
97
|
+
answered = null;
|
|
98
|
+
}
|
|
99
|
+
assert.notEqual(answered, made);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("a step asked for by an automatic viewer and served by the picture leaves the picture a picture", async (t) => {
|
|
103
|
+
const { manager, made } = hostWithA1080pOutput(t);
|
|
104
|
+
manager.viewers.of(made, "auto-viewer").qualityMode = "auto";
|
|
105
|
+
|
|
106
|
+
const variant = await manager.renditions.resolveVariantSession(made.id, 720, 0, "auto-viewer");
|
|
107
|
+
|
|
108
|
+
assert.equal(variant, made, "the picture already made at 1080p serves the 720p request");
|
|
109
|
+
assert.notEqual(made.isStep, true, "and is not turned into a step of itself");
|
|
110
|
+
assert.ok(manager.viewers.forOutput(made).has("auto-viewer"));
|
|
111
|
+
});
|