@torrent-tv/proxy 2.107.50 → 2.107.51
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
|
@@ -154,7 +154,7 @@ export class ViewerRequests {
|
|
|
154
154
|
#forecastPieces = new WeakMap();
|
|
155
155
|
|
|
156
156
|
/**
|
|
157
|
-
* @param {object} host - `opening`, `activeOutputFor`, `viewerSecondsOn`, `minimumBufferSecondsFor`, `getSourceStats`, `planEncodersSoon`, `encodeRuns`, `encodeSpeedReadingsOf`, `
|
|
157
|
+
* @param {object} host - `opening`, `activeOutputFor`, `viewerSecondsOn`, `minimumBufferSecondsFor`, `getSourceStats`, `planEncodersSoon`, `encodeRuns`, `encodeSpeedReadingsOf`, `outputs`, `lookaheadSeconds`, `quality`, `qualityOffer`, `renditions`, `segmentDurationSec`, `segmentStore`, `sourceFiles`, `startupWaitMs`, `viewers`, `placeViewerOn`, `chooseAudioTrack`, `acceptsGeneration`, `generationOfRequest`, `noteGivenOutput`, `holdForResponse`, `noteServingVerdict`, `servingVerdictOf`
|
|
158
158
|
*/
|
|
159
159
|
constructor(host) {
|
|
160
160
|
this.#host = host;
|
|
@@ -351,6 +351,7 @@ export class ViewerRequests {
|
|
|
351
351
|
// Whether they were already on the output this request lands on, read at
|
|
352
352
|
// the moment they are put on it.
|
|
353
353
|
let alreadyOn = false;
|
|
354
|
+
let placedHere = false;
|
|
354
355
|
// THE PLACE ON THIS MACHINE, AND THE VIEWER IN IT, in one synchronous call
|
|
355
356
|
// the opening makes the moment it has the output (roadmap item 97, step 14).
|
|
356
357
|
// Asked and placed together, so the next viewer to open anything is asked
|
|
@@ -367,7 +368,7 @@ export class ViewerRequests {
|
|
|
367
368
|
: this.#host.admitsWatching(candidate);
|
|
368
369
|
if (answer.admitted) {
|
|
369
370
|
known = this.#host.viewers.of(candidate, consumerId);
|
|
370
|
-
this.
|
|
371
|
+
placedHere = this.placeViewerOn(candidate, consumerId, startPositionSeconds) === true;
|
|
371
372
|
}
|
|
372
373
|
return answer;
|
|
373
374
|
}
|
|
@@ -385,7 +386,7 @@ export class ViewerRequests {
|
|
|
385
386
|
// browser may need a track re-encoded that the first viewer's could
|
|
386
387
|
// decode as it stands.
|
|
387
388
|
const viewer = this.#host.viewers.of(output, consumerId);
|
|
388
|
-
|
|
389
|
+
this.#host.chooseAudioTrack(output, consumerId, audio);
|
|
389
390
|
// The picture as their page sees it, which bounds the height made for
|
|
390
391
|
// them from here on (roadmap item 98).
|
|
391
392
|
viewer.noteVisiblePicture(request.visiblePicture);
|
|
@@ -400,7 +401,7 @@ export class ViewerRequests {
|
|
|
400
401
|
: null,
|
|
401
402
|
bufferedAheadSec: request.bufferedAheadSec,
|
|
402
403
|
bufferLimitSeconds: request.bufferLimitSeconds,
|
|
403
|
-
positionSeconds: startPositionSeconds,
|
|
404
|
+
...(placedHere ? { positionSeconds: startPositionSeconds } : {}),
|
|
404
405
|
waiting: true,
|
|
405
406
|
playing: false,
|
|
406
407
|
visiblePicture: request.visiblePicture
|
|
@@ -438,65 +439,24 @@ export class ViewerRequests {
|
|
|
438
439
|
}
|
|
439
440
|
|
|
440
441
|
/**
|
|
441
|
-
*
|
|
442
|
+
* Ask the viewer layer to place this viewer at their initial position.
|
|
442
443
|
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* request, so a viewer counted as placeless until they had asked for a
|
|
447
|
-
* segment, and an output whose viewers were all placeless had every encoder
|
|
448
|
-
* on it stopped for having nobody. The soundtrack that failed that day could
|
|
449
|
-
* not have asked: the segment it would have asked for needed an `init.mp4`
|
|
450
|
-
* that the stopped encoder was going to make.
|
|
451
|
-
*
|
|
452
|
-
* Only ever places a viewer who has none. A viewer already placed is being
|
|
453
|
-
* kept current by their own requests and seeks, and a fresh create request
|
|
454
|
-
* carries a default of zero that must not drag them back to the beginning.
|
|
455
|
-
*
|
|
456
|
-
* @param {HlsSession} session
|
|
457
|
-
* @param {import("../viewer/Viewer.js").Viewer} viewer
|
|
458
|
-
* @param {number} positionSeconds
|
|
459
|
-
* @returns {void}
|
|
460
|
-
*/
|
|
461
|
-
/**
|
|
462
|
-
* Put a viewer named by id onto this output, where they have no position yet.
|
|
463
|
-
*
|
|
464
|
-
* The same operation as {@link placeViewer}, addressed the way another
|
|
465
|
-
* component may address it: by name. Encoding asks for this when a request
|
|
466
|
-
* for any file of an output is the first sign of the person behind it, and it
|
|
467
|
-
* must not be handed the viewer to do it — a viewer's record has one writer,
|
|
468
|
-
* and that is the viewer layer.
|
|
444
|
+
* Encoding asks for this when a request for any file of an output is the
|
|
445
|
+
* first sign of the person behind it. The operation takes the viewer's name
|
|
446
|
+
* and position; the viewer layer owns the record and its idempotency rule.
|
|
469
447
|
*
|
|
470
448
|
* @param {object} output
|
|
471
449
|
* @param {string} consumerId
|
|
472
450
|
* @param {number} positionSeconds
|
|
473
|
-
* @returns {
|
|
451
|
+
* @returns {boolean} Whether the viewer layer placed the viewer.
|
|
474
452
|
*/
|
|
475
453
|
placeViewerOn(output, consumerId, positionSeconds) {
|
|
476
454
|
if (!output || !consumerId) {
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
const viewer = this.#host.viewers.join(output, consumerId);
|
|
480
|
-
if (viewer) this.placeViewer(output, viewer, positionSeconds);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
placeViewer(session, viewer, positionSeconds) {
|
|
484
|
-
if (viewer.position !== null) {
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
const seconds = Number.isFinite(positionSeconds) && positionSeconds > 0 ? positionSeconds : 0;
|
|
488
|
-
let segment = 0;
|
|
489
|
-
try {
|
|
490
|
-
const index = this.#host.outputTimes.segmentIndexForTime(session, seconds);
|
|
491
|
-
if (Number.isInteger(index) && index >= 0) {
|
|
492
|
-
segment = index;
|
|
493
|
-
}
|
|
494
|
-
} catch {
|
|
495
|
-
// A session whose cut table is not built yet places its viewer at the
|
|
496
|
-
// beginning, which is where the run starts anyway.
|
|
455
|
+
return false;
|
|
497
456
|
}
|
|
498
|
-
|
|
499
|
-
this.#host.planEncodersSoon();
|
|
457
|
+
const placed = this.#host.placeViewerOn(output, consumerId, positionSeconds) === true;
|
|
458
|
+
if (placed) this.#host.planEncodersSoon();
|
|
459
|
+
return placed;
|
|
500
460
|
}
|
|
501
461
|
|
|
502
462
|
/**
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
noteStepBeingWarmed,
|
|
52
52
|
noteStepOnScreen,
|
|
53
53
|
outputsBeingPrepared,
|
|
54
|
+
placeInitially,
|
|
54
55
|
placeOn,
|
|
55
56
|
presentOn,
|
|
56
57
|
qualityModeOf,
|
|
@@ -682,8 +683,11 @@ export function wireOutputs({
|
|
|
682
683
|
return video + audio;
|
|
683
684
|
},
|
|
684
685
|
get opening() { return parts.opening; },
|
|
685
|
-
get outputTimes() { return parts.outputTimes; },
|
|
686
686
|
get outputs() { return parts.outputs; },
|
|
687
|
+
placeViewerOn: (output, consumerId, seconds, now) =>
|
|
688
|
+
placeInitially(parts.viewers, output, consumerId, seconds, now),
|
|
689
|
+
chooseAudioTrack: (output, consumerId, choice) =>
|
|
690
|
+
chooseAudioTrack(parts.viewers, output, consumerId, choice),
|
|
687
691
|
get lookaheadSeconds() { return parts.lookaheadSeconds; },
|
|
688
692
|
get quality() { return parts.quality; },
|
|
689
693
|
get qualityOffer() { return parts.qualityOffer; },
|
|
@@ -427,6 +427,22 @@ export class Viewer {
|
|
|
427
427
|
this.bufferedSeconds = 0;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Place this viewer at the position supplied by their first output opening.
|
|
432
|
+
* An opening that reuses an output must not reset a position already stated
|
|
433
|
+
* by this viewer. Initial placement has none of the buffer or pause effects
|
|
434
|
+
* of an explicit seek.
|
|
435
|
+
*
|
|
436
|
+
* @param {number} seconds
|
|
437
|
+
* @param {number} [now]
|
|
438
|
+
* @returns {boolean} Whether this call placed the viewer.
|
|
439
|
+
*/
|
|
440
|
+
placeInitially(seconds, now = Date.now()) {
|
|
441
|
+
if (this.position !== null) return false;
|
|
442
|
+
this.#place(Number.isFinite(seconds) && seconds > 0 ? seconds : 0, now);
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
|
|
430
446
|
/**
|
|
431
447
|
* Where they are, stated — without anything a move to another place means.
|
|
432
448
|
*
|
|
@@ -96,10 +96,26 @@ export function audioChoiceOf(viewers, output, consumerId) {
|
|
|
96
96
|
* @returns {void}
|
|
97
97
|
*/
|
|
98
98
|
export function chooseAudioTrack(viewers, output, consumerId, choice) {
|
|
99
|
+
if (!choice) return;
|
|
99
100
|
const viewer = viewers.join(output, consumerId);
|
|
100
101
|
if (viewer) viewer.audio = { trackIndex: choice.trackIndex, transcode: choice.transcode === true };
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Place a viewer at the initial position named by an output opening.
|
|
106
|
+
*
|
|
107
|
+
* @param {object} viewers
|
|
108
|
+
* @param {object} output
|
|
109
|
+
* @param {string} consumerId
|
|
110
|
+
* @param {number} seconds
|
|
111
|
+
* @param {number} [now]
|
|
112
|
+
* @returns {boolean} Whether this call placed the viewer.
|
|
113
|
+
*/
|
|
114
|
+
export function placeInitially(viewers, output, consumerId, seconds, now = Date.now()) {
|
|
115
|
+
const viewer = viewers.join(output, consumerId, now);
|
|
116
|
+
return viewer?.placeInitially(seconds, now) ?? false;
|
|
117
|
+
}
|
|
118
|
+
|
|
103
119
|
/**
|
|
104
120
|
* The step on this viewer's screen, as a session id, or null for the picture
|
|
105
121
|
* itself.
|