@torrent-tv/proxy 2.93.3 → 2.93.4

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.93.3",
3
+ "version": "2.93.4",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
package/server.js CHANGED
@@ -830,7 +830,7 @@ export async function startProxyServer({
830
830
  scope: "preparation", ...sourcePreparation.demandFor(work) });
831
831
  }
832
832
  }
833
- if (["packets", "subtitle-cues"].includes(work.statement) && (work.selected || work.role === "subtitle-embedded")) {
833
+ if ((work.statement === "packets" && work.role !== "source-rest") || work.role === "subtitle-embedded" && work.statement === "subtitle-cues") {
834
834
  const info = await containerOrchestrator.inspect({ ...params, onReadResult: undefined }, "media-info");
835
835
  if (info.kind !== "result") return info;
836
836
  const positions = outputParts.viewers.forSource(work.sourceKey)
@@ -54,6 +54,7 @@ const MICROSECONDS_PER_SECOND = 1_000_000;
54
54
  * the stretch it was given, which no other live run of that output holds.
55
55
  * @property {string} address
56
56
  * @property {string} ending - One of {@link ENCODE_EXIT}.
57
+ * @property {string | null} publicationCode - The closed-piece refusal category, separate from the process exit.
57
58
  * @property {string} because - Why, in words, including who asked when we did.
58
59
  * @property {number | null} code
59
60
  * @property {string | null} signal
@@ -108,6 +109,7 @@ export class EncodeRun {
108
109
  #pendingClosed = null;
109
110
  #closedTimings = new Map();
110
111
  #publicationError = null;
112
+ #publicationCode = null;
111
113
  #inputTruncated = false;
112
114
  #stderrReadTail = "";
113
115
  #processExited = false;
@@ -602,6 +604,7 @@ export class EncodeRun {
602
604
  served = this.onClosed(name, following, this.#closedTimings.get(name) ?? null);
603
605
  } catch (error) {
604
606
  this.#publicationError = error instanceof Error ? error.message : String(error);
607
+ this.#publicationCode = error?.code ?? null;
605
608
  this.lastError = this.#publicationError;
606
609
  // A refused closed piece must release this run's claim now, rather
607
610
  // than keep its viewer waiting until the rest of the film is encoded.
@@ -877,6 +880,7 @@ export class EncodeRun {
877
880
  run: this,
878
881
  address: this.address,
879
882
  ending,
883
+ publicationCode: this.#publicationCode,
880
884
  because,
881
885
  code: code ?? null,
882
886
  signal: signal ?? null,
@@ -395,6 +395,7 @@ export class EncodeRuns {
395
395
  return mediaRanges;
396
396
  } catch (error) {
397
397
  this.#host.logger.warn(`encode: could not read the media of ${name}: ${error instanceof Error ? error.message : String(error)}`);
398
+ if (/^E[A-Z]+$/.test(error?.code ?? "")) throw error;
398
399
  return false;
399
400
  }
400
401
  }
@@ -986,7 +987,8 @@ export class EncodeRuns {
986
987
  }
987
988
  }
988
989
  const mediaRanges = this.#wholeClosedPiece(session, name, index, admittedInput, bytes);
989
- if (mediaRanges === false) throw new Error(`Closed piece #${index} has incomplete media.`);
990
+ if (mediaRanges === false) throw Object.assign(new Error(`Closed piece #${index} has incomplete media.`),
991
+ { code: "ERR_INCOMPLETE_MEDIA" });
990
992
  const published = this.#host.segmentFiles.publish(session.outputKey ?? "", name, session.segmentFormat, { mediaRanges, bytes });
991
993
  if (!published) throw new Error(`Closed piece #${index} could not be stored.`);
992
994
  return published;
@@ -3,6 +3,9 @@ import { ENCODE_EXIT } from "./encode-exit.js";
3
3
 
4
4
  /** Process and resource failures are not evidence against the admitted bytes. */
5
5
  export function failedAdmittedInput(ended, hardwareEncode = false) {
6
+ if (ended.ending === ENCODE_EXIT.PUBLICATION_FAILED) {
7
+ return !hardwareEncode && ended.publicationCode === "ERR_INCOMPLETE_MEDIA";
8
+ }
6
9
  if (hardwareEncode || ended.signal || ended.code === null || ended.code === undefined) return false;
7
10
  if (!Number.isInteger(ended.code) || ended.code < 0) return false;
8
11
  if (/cannot allocate memory|out of memory|no space left|resource temporarily unavailable|too many open files|ENOMEM|ENOSPC|EMFILE|EAGAIN/i.test(ended.because ?? "")) return false;
@@ -430,6 +430,9 @@ export class ViewerRequests {
430
430
  // without this the base session would idle out from under its own variants.
431
431
  const session = this.#host.activeOutputFor({ base: named, consumerId, outputs: this.#host.outputs });
432
432
  this.#host.outputs.touch(session);
433
+ const audio = this.#host.renditions.servesAudioSeparately(session)
434
+ ? this.#host.renditions.playbackAudioOutputFor(session, consumerId) : null;
435
+ const failed = [session, audio].find(output => output && this.#host.encodeRuns.wireStateOf(output) === "failed");
433
436
  const warmupTotalSeconds = this.#host.startupWaitMs / 1000;
434
437
  const warmupElapsedSeconds = Math.max(
435
438
  0,
@@ -452,7 +455,7 @@ export class ViewerRequests {
452
455
  // The id the caller asked about, not the variant it was answered from —
453
456
  // the browser tracks its sessions by the id it was given.
454
457
  sessionId: named.id,
455
- state: this.#host.encodeRuns.wireStateOf(session),
458
+ state: failed ? "failed" : this.#host.encodeRuns.wireStateOf(session),
456
459
  // The smallest buffer at which no interruption reaches the viewer, from
457
460
  // THIS file's own recent interruptions: one whole segment — the one being
458
461
  // played — plus the worst wait that can arrive before the buffer refills.
@@ -537,7 +540,7 @@ export class ViewerRequests {
537
540
  expectedSessionCreateMs: this.#host.expectedSessionCreateMs(),
538
541
  expectedFirstSegmentMs: this.#host.expectedFirstSegmentMs(),
539
542
  updatedAt: progress.updatedAt,
540
- error: this.#host.encodeRuns.failureOf(session)
543
+ error: this.#host.encodeRuns.failureOf(failed ?? session)
541
544
  };
542
545
  }
543
546