@torrent-tv/proxy 2.101.39 → 2.101.40

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.101.39",
3
+ "version": "2.101.40",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
@@ -999,8 +999,13 @@ export class ViewerRequests {
999
999
  } });
1000
1000
  if (waitEstimate) forecast.waitEstimate = waitEstimate;
1001
1001
  }
1002
- if (measurement.forecastReason !== forecast.reason) {
1002
+ const unavailableInput = forecast.unavailableSource;
1003
+ const forecastInputKey = unavailableInput ? JSON.stringify([
1004
+ unavailableInput.sourceId, unavailableInput.trackId, unavailableInput.segmentIndex, unavailableInput.phase
1005
+ ]) : null;
1006
+ if (measurement.forecastReason !== forecast.reason || measurement.forecastInputKey !== forecastInputKey) {
1003
1007
  measurement.forecastReason = forecast.reason;
1008
+ measurement.forecastInputKey = forecastInputKey;
1004
1009
  logger.info(`playback readiness ${session.id} consumer=${consumerId} ${JSON.stringify({
1005
1010
  ...forecast,
1006
1011
  positionSeconds,
@@ -258,6 +258,7 @@ export function predictPlaybackReadiness(input = {}) {
258
258
  }
259
259
  const link = rateCurve(input.linkReadings, now);
260
260
  let unknownReason = null;
261
+ let unavailableSource = null;
261
262
  if (!link) {
262
263
  return result(false, null, buffered, reserve, null, "link-rate-unavailable", 0);
263
264
  }
@@ -323,7 +324,10 @@ export function predictPlaybackReadiness(input = {}) {
323
324
  } else if (source.source.complete !== true) {
324
325
  const ranges = exactInputs ? inputRangesOf(exactInputs, sourceId) : null;
325
326
  if (ranges === null) {
326
- unknownReason ??= "source-input-ranges-unavailable";
327
+ if (unknownReason === null) {
328
+ unknownReason = "source-input-ranges-unavailable";
329
+ unavailableSource = { sourceId, trackId: track.id, segmentIndex: segment.index, phase: "near" };
330
+ }
327
331
  } else {
328
332
  if (sourceByteIntervals === NO_SOURCE_BYTES) sourceByteIntervals = new Map();
329
333
  sourceByteIntervals.set(sourceId, ranges);
@@ -348,7 +352,8 @@ export function predictPlaybackReadiness(input = {}) {
348
352
  }
349
353
 
350
354
  if (unknownReason) {
351
- return result(false, null, buffered, reserve, null, unknownReason, preparedSegments);
355
+ return { ...result(false, null, buffered, reserve, null, unknownReason, preparedSegments),
356
+ ...(unavailableSource ? { unavailableSource } : {}) };
352
357
  }
353
358
  for (const { track, curve } of trackState) {
354
359
  if (jobs.some((job) => job.track === track && !job.produced) && !curve) {
@@ -671,7 +676,8 @@ function scheduleTail({ trackState, sourceState, sourceByteCoverage, sourceArriv
671
676
  if (!source) return { reason: "source-measurement-unavailable" };
672
677
  if (source.source.complete === true) continue;
673
678
  const ranges = exactInputs ? inputRangesOf(exactInputs, sourceId) : null;
674
- if (ranges === null) return { reason: "source-input-ranges-unavailable" };
679
+ if (ranges === null) return { reason: "source-input-ranges-unavailable",
680
+ unavailableSource: { sourceId, trackId: track.id, segmentIndex: segment.index, phase: "tail" } };
675
681
  const bytes = supplyOf(sourceId);
676
682
  let order = 0;
677
683
  for (const range of ranges) {