@torrent-tv/proxy 2.107.21 → 2.107.23
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
|
@@ -187,9 +187,12 @@ export class EncodeRun {
|
|
|
187
187
|
/** The film made and the run's own working time, as of the last progress report. */
|
|
188
188
|
#workSample = null;
|
|
189
189
|
|
|
190
|
-
/**
|
|
190
|
+
/** Baseline work sample for this run's next speed reading. */
|
|
191
191
|
#pieceSample = null;
|
|
192
192
|
|
|
193
|
+
/** A closed, published piece is waiting for a usable progress sample. */
|
|
194
|
+
#speedMeasurementPending = false;
|
|
195
|
+
|
|
193
196
|
/** @type {{ speed: number, at: number } | null} */
|
|
194
197
|
#speedReading = null;
|
|
195
198
|
|
|
@@ -302,6 +305,7 @@ export class EncodeRun {
|
|
|
302
305
|
this.progress = new RunProgress({ startSeconds, totalSeconds, now: this.now });
|
|
303
306
|
/** Where this run's time went: its own work, or waiting, or stopped. */
|
|
304
307
|
this.clock = new RunClock({ now: this.now });
|
|
308
|
+
this.#pieceSample = { at: this.now(), producedSeconds: 0, workingMs: 0 };
|
|
305
309
|
this.onEnded = typeof onEnded === "function" ? onEnded : () => {};
|
|
306
310
|
this.onProgress = typeof onProgress === "function" ? onProgress : () => {};
|
|
307
311
|
this.onProduced = typeof onProduced === "function" ? onProduced : () => {};
|
|
@@ -338,9 +342,9 @@ export class EncodeRun {
|
|
|
338
342
|
}
|
|
339
343
|
|
|
340
344
|
/**
|
|
341
|
-
* This run's processing speed: film made over its own working time
|
|
342
|
-
*
|
|
343
|
-
*
|
|
345
|
+
* This run's processing speed: film made over its own working time since the
|
|
346
|
+
* last baseline, with the time its input waited and the time it was stopped
|
|
347
|
+
* taken out (`RunClock`). Zero until a closed piece has enough progress data.
|
|
344
348
|
*
|
|
345
349
|
* @returns {number}
|
|
346
350
|
*/
|
|
@@ -349,8 +353,8 @@ export class EncodeRun {
|
|
|
349
353
|
}
|
|
350
354
|
|
|
351
355
|
/**
|
|
352
|
-
* The same speed with the moment it was measured, or null before a
|
|
353
|
-
* piece has
|
|
356
|
+
* The same speed with the moment it was measured, or null before a closed
|
|
357
|
+
* piece has enough progress data.
|
|
354
358
|
*
|
|
355
359
|
* @returns {{ speed: number, at: number } | null}
|
|
356
360
|
*/
|
|
@@ -452,6 +456,16 @@ export class EncodeRun {
|
|
|
452
456
|
/** An input read of this run has its bytes. */
|
|
453
457
|
inputWaitEnds() {
|
|
454
458
|
this.clock.inputWaitEnds();
|
|
459
|
+
if (this.#speedReading === null && this.#workSample !== null) {
|
|
460
|
+
// Progress made while an input read was waiting belongs to the wait, not
|
|
461
|
+
// to the encoder's rate. Start the first measurement from the latest
|
|
462
|
+
// progress known when the input resumes.
|
|
463
|
+
this.#pieceSample = {
|
|
464
|
+
...this.#workSample,
|
|
465
|
+
at: this.now(),
|
|
466
|
+
workingMs: this.clock.workingMs()
|
|
467
|
+
};
|
|
468
|
+
}
|
|
455
469
|
}
|
|
456
470
|
|
|
457
471
|
/** @returns {boolean} Whether an input read of this run is waiting for bytes now. */
|
|
@@ -589,12 +603,7 @@ export class EncodeRun {
|
|
|
589
603
|
producedSeconds: Math.max(0, this.progress.processedSeconds - this.progress.startPositionSeconds),
|
|
590
604
|
workingMs: this.clock.workingMs(at)
|
|
591
605
|
};
|
|
592
|
-
|
|
593
|
-
// on the first media progress report so closing that segment yields a
|
|
594
|
-
// processing rate without counting the preceding input wait.
|
|
595
|
-
if (this.#pieceSample === null && this.#workSample.producedSeconds > 0) {
|
|
596
|
-
this.#pieceSample = this.#workSample;
|
|
597
|
-
}
|
|
606
|
+
if (this.#speedMeasurementPending) this.#measureSpeed();
|
|
598
607
|
}
|
|
599
608
|
this.onProgress(this.progress.snapshot());
|
|
600
609
|
}
|
|
@@ -688,7 +697,6 @@ export class EncodeRun {
|
|
|
688
697
|
}
|
|
689
698
|
|
|
690
699
|
#publishClosed(name, following = null, { quiet = false, tentative = false } = {}) {
|
|
691
|
-
if (!tentative) this.#measureSpeed();
|
|
692
700
|
// ITS SERVED NAME, which is what whoever owns the disk gives it in answer.
|
|
693
701
|
// ffmpeg writes a piece under a working name and reports that; the piece
|
|
694
702
|
// becomes servable by being renamed, and everything below works in the
|
|
@@ -724,7 +732,8 @@ export class EncodeRun {
|
|
|
724
732
|
}
|
|
725
733
|
|
|
726
734
|
if (!served) return false;
|
|
727
|
-
|
|
735
|
+
this.#speedMeasurementPending = true;
|
|
736
|
+
this.#measureSpeed();
|
|
728
737
|
if (!this.#stopping) {
|
|
729
738
|
this.#provenName = served;
|
|
730
739
|
}
|
|
@@ -744,25 +753,22 @@ export class EncodeRun {
|
|
|
744
753
|
}
|
|
745
754
|
|
|
746
755
|
/**
|
|
747
|
-
* A
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
*
|
|
756
|
+
* A published piece is measured against this run's last baseline over its
|
|
757
|
+
* own working time. The initial baseline is the run start, advanced to the
|
|
758
|
+
* latest known progress when input resumes, so a one-piece run can be
|
|
759
|
+
* measured even when FFmpeg reports progress only once. Input waits remain
|
|
760
|
+
* excluded by RunClock.
|
|
752
761
|
*/
|
|
753
762
|
#measureSpeed() {
|
|
754
763
|
const sample = this.#workSample;
|
|
755
764
|
if (sample === null) {
|
|
756
765
|
return;
|
|
757
766
|
}
|
|
758
|
-
if (this.#pieceSample === null) {
|
|
759
|
-
if (sample.producedSeconds > 0) this.#pieceSample = sample;
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
767
|
const speed = speedFromWork(this.#pieceSample, sample);
|
|
763
768
|
if (speed !== null) {
|
|
764
769
|
this.#speedReading = { speed, at: sample.at };
|
|
765
770
|
this.#pieceSample = sample;
|
|
771
|
+
this.#speedMeasurementPending = false;
|
|
766
772
|
this.onSpeedMeasured(this.speedReading);
|
|
767
773
|
}
|
|
768
774
|
}
|
|
@@ -552,7 +552,9 @@ export function predictPlaybackReadiness(input = {}) {
|
|
|
552
552
|
let after = contiguousEnd(delivered, at);
|
|
553
553
|
for (const completion of completions.filter((item) => item.trackIndex === trackIndex)) {
|
|
554
554
|
const before = after;
|
|
555
|
-
|
|
555
|
+
const ranges = compare(before, at) === 0
|
|
556
|
+
? withSeekStartTolerance(completion.segment.ranges, at, unit) : completion.segment.ranges;
|
|
557
|
+
for (const range of ranges) addMediaRange(delivered, range);
|
|
556
558
|
after = contiguousEnd(delivered, at);
|
|
557
559
|
const ahead = secondsAhead(earliest(before, trackEnd), at);
|
|
558
560
|
constrain(completion.at - ahead, "delivery", trackIndex, completion.segment.index, completion.at, ahead, false,
|
|
@@ -581,7 +583,9 @@ export function predictPlaybackReadiness(input = {}) {
|
|
|
581
583
|
}
|
|
582
584
|
for (const production of productions.filter((item) => item.trackIndex === trackIndex)) {
|
|
583
585
|
const before = contiguousEnd(prepared, at);
|
|
584
|
-
|
|
586
|
+
const ranges = compare(before, at) === 0
|
|
587
|
+
? withSeekStartTolerance(production.segment.ranges, at, unit) : production.segment.ranges;
|
|
588
|
+
for (const range of ranges) addMediaRange(prepared, range);
|
|
585
589
|
// Supply interruption coverage is stock held by the proxy as well as
|
|
586
590
|
// the browser. It is not a browser buffer-size admission rule.
|
|
587
591
|
// The reserve is bounded by what is left of the track, not of the window.
|
|
@@ -851,6 +855,25 @@ function heldRanges(ranges, segments, unit, position) {
|
|
|
851
855
|
return held;
|
|
852
856
|
}
|
|
853
857
|
|
|
858
|
+
/**
|
|
859
|
+
* Include the first arriving range when its start is within the media
|
|
860
|
+
* element's allowance for a seek target. This does not bridge later gaps.
|
|
861
|
+
*
|
|
862
|
+
* @param {import("./media-time.js").MediaRange[]} ranges
|
|
863
|
+
* @param {import("./media-time.js").MediaTime} position
|
|
864
|
+
* @param {bigint} unit
|
|
865
|
+
* @returns {import("./media-time.js").MediaRange[]}
|
|
866
|
+
*/
|
|
867
|
+
function withSeekStartTolerance(ranges, position, unit) {
|
|
868
|
+
const first = ranges.reduce((earliestRange, range) =>
|
|
869
|
+
!earliestRange || compare(range.start, earliestRange.start) < 0 ? range : earliestRange, null);
|
|
870
|
+
const toleranceEnd = add(position, rescale(fromSeconds(CLIENT_RANGE_START_TOLERANCE_SECONDS), unit));
|
|
871
|
+
if (!first || compare(first.start, position) <= 0 || compare(first.start, toleranceEnd) > 0) {
|
|
872
|
+
return ranges;
|
|
873
|
+
}
|
|
874
|
+
return ranges.map((range) => range === first ? { ...range, start: position } : range);
|
|
875
|
+
}
|
|
876
|
+
|
|
854
877
|
/**
|
|
855
878
|
* The pieces of a track this forecast places in exact time: those still to
|
|
856
879
|
* play (ending after `position`) that start before `horizonEnd`, the first
|