@torrent-tv/proxy 2.80.12 → 2.80.14
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 +19 -0
- package/docs/download-architecture.md +65 -0
- package/docs/encode-architecture.md +52 -0
- package/package.json +1 -1
- package/routes/api/transcode-sessions/net-report/post.js +64 -53
- package/routes/stream/get.js +324 -300
- package/routes/transcode/session-file/get.js +22 -2
- package/services/download/SwarmSelection.js +20 -4
- package/services/encode/SegmentDemand.js +34 -0
- package/services/encode/SegmentStore.js +743 -718
- package/services/hls-session-manager.js +22 -29
- package/services/orchestrators/EncodeOrchestrator.js +735 -726
- package/services/output/LiveOutputs.js +36 -0
- package/services/output/playlists.js +86 -11
- package/services/output/rates.js +95 -0
- package/services/piece-store/piece-lru.js +9 -1
- package/services/priority/PriorityOrchestrator.js +284 -278
- package/services/priority/WaitLedger.js +142 -0
- package/services/supply-margin.js +40 -1
- package/services/torrent-pool.js +38 -1
- package/services/torrent-worker/client.js +27 -12
- package/services/torrent-worker/piece-reader.js +9 -4
- package/services/torrent-worker/worker.js +5 -0
- package/services/viewer/Viewer.js +345 -297
- package/test/declared-rates.test.js +116 -0
- package/test/piece-lru.test.js +5 -1
- package/test/supply-margin.test.js +25 -8
- package/test/wait-ledger.test.js +100 -0
|
@@ -3178,7 +3178,7 @@ export class HlsSessionManager {
|
|
|
3178
3178
|
* @param {{ linkMbps: number, bufferedAheadSec: number, consumerId?: string, positionSeconds?: number }} report
|
|
3179
3179
|
* @returns {boolean}
|
|
3180
3180
|
*/
|
|
3181
|
-
recordNetReport(sessionId, { linkMbps, bufferedAheadSec, consumerId, positionSeconds, playing }) {
|
|
3181
|
+
recordNetReport(sessionId, { linkMbps, bufferedAheadSec, consumerId, positionSeconds, playing, onScreen, inPictureInPicture }) {
|
|
3182
3182
|
const named = this.sessionsById.get(sessionId);
|
|
3183
3183
|
if (!named || named.state === "disposed") {
|
|
3184
3184
|
return false;
|
|
@@ -3196,7 +3196,7 @@ export class HlsSessionManager {
|
|
|
3196
3196
|
const now = Date.now();
|
|
3197
3197
|
this.viewers
|
|
3198
3198
|
.of(session, typeof consumerId === "string" && consumerId.length > 0 ? consumerId : "")
|
|
3199
|
-
.report({ linkMbps, bufferedAheadSec, positionSeconds, playing }, now);
|
|
3199
|
+
.report({ linkMbps, bufferedAheadSec, positionSeconds, playing, onScreen, inPictureInPicture }, now);
|
|
3200
3200
|
// A stale reading must not go on deciding for the viewers still here: a
|
|
3201
3201
|
// report describes a link at a moment, and a viewer who seeked since then
|
|
3202
3202
|
// is somewhere else entirely.
|
|
@@ -8295,13 +8295,6 @@ export class HlsSessionManager {
|
|
|
8295
8295
|
if (!this.liveOutputs.publishesVariants(session)) {
|
|
8296
8296
|
return null;
|
|
8297
8297
|
}
|
|
8298
|
-
const sourceHeight = Number(session.file.height) || 0;
|
|
8299
|
-
// What CAN be spliced, not what is worth offering this second. The live
|
|
8300
|
-
// judgement travels in `offeredHeights` and in every progress report, which
|
|
8301
|
-
// is what the viewer's menu follows; letting it decide the master's
|
|
8302
|
-
// existence made a live session answer 404 to its own published address.
|
|
8303
|
-
const rungs = this.liveOutputs.splicableHeights(session);
|
|
8304
|
-
const sourceWidth = Number(session.file.width) || 0;
|
|
8305
8298
|
// The audio tracks, published once for the whole file rather than muxed
|
|
8306
8299
|
// into every rung. Two things follow from that: the same track is not
|
|
8307
8300
|
// encoded once per rung on a host that struggles to encode it once, and
|
|
@@ -8319,10 +8312,12 @@ export class HlsSessionManager {
|
|
|
8319
8312
|
? this.#audioRenditionsOf(session, this.#audioChoiceOf(session, consumerId).trackIndex)
|
|
8320
8313
|
: [];
|
|
8321
8314
|
return masterPlaylistText({
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8315
|
+
// The shape of the film and the rates it carries, asked of the layer that
|
|
8316
|
+
// holds both. What CAN be spliced, not what is worth offering this second:
|
|
8317
|
+
// the live judgement travels in `offeredHeights` and in every progress
|
|
8318
|
+
// report, and letting it decide the master's existence made a live session
|
|
8319
|
+
// answer 404 to its own published address.
|
|
8320
|
+
...this.liveOutputs.masterFactsOf(session, (address) => this.segmentStore.largestPiece(address)),
|
|
8326
8321
|
renditions,
|
|
8327
8322
|
playlistFileName: PLAYLIST_FILE_NAME
|
|
8328
8323
|
});
|
|
@@ -9648,6 +9643,8 @@ export class HlsSessionManager {
|
|
|
9648
9643
|
|
|
9649
9644
|
|
|
9650
9645
|
#holdForProduction(session, fileName, isPlaylist, options) {
|
|
9646
|
+
/** @type {{ address: string, rank: number, topRank: number } | null} */
|
|
9647
|
+
let ranked = null;
|
|
9651
9648
|
if (!isPlaylist) {
|
|
9652
9649
|
this.#explainHold(session, fileName, "the file is not on disk");
|
|
9653
9650
|
}
|
|
@@ -9667,20 +9664,16 @@ export class HlsSessionManager {
|
|
|
9667
9664
|
// failed did the player move to the segment it actually needed — 63 s of
|
|
9668
9665
|
// spinner after a track that had been made ready in 7.
|
|
9669
9666
|
//
|
|
9670
|
-
// WHETHER ANYBODY IS COMING FOR IT, asked of the
|
|
9671
|
-
//
|
|
9672
|
-
//
|
|
9673
|
-
//
|
|
9674
|
-
//
|
|
9675
|
-
//
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
// request as absent for as long as a fresh session has no map.
|
|
9681
|
-
const zones = this.encodeOrchestrator.demand.mapOn(session.outputKey ?? "");
|
|
9682
|
-
const nobodyIsComing = zones.length > 0 &&
|
|
9683
|
-
!zones.some((zone) => requestedIndex >= zone.from && requestedIndex <= zone.to);
|
|
9667
|
+
// WHETHER ANYBODY IS COMING FOR IT, asked of the map (`SegmentDemand.rankOf`,
|
|
9668
|
+
// which also tells "in nobody's zone" from "no map yet"). The same walk
|
|
9669
|
+
// was written out here and could answer only yes or no, so the RANK was
|
|
9670
|
+
// discarded at the one point where a viewer measurably waits for a named
|
|
9671
|
+
// segment; it goes back out with the answer, because the wait is measured
|
|
9672
|
+
// by whoever holds the request.
|
|
9673
|
+
const address = session.outputKey ?? "";
|
|
9674
|
+
const { rank, topRank } = this.encodeOrchestrator.demand.rankOf(address, requestedIndex);
|
|
9675
|
+
ranked = { address, rank, topRank };
|
|
9676
|
+
const nobodyIsComing = topRank > 0 && rank === 0;
|
|
9684
9677
|
if (
|
|
9685
9678
|
Number.isFinite(requestedIndex) &&
|
|
9686
9679
|
requestedIndex < (earliestRunStart(session) ?? 0) &&
|
|
@@ -9691,7 +9684,7 @@ export class HlsSessionManager {
|
|
|
9691
9684
|
`transcode ${session.id} segment #${requestedIndex} is ${(earliestRunStart(session) ?? 0) - requestedIndex} ` +
|
|
9692
9685
|
"segments behind the run and in nobody's zone; answered as absent rather than held"
|
|
9693
9686
|
);
|
|
9694
|
-
return { kind: "not-found" };
|
|
9687
|
+
return { kind: "not-found", ranked };
|
|
9695
9688
|
}
|
|
9696
9689
|
this.#ensureEncodingFor(
|
|
9697
9690
|
session,
|
|
@@ -9699,7 +9692,7 @@ export class HlsSessionManager {
|
|
|
9699
9692
|
Number.isFinite(options?.requestSeq) ? options.requestSeq : Number.MAX_SAFE_INTEGER
|
|
9700
9693
|
);
|
|
9701
9694
|
}
|
|
9702
|
-
return { kind: "warming-up" };
|
|
9695
|
+
return { kind: "warming-up", ranked };
|
|
9703
9696
|
}
|
|
9704
9697
|
|
|
9705
9698
|
/**
|