@torrent-tv/proxy 2.80.2 → 2.80.4
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 +16 -1
- package/package.json +1 -1
- package/services/encode/EncodeRun.js +29 -0
- package/services/encode/SegmentStore.js +2 -2
- package/services/encode/open-piece.js +29 -5
- package/services/encode/run-command.js +697 -662
- package/services/hls-session-manager.js +10626 -10674
- package/services/orchestrators/EncodeOrchestrator.js +5 -2
- package/services/output/Timeline.js +256 -220
- package/services/output/cut-grid.js +97 -0
- package/test/flushed-piece.test.js +108 -0
- package/test/quality-variants.test.js +1209 -1116
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The piece an encoder writes out on its way to being stopped.
|
|
3
|
+
*
|
|
4
|
+
* `-segment_list pipe:3` was taken as proof that a piece is whole: ffmpeg names
|
|
5
|
+
* a file when it closes it, so a named file is closed. True of the FILE and
|
|
6
|
+
* false of the SPAN. On SIGTERM ffmpeg writes out the piece it had open and
|
|
7
|
+
* names it like any other, so the result is a valid, decodable piece holding
|
|
8
|
+
* film only up to the instant of the stop — under a name whose playlist entry
|
|
9
|
+
* promises the whole span.
|
|
10
|
+
*
|
|
11
|
+
* Field 2026-09-06, one session, both tracks: `segment-00010.mp4` held 3.92 s
|
|
12
|
+
* of its declared 5.589 s (96 frames), and the picture jumped 1.5 s at 1:02;
|
|
13
|
+
* the soundtrack's own stopped run left the same shape at 17.5 s, 2.8 s wide.
|
|
14
|
+
* Judging such a file by whether it decodes answers yes, which is how both
|
|
15
|
+
* reached the viewer.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import test from "node:test";
|
|
19
|
+
import assert from "node:assert/strict";
|
|
20
|
+
import { mkdtemp, rm, writeFile, readdir } from "node:fs/promises";
|
|
21
|
+
import os from "node:os";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { discardOpenPiece } from "../services/encode/open-piece.js";
|
|
24
|
+
|
|
25
|
+
const format = {
|
|
26
|
+
isSegmentFileName: (name) => /^segment-\d{5}\.mp4$/.test(name),
|
|
27
|
+
segmentIndexFromName: (name) => Number(name.slice(8, 13))
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** A run directory holding pieces 0..last, every one of them readable. */
|
|
31
|
+
async function runDirectory(last) {
|
|
32
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "flushed-piece-"));
|
|
33
|
+
for (let index = 0; index <= last; index += 1) {
|
|
34
|
+
await writeFile(path.join(dir, `segment-${String(index).padStart(5, "0")}.mp4`), Buffer.alloc(64, 7));
|
|
35
|
+
}
|
|
36
|
+
return dir;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test("the piece named on the way out goes, though it reads perfectly", async () => {
|
|
40
|
+
const dir = await runDirectory(10);
|
|
41
|
+
try {
|
|
42
|
+
const removed = await discardOpenPiece(
|
|
43
|
+
dir,
|
|
44
|
+
format,
|
|
45
|
+
{ from: 0, to: 535 },
|
|
46
|
+
// Everything decodes. This is the field case exactly: the short piece is
|
|
47
|
+
// a valid fMP4 and nothing about its contents betrays it.
|
|
48
|
+
() => true,
|
|
49
|
+
"segment-00010.mp4"
|
|
50
|
+
);
|
|
51
|
+
assert.equal(removed, 10, "the flushed piece was kept because it decodes");
|
|
52
|
+
const left = await readdir(dir);
|
|
53
|
+
assert.ok(!left.includes("segment-00010.mp4"));
|
|
54
|
+
assert.ok(left.includes("segment-00009.mp4"), "a piece closed before the stop was taken too");
|
|
55
|
+
} finally {
|
|
56
|
+
await rm(dir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("a run that named nothing on the way out loses no readable piece", async () => {
|
|
61
|
+
// A run that reached the end of its stretch closed its last file properly.
|
|
62
|
+
// Removing it would mean encoding it a second time for nothing.
|
|
63
|
+
const dir = await runDirectory(10);
|
|
64
|
+
try {
|
|
65
|
+
const removed = await discardOpenPiece(dir, format, { from: 0, to: 535 }, () => true, null);
|
|
66
|
+
assert.equal(removed, null);
|
|
67
|
+
assert.ok((await readdir(dir)).includes("segment-00010.mp4"));
|
|
68
|
+
} finally {
|
|
69
|
+
await rm(dir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("a piece that does not read still goes, named or not", async () => {
|
|
74
|
+
const dir = await runDirectory(10);
|
|
75
|
+
try {
|
|
76
|
+
const removed = await discardOpenPiece(dir, format, { from: 0, to: 535 }, () => false, null);
|
|
77
|
+
assert.equal(removed, 10, "an unreadable last piece survived");
|
|
78
|
+
} finally {
|
|
79
|
+
await rm(dir, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("only inside the stretch the ended run was given", async () => {
|
|
84
|
+
// Several runs write into one directory, kept apart by their intervals. The
|
|
85
|
+
// highest file overall may belong to a run that is still going.
|
|
86
|
+
const dir = await runDirectory(20);
|
|
87
|
+
try {
|
|
88
|
+
const removed = await discardOpenPiece(
|
|
89
|
+
dir, format, { from: 0, to: 10 }, () => true, "segment-00010.mp4"
|
|
90
|
+
);
|
|
91
|
+
assert.equal(removed, 10);
|
|
92
|
+
assert.ok((await readdir(dir)).includes("segment-00020.mp4"), "another run's piece was taken");
|
|
93
|
+
} finally {
|
|
94
|
+
await rm(dir, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("a name from another run's stretch takes nothing", async () => {
|
|
99
|
+
const dir = await runDirectory(20);
|
|
100
|
+
try {
|
|
101
|
+
const removed = await discardOpenPiece(
|
|
102
|
+
dir, format, { from: 0, to: 10 }, () => true, "segment-00020.mp4"
|
|
103
|
+
);
|
|
104
|
+
assert.equal(removed, null, "a name outside the stretch removed a piece anyway");
|
|
105
|
+
} finally {
|
|
106
|
+
await rm(dir, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
});
|