@torrent-tv/proxy 2.9.63 → 2.9.64

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 CHANGED
@@ -1,3 +1,7 @@
1
+ ## 2.9.64
2
+
3
+ - **Fix**: The 2.9.63 pull-to-lowest-awaited-segment dragged the encoder to the start of the file. A seek to #1354 restarted at **#123** — the position of the *previous* watch — because requests outstanding from before the seek still counted toward `lowestAwaitedIndex`. Two fixes: the awaited floor is cleared the moment a new seek arrives (earlier requests describe where the player used to be, not where it is going), and the pull is bounded by `SEEK_PULL_LIMIT_SEGMENTS` (120) below the target — anything deeper is a leftover, not the preceding keyframe.
4
+
1
5
  ## 2.9.63
2
6
 
3
7
  - **Fix**: A seek landed the encoder on exactly the requested segment, which is the one position the player never asks for — so it produced files nobody was waiting for and playback hung. Per Apple HLS authoring guidance, a player given a position locates the nearest keyframe **preceding** it, decodes from there, and only then presents from the requested point; it therefore always fetches segments **below** the target. Measured on iOS: a seek to #1082 fetched from #1074 (8 back), one to #1358 fetched from #1301 (57 back) and asked for **nothing at or above** the target. The encoder now starts `SEEK_BACKOFF_SEGMENTS` (12) before the requested segment, and — since the needed depth varies and no fixed number covers it — is pulled down further to the lowest segment the player is actually waiting on, which its own requests report exactly (`lowestAwaitedIndex`). Only ever moves the start earlier, never later. Costs a few seconds of extra encoding per seek.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.9.63",
3
+ "version": "2.9.64",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "publishConfig": {
@@ -85,6 +85,13 @@ const ENCODER_STALL_MS = 12_000;
85
85
  // player is actually waiting on when that is lower still. Costs a few seconds
86
86
  // of extra encoding per seek.
87
87
  const SEEK_BACKOFF_SEGMENTS = 12;
88
+ // Hard limit on how far below the requested segment the start may be pulled by
89
+ // `lowestAwaitedIndex`. Without it a stale request from earlier playback drags
90
+ // the encoder across the whole file: field 2026-08-02, a seek to #1354 was
91
+ // pulled to #123 — the start of the previous watch — because requests from
92
+ // before the seek were still counted. Anything deeper than this is not the
93
+ // preceding keyframe, it is a leftover.
94
+ const SEEK_PULL_LIMIT_SEGMENTS = 120;
88
95
  const SEEK_SETTLE_MS = 1_200;
89
96
  // Hard cap on the total settle wait, measured from the first far request of a
90
97
  // burst, so a still-moving scrubber cannot delay a genuine seek forever.
@@ -2063,6 +2070,10 @@ export class HlsSessionManager {
2063
2070
  // player needs a segment containing the preceding keyframe, so one that
2064
2071
  // begins exactly at the target is useless to it.
2065
2072
  const startIndex = Math.max(0, index - SEEK_BACKOFF_SEGMENTS);
2073
+ // A new seek invalidates everything the player was waiting for before it:
2074
+ // those requests describe where it USED to be. Clearing here is what keeps
2075
+ // the pull below anchored to this seek.
2076
+ session.lowestAwaitedIndex = -1;
2066
2077
  logger.info(
2067
2078
  `transcode ${session.id} viewer seek to ${positionSeconds.toFixed(1)}s → segment #${index}, ` +
2068
2079
  `starting at #${startIndex} (${SEEK_BACKOFF_SEGMENTS} back for the preceding keyframe)`
@@ -2168,7 +2179,8 @@ export class HlsSessionManager {
2168
2179
  // requests say exactly how far back it needs the keyframe, so honour that
2169
2180
  // rather than a guess. Only ever pulls the start EARLIER, never later.
2170
2181
  const awaited = session.lowestAwaitedIndex;
2171
- const effectiveTarget = awaited >= 0 && awaited < target ? awaited : target;
2182
+ const pullFloor = Math.max(0, target - SEEK_PULL_LIMIT_SEGMENTS);
2183
+ const effectiveTarget = awaited >= pullFloor && awaited < target ? awaited : target;
2172
2184
  if (effectiveTarget !== target) {
2173
2185
  logger.info(
2174
2186
  `transcode ${session.id} pulling encode start #${target} → #${effectiveTarget} ` +