@torrent-tv/proxy 2.53.0 → 2.54.0

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.
@@ -118,16 +118,59 @@ export function nominalKbpsForHeight(height) {
118
118
  return best[1];
119
119
  }
120
120
 
121
+ /**
122
+ * The peak this encode may reach, in kbit/s, for a nominal rate.
123
+ *
124
+ * Exported because the same figure answers a second question: whether a rung
125
+ * fits the viewer's measured link. The budget compares the link against what
126
+ * the encode is ALLOWED to peak at rather than against what it happened to
127
+ * produce in the last few segments, so a rung is judged by the bound we impose
128
+ * on it and not by a quiet stretch of the film.
129
+ *
130
+ * @param {number} nominalKbps
131
+ * @returns {number}
132
+ */
133
+ export function maxrateKbpsFor(nominalKbps) {
134
+ return Math.round(nominalKbps * CAP_MAXRATE_FACTOR);
135
+ }
136
+
137
+ /**
138
+ * The nominal rate whose cap is a given peak — the inverse of
139
+ * {@link maxrateKbpsFor}.
140
+ *
141
+ * Used to turn a MEASURED limit into the figure the cap arithmetic takes. The
142
+ * viewer's usable link is a peak the stream must not exceed, and the encoder is
143
+ * configured from a nominal rate, so the two are converted through the one
144
+ * factor rather than through a second constant invented for the purpose.
145
+ *
146
+ * @param {number} maxrateKbps
147
+ * @returns {number}
148
+ */
149
+ export function nominalKbpsForMaxrate(maxrateKbps) {
150
+ return Math.round(maxrateKbps / CAP_MAXRATE_FACTOR);
151
+ }
152
+
121
153
  /**
122
154
  * `-maxrate`/`-bufsize` args for an encode height (constrained CRF).
123
155
  *
156
+ * `nominalKbps` overrides the height's own nominal rate. It is how a measured
157
+ * limit — the viewer's link, the only figure that bounds an encode from
158
+ * outside this host — reaches the encoder without touching the picture's SIZE.
159
+ * That distinction is the whole point: `-maxrate`, `-bufsize` and CRF do not
160
+ * appear in the SPS (x264 writes no HRD parameters by default), so they can be
161
+ * moved in the middle of a session while one init segment goes on describing
162
+ * every fragment. The size cannot.
163
+ *
124
164
  * @param {number} height
165
+ * @param {number | null} [nominalKbps=null]
125
166
  * @returns {string[]}
126
167
  */
127
- function bitrateCapArgs(height) {
128
- const nominal = nominalKbpsForHeight(height);
168
+ function bitrateCapArgs(height, nominalKbps = null) {
169
+ const nominal = Number.isFinite(nominalKbps) && nominalKbps > 0
170
+ ? nominalKbps
171
+ : nominalKbpsForHeight(height);
129
172
  return [
130
- "-maxrate", `${Math.round(nominal * CAP_MAXRATE_FACTOR)}k`,
173
+ "-maxrate", `${maxrateKbpsFor(nominal)}k`,
131
174
  "-bufsize", `${Math.round(nominal * CAP_BUFSIZE_FACTOR)}k`
132
175
  ];
133
176
  }
@@ -221,7 +264,7 @@ export function softwareDescriptor() {
221
264
  kind: "software",
222
265
  device: null,
223
266
  inputArgs: [],
224
- buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, preset, fps, tonemap, forcedKeyframeTimes }) {
267
+ buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, preset, fps, tonemap, forcedKeyframeTimes, nominalKbps = null }) {
225
268
  const { w, h } = safeDimensions(targetWidth, targetHeight);
226
269
  const chosenPreset = typeof preset === "string" && preset.length > 0 ? preset : SOFTWARE_PRESET;
227
270
  // Output frame rate: inherited from the source (rounded/capped) by the
@@ -249,7 +292,7 @@ export function softwareDescriptor() {
249
292
  // cannot produce segments a thin viewer link (cellular) can't
250
293
  // download in time. Sized by the TARGET box height (the rung the
251
294
  // budget/manual selection chose).
252
- ...bitrateCapArgs(h),
295
+ ...bitrateCapArgs(h, nominalKbps),
253
296
  "-threads", String(CPU_THREADS),
254
297
  "-pix_fmt", "yuv420p",
255
298
  // Fixed GOP: a keyframe exactly every (segmentDurationSec × fps) frames,
@@ -396,7 +439,7 @@ function v4l2m2mDescriptor() {
396
439
  * @property {"software"|"vaapi"|"qsv"|"nvenc"|"v4l2m2m"} kind
397
440
  * @property {string|null} device
398
441
  * @property {string[]} inputArgs
399
- * @property {(opts: { targetWidth: number, targetHeight: number, segmentDurationSec: number, preset?: string, fps?: number, tonemap?: boolean, forcedKeyframeTimes?: number[] | null }) => string[]} buildVideoArgs
442
+ * @property {(opts: { targetWidth: number, targetHeight: number, segmentDurationSec: number, preset?: string, fps?: number, tonemap?: boolean, forcedKeyframeTimes?: number[] | null, nominalKbps?: number | null }) => string[]} buildVideoArgs
400
443
  */
401
444
 
402
445
  /**