@torrent-tv/proxy 2.99.1 → 2.99.3
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/package.json
CHANGED
|
@@ -43,24 +43,29 @@
|
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* Whether an output's pieces
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
46
|
+
* Whether an output's pieces may hold a little past their published end: a
|
|
47
|
+
* piece ends at the first frame boundary at or after it, and the player places
|
|
48
|
+
* the next piece where this one truly ends (hls.js `updateFragPTSDTS`). A
|
|
49
|
+
* viewer standing at a published edge is then asked for by the piece BEFORE
|
|
50
|
+
* it. True of a copied picture, whose pieces end at a packet, and of sound
|
|
51
|
+
* however it is made: copied sound ends at a packet, and encoded sound at a
|
|
52
|
+
* frame of the encoder — 1024 samples of AAC, 21.3 ms at 48 kHz. Only a
|
|
53
|
+
* re-encoded picture, given a keyframe at every cut, ends where it is published.
|
|
51
54
|
*
|
|
52
55
|
* Field 2026-10-09, MP3 copied out of an AVI: a seek to 4000 s asked for the
|
|
53
56
|
* piece ending at 4000 s. Field r43 (Home Assistant, 2026-10-15), a copied
|
|
54
57
|
* Matroska picture: a seek to 1000.000 s, the published start of #96, asked for
|
|
55
58
|
* #95 on both tracks; the picture's pieces were not counted as copies, nothing
|
|
56
|
-
* made #95, and the picture stood 131 s until the viewer moved
|
|
57
|
-
* (
|
|
59
|
+
* made #95, and the picture stood 131 s until the viewer moved. With the
|
|
60
|
+
* picture counted (r44), its #95 was made in 6.4 s and the soundtrack's, AAC
|
|
61
|
+
* encoded from the film (`its muxer counts cuts -0.021333s`), was still not
|
|
62
|
+
* made (torrent-tv/meta#178).
|
|
58
63
|
*
|
|
59
64
|
* @param {{ video?: object | null, audio?: object | null, transcodesVideo?: boolean, transcodesAudio?: boolean } | null | undefined} spec
|
|
60
65
|
* @returns {boolean}
|
|
61
66
|
*/
|
|
62
67
|
export function piecesRunPastEnd(spec) {
|
|
63
|
-
return (Boolean(spec?.video) && spec.transcodesVideo !== true) ||
|
|
68
|
+
return (Boolean(spec?.video) && spec.transcodesVideo !== true) || Boolean(spec?.audio);
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
export class Timeline {
|
|
@@ -496,7 +496,11 @@ export class QualityController {
|
|
|
496
496
|
bufferedSec: buffer?.bufferedSec ?? 0,
|
|
497
497
|
slope: buffer?.slope ?? null,
|
|
498
498
|
reportGapSec: buffer?.reportGapSec ?? 0,
|
|
499
|
-
secondsToReady: this.#secondsToReady(session)
|
|
499
|
+
secondsToReady: this.#secondsToReady(session),
|
|
500
|
+
// What is left of the film after them: a buffer holding all of it drains
|
|
501
|
+
// because the film ends.
|
|
502
|
+
remainingSec: Number.isFinite(buffer?.positionSec) && session.file?.durationSeconds > 0
|
|
503
|
+
? Math.max(0, session.file.durationSeconds - buffer.positionSec) : null
|
|
500
504
|
});
|
|
501
505
|
if (!threat) {
|
|
502
506
|
return false;
|
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
*
|
|
21
21
|
* A time to ready that is not known is not assumed to be short: with nothing to
|
|
22
22
|
* show there is time left, a draining buffer is a threat.
|
|
23
|
+
*
|
|
24
|
+
* A BUFFER HOLDING THE REST OF THE FILM IS NO THREAT: it drains because the
|
|
25
|
+
* film ends, and no output can add to it. Field r43 (Home Assistant,
|
|
26
|
+
* 2026-10-15): the last two minutes of an AVI were read as a draining buffer,
|
|
27
|
+
* a faster setting was prepared 53 times and given up each time with nothing
|
|
28
|
+
* left to give, and the player was asked for 240p eight times
|
|
29
|
+
* (torrent-tv/meta#178).
|
|
23
30
|
*/
|
|
24
31
|
|
|
25
32
|
/**
|
|
@@ -31,14 +38,19 @@
|
|
|
31
38
|
* two reports.
|
|
32
39
|
* @param {number | null} params.secondsToReady - How long the new output would
|
|
33
40
|
* take to close the piece the viewer needs; null when not known.
|
|
41
|
+
* @param {number | null} [params.remainingSec] - The film left after where the
|
|
42
|
+
* viewer stands; null when not known.
|
|
34
43
|
* @returns {{ threat: boolean, secondsToEmpty: number | null }}
|
|
35
44
|
*/
|
|
36
|
-
export function drainThreat({ bufferedSec, slope, reportGapSec, secondsToReady }) {
|
|
45
|
+
export function drainThreat({ bufferedSec, slope, reportGapSec, secondsToReady, remainingSec = null }) {
|
|
37
46
|
if (!Number.isFinite(slope) || slope >= 0) {
|
|
38
47
|
return { threat: false, secondsToEmpty: null };
|
|
39
48
|
}
|
|
40
49
|
const held = Number.isFinite(bufferedSec) && bufferedSec > 0 ? bufferedSec : 0;
|
|
41
50
|
const secondsToEmpty = held / -slope;
|
|
51
|
+
if (Number.isFinite(remainingSec) && held >= remainingSec) {
|
|
52
|
+
return { threat: false, secondsToEmpty };
|
|
53
|
+
}
|
|
42
54
|
if (!Number.isFinite(secondsToReady) || secondsToReady < 0) {
|
|
43
55
|
return { threat: true, secondsToEmpty };
|
|
44
56
|
}
|
|
@@ -338,7 +338,8 @@ export function bufferOf(viewers, output, consumerId, spanSec) {
|
|
|
338
338
|
}
|
|
339
339
|
const trend = viewer.bufferTrend(spanSec);
|
|
340
340
|
const held = Number.isFinite(viewer.bufferedSeconds) ? Math.max(0, viewer.bufferedSeconds) : 0;
|
|
341
|
-
return { bufferedSec: held, slope: trend?.slope ?? null, reportGapSec: trend?.reportGapSec ?? 0
|
|
341
|
+
return { bufferedSec: held, slope: trend?.slope ?? null, reportGapSec: trend?.reportGapSec ?? 0,
|
|
342
|
+
positionSec: viewer.positionSeconds() ?? null };
|
|
342
343
|
}
|
|
343
344
|
|
|
344
345
|
/**
|