@torrent-tv/proxy 2.107.24 → 2.107.26
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
|
@@ -1282,8 +1282,12 @@ export class ViewerRequests {
|
|
|
1282
1282
|
const ranges = inventory.has(index) ? this.#host.encodeRuns.finishedMediaRangesOf(output, index) : undefined;
|
|
1283
1283
|
const mediaRanges = ranges && output.segmentFormat?.servedMediaRanges ?
|
|
1284
1284
|
output.segmentFormat.servedMediaRanges(ranges, { initBytes: sessionInit }) : undefined;
|
|
1285
|
+
// The player can request a fragment whose media timestamps extend a few
|
|
1286
|
+
// frames past its nominal playlist end while seeking to the next piece.
|
|
1285
1287
|
if (index !== 0 && mediaRanges === undefined && !inventory.has(index) &&
|
|
1286
|
-
Number.isFinite(endSeconds) && Number.isFinite(positionSeconds) &&
|
|
1288
|
+
Number.isFinite(endSeconds) && Number.isFinite(positionSeconds) &&
|
|
1289
|
+
!this.#host.playbackReadiness.endsWithinPlayerSeekTolerance(endSeconds, positionSeconds) &&
|
|
1290
|
+
endSeconds < positionSeconds) {
|
|
1287
1291
|
continue;
|
|
1288
1292
|
}
|
|
1289
1293
|
const startSeconds = timeline.publishedStartOf(index);
|
|
@@ -72,7 +72,7 @@ import { ViewerRequests } from "./ViewerRequests.js";
|
|
|
72
72
|
import { OutputLifecycle } from "./OutputLifecycle.js";
|
|
73
73
|
import { SegmentServing } from "./SegmentServing.js";
|
|
74
74
|
import { audioStartSecondsFor } from "../viewer/audio-start.js";
|
|
75
|
-
import { forecastRate, rateSummaryOf, predictPlaybackReadiness, RateTrend } from "../viewer/playback-readiness.js";
|
|
75
|
+
import { endsWithinPlayerSeekTolerance, forecastRate, rateSummaryOf, predictPlaybackReadiness, RateTrend } from "../viewer/playback-readiness.js";
|
|
76
76
|
import { audioRenditionName } from "../media/audio-inventory.js";
|
|
77
77
|
import { Renditions } from "../encode/Renditions.js";
|
|
78
78
|
import { CushionReport, LOOKAHEAD_PAUSE_SECONDS } from "../encode/CushionReport.js";
|
|
@@ -640,7 +640,8 @@ export function wireOutputs({
|
|
|
640
640
|
get encodeRuns() { return parts.encodeRuns; },
|
|
641
641
|
// When this viewer's playback can start and run to the end: the viewer
|
|
642
642
|
// component's forecast, which models the viewer's browser.
|
|
643
|
-
playbackReadiness: { predict: predictPlaybackReadiness, forecastRate, rateSummaryOf, RateTrend
|
|
643
|
+
playbackReadiness: { predict: predictPlaybackReadiness, forecastRate, rateSummaryOf, RateTrend,
|
|
644
|
+
endsWithinPlayerSeekTolerance },
|
|
644
645
|
// Whether the subtitle a viewer chose has been read where they stand — the
|
|
645
646
|
// source preparation's answer, set on these parts by the assembly.
|
|
646
647
|
subtitleReadyFor: (viewer) => parts.subtitleReadyFor?.(viewer) ?? true,
|
|
@@ -38,9 +38,20 @@ import {
|
|
|
38
38
|
ZERO
|
|
39
39
|
} from "./media-time.js";
|
|
40
40
|
|
|
41
|
-
// Match the media element's allowance
|
|
42
|
-
//
|
|
43
|
-
const
|
|
41
|
+
// Match the media element's allowance around a seek target. A fragment's
|
|
42
|
+
// timestamps can extend slightly beyond its nominal playlist boundary.
|
|
43
|
+
export const PLAYER_SEEK_TOLERANCE_SECONDS = 0.25;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {number} segmentEndSeconds
|
|
47
|
+
* @param {number} positionSeconds
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
export function endsWithinPlayerSeekTolerance(segmentEndSeconds, positionSeconds) {
|
|
51
|
+
return Number.isFinite(segmentEndSeconds) && Number.isFinite(positionSeconds) &&
|
|
52
|
+
segmentEndSeconds <= positionSeconds &&
|
|
53
|
+
positionSeconds - segmentEndSeconds <= PLAYER_SEEK_TOLERANCE_SECONDS;
|
|
54
|
+
}
|
|
44
55
|
|
|
45
56
|
/**
|
|
46
57
|
* The mean rate predicted over a horizon by the integral of the measured rate.
|
|
@@ -223,7 +234,8 @@ export function predictPlaybackReadiness(input = {}) {
|
|
|
223
234
|
bitsPerMediaSecond: averageBitsPerMediaSecond(track, track.segments,
|
|
224
235
|
new Set(Array.isArray(track.readySegmentIndices) ? track.readySegmentIndices : [])),
|
|
225
236
|
segments: segmentsOf[trackIndex]
|
|
226
|
-
.filter((segment) => isPiece(segment) &&
|
|
237
|
+
.filter((segment) => isPiece(segment) &&
|
|
238
|
+
segment.endSeconds >= position - PLAYER_SEEK_TOLERANCE_SECONDS && segment.startSeconds < horizonEnd)
|
|
227
239
|
.sort((left, right) => left.startSeconds - right.startSeconds || left.index - right.index),
|
|
228
240
|
// The pieces after the near window, as the playlist cuts them, and the
|
|
229
241
|
// offset the page's player placed them by.
|
|
@@ -290,9 +302,12 @@ export function predictPlaybackReadiness(input = {}) {
|
|
|
290
302
|
for (const segment of segments) {
|
|
291
303
|
// Media the page already holds is not transferred again: every range of
|
|
292
304
|
// the piece still ahead of the viewer lies inside what the page holds.
|
|
305
|
+
const boundaryPrerequisite = endsWithinPlayerSeekTolerance(segment.endSeconds, position);
|
|
293
306
|
let held = segment.ranges.length > 0;
|
|
294
307
|
for (const range of segment.ranges) {
|
|
295
|
-
|
|
308
|
+
const requiredStart = boundaryPrerequisite ? range.start : latest(range.start, at);
|
|
309
|
+
if ((boundaryPrerequisite || compare(range.end, at) > 0) &&
|
|
310
|
+
!contains(state.clientRanges, requiredStart, range.end)) {
|
|
296
311
|
held = false;
|
|
297
312
|
break;
|
|
298
313
|
}
|
|
@@ -840,7 +855,7 @@ function heldRanges(ranges, segments, unit, position) {
|
|
|
840
855
|
const pieces = segments.flatMap((segment) => segment.ranges ?? []);
|
|
841
856
|
const zero = mediaTime(0n, unit);
|
|
842
857
|
const error = rescale(REPORTED_TIME_ERROR, unit);
|
|
843
|
-
const startTolerance = add(position, rescale(fromSeconds(
|
|
858
|
+
const startTolerance = add(position, rescale(fromSeconds(PLAYER_SEEK_TOLERANCE_SECONDS), unit));
|
|
844
859
|
const held = [];
|
|
845
860
|
for (const range of ranges) {
|
|
846
861
|
const reportedStart = rescale(range.start, unit);
|
|
@@ -867,7 +882,7 @@ function heldRanges(ranges, segments, unit, position) {
|
|
|
867
882
|
function withSeekStartTolerance(ranges, position, unit) {
|
|
868
883
|
const first = ranges.reduce((earliestRange, range) =>
|
|
869
884
|
!earliestRange || compare(range.start, earliestRange.start) < 0 ? range : earliestRange, null);
|
|
870
|
-
const toleranceEnd = add(position, rescale(fromSeconds(
|
|
885
|
+
const toleranceEnd = add(position, rescale(fromSeconds(PLAYER_SEEK_TOLERANCE_SECONDS), unit));
|
|
871
886
|
if (!first || compare(first.start, position) <= 0 || compare(first.start, toleranceEnd) > 0) {
|
|
872
887
|
return ranges;
|
|
873
888
|
}
|
|
@@ -876,8 +891,11 @@ function withSeekStartTolerance(ranges, position, unit) {
|
|
|
876
891
|
|
|
877
892
|
/**
|
|
878
893
|
* The pieces of a track this forecast places in exact time: those still to
|
|
879
|
-
* play (ending
|
|
880
|
-
* piece, every piece that has been read and
|
|
894
|
+
* play (ending within the player's seek tolerance of `position`) that start
|
|
895
|
+
* before `horizonEnd`, the first piece, every piece that has been read and
|
|
896
|
+
* every piece that is made. A piece ending just before a seek target is kept
|
|
897
|
+
* as a prerequisite because its media timestamps can extend past its nominal
|
|
898
|
+
* playlist boundary. A piece
|
|
881
899
|
* that is none of these changes no exact answer: after the near window it is
|
|
882
900
|
* scheduled in seconds, it is not where the track starts, no unread piece is
|
|
883
901
|
* placed by it (only read pieces are), it lends no frame to what the page
|
|
@@ -891,7 +909,8 @@ function withSeekStartTolerance(ranges, position, unit) {
|
|
|
891
909
|
function piecesThatMatter(track, position, horizonEnd = Number.POSITIVE_INFINITY) {
|
|
892
910
|
const made = new Set(Array.isArray(track.readySegmentIndices) ? track.readySegmentIndices : []);
|
|
893
911
|
const kept = track.segments.filter((segment) => segment?.index === 0 || segment?.mediaRanges !== undefined ||
|
|
894
|
-
made.has(segment?.index) || (!(Number.isFinite(segment?.endSeconds) &&
|
|
912
|
+
made.has(segment?.index) || (!(Number.isFinite(segment?.endSeconds) &&
|
|
913
|
+
segment.endSeconds < position - PLAYER_SEEK_TOLERANCE_SECONDS) &&
|
|
895
914
|
!(Number.isFinite(segment?.startSeconds) && segment.startSeconds >= horizonEnd)));
|
|
896
915
|
return kept.length === track.segments.length ? track.segments : kept;
|
|
897
916
|
}
|