@torrent-tv/proxy 2.107.55 → 2.107.56
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
|
@@ -108,7 +108,7 @@ function sourceCaptureOf(stats, actionId, generation) {
|
|
|
108
108
|
return { ...source, actionId: actionId ?? null, generation: Number.isSafeInteger(generation) ? generation : null };
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
function encoderCaptureOf(sampleCaptures, liveRuns, actionId, generation) {
|
|
111
|
+
export function encoderCaptureOf(sampleCaptures, liveRuns, actionId, generation) {
|
|
112
112
|
const runCaptures = (liveRuns ?? []).map(run => ({ owner: "proxy-encoder", clock: "performance",
|
|
113
113
|
clockEpoch: run.progress?.clockEpoch, startedAt: run.progress?.updatedAtMonotonic,
|
|
114
114
|
completedAt: run.progress?.updatedAtMonotonic, revision: run.progress?.updatedAtMonotonic,
|
|
@@ -117,19 +117,56 @@ function encoderCaptureOf(sampleCaptures, liveRuns, actionId, generation) {
|
|
|
117
117
|
Number.isFinite(run.progress?.updatedAtMonotonic) ? null : "encoder-progress-capture-unavailable" }));
|
|
118
118
|
const captures = [...(Array.isArray(sampleCaptures) ? sampleCaptures : []), ...runCaptures];
|
|
119
119
|
const epoch = captures[0]?.clockEpoch;
|
|
120
|
-
const
|
|
121
|
-
|
|
120
|
+
const samplesOrdered = (Array.isArray(sampleCaptures) ? sampleCaptures : []).every((capture, index, samples) =>
|
|
121
|
+
index === 0 || capture.revision >= samples[index - 1].revision);
|
|
122
|
+
const valid = captures.length > 0 && samplesOrdered && epoch === performance.timeOrigin && captures.every(capture =>
|
|
123
|
+
capture.owner === "proxy-encoder" && capture.clock === "performance" && capture.validity === "valid" &&
|
|
122
124
|
Number.isFinite(capture.clockEpoch) && capture.clockEpoch === epoch && Number.isFinite(capture.startedAt) &&
|
|
123
125
|
Number.isFinite(capture.completedAt) && capture.completedAt >= capture.startedAt &&
|
|
124
126
|
Number.isFinite(capture.revision));
|
|
125
|
-
if (!valid)
|
|
127
|
+
if (!valid) {
|
|
128
|
+
const projected = captures.find(capture => capture.provenance === "projected");
|
|
129
|
+
return { ...unknownCapture("proxy-encoder", actionId, generation,
|
|
130
|
+
projected?.unknownReason ?? "encoder-capture-unavailable"),
|
|
131
|
+
samples: captures, ...(projected ? { provenance: projected.provenance, projectionSource: projected.source } : {}) };
|
|
132
|
+
}
|
|
126
133
|
return { owner: "proxy-encoder", clock: "performance", clockEpoch: epoch,
|
|
127
134
|
startedAt: Math.min(...captures.map(capture => capture.startedAt)),
|
|
128
135
|
completedAt: Math.max(...captures.map(capture => capture.completedAt)), actionId: actionId ?? null,
|
|
129
|
-
generation: Number.isSafeInteger(generation) ? generation : null,
|
|
136
|
+
generation: Number.isSafeInteger(generation) ? generation : null, provenance: "measured",
|
|
130
137
|
revision: captures.at(-1).revision ?? null, samples: captures, validity: "valid", unknownReason: null };
|
|
131
138
|
}
|
|
132
139
|
|
|
140
|
+
export function trackRateReadings(readings, { predicted, projected }, now, playbackReadiness) {
|
|
141
|
+
const measured = (readings ?? []).filter(reading => reading.at <= now);
|
|
142
|
+
const summary = measured.length > 0 ? playbackReadiness.rateSummaryOf(measured) : null;
|
|
143
|
+
if (summary) return { summary, captures: measured.map(reading => ({ owner: reading.captureOwner,
|
|
144
|
+
clock: reading.captureClock, clockEpoch: reading.captureClockEpoch,
|
|
145
|
+
startedAt: reading.captureStartedAtMonotonic, completedAt: reading.captureCompletedAtMonotonic,
|
|
146
|
+
revision: reading.at,
|
|
147
|
+
validity: reading.captureOwner === "proxy-encoder" && reading.captureClock === "performance" &&
|
|
148
|
+
Number.isFinite(reading.captureClockEpoch) && Number.isFinite(reading.captureStartedAtMonotonic) &&
|
|
149
|
+
Number.isFinite(reading.captureCompletedAtMonotonic) && Number.isFinite(reading.at) &&
|
|
150
|
+
reading.captureCompletedAtMonotonic >= reading.captureStartedAtMonotonic
|
|
151
|
+
? "valid" : "unknown",
|
|
152
|
+
unknownReason: reading.captureOwner === "proxy-encoder" && reading.captureClock === "performance" &&
|
|
153
|
+
Number.isFinite(reading.captureClockEpoch) && Number.isFinite(reading.captureStartedAtMonotonic) &&
|
|
154
|
+
Number.isFinite(reading.captureCompletedAtMonotonic) && Number.isFinite(reading.at) &&
|
|
155
|
+
reading.captureCompletedAtMonotonic >= reading.captureStartedAtMonotonic
|
|
156
|
+
? null : "encoder-sample-capture-unavailable" })) };
|
|
157
|
+
const rate = Number(predicted ?? projected);
|
|
158
|
+
if (Number.isFinite(rate) && rate > 0) {
|
|
159
|
+
const seed = new playbackReadiness.RateTrend();
|
|
160
|
+
seed.add(now, rate);
|
|
161
|
+
const source = predicted === null || predicted === undefined
|
|
162
|
+
? "current-cost-projection" : "stored-encode-prediction";
|
|
163
|
+
return { summary: seed.snapshot(), captures: [{ owner: "proxy-encoder", clock: "performance",
|
|
164
|
+
clockEpoch: null, startedAt: null, completedAt: null, revision: null, provenance: "projected", source,
|
|
165
|
+
validity: "unknown", unknownReason: "projected-encoder-speed-has-no-capture" }] };
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
133
170
|
function observeForecastInput(observeWait, sourceKey, state, event) {
|
|
134
171
|
if (!state) return;
|
|
135
172
|
observeWait?.(sourceKey, "process", {
|
|
@@ -956,6 +993,8 @@ export class ViewerRequests {
|
|
|
956
993
|
const liveRuns = this.#host.encodeRuns.liveRunsOf?.(output) ?? [];
|
|
957
994
|
const encoderCapture = encoderCaptureOf(trackRate?.captures, liveRuns, actionId, generation);
|
|
958
995
|
const encoderCaptureValid = encoderCapture.validity === "valid";
|
|
996
|
+
const projectedRateCanSeedForecast = trackRate?.captures?.length > 0 &&
|
|
997
|
+
trackRate.captures.every(capture => capture.provenance === "projected");
|
|
959
998
|
const processingStarted = liveRuns.some(({ progress }) => progress.processedSeconds > progress.startPositionSeconds);
|
|
960
999
|
const startedAt = liveRuns.find(({ startedAt }) => startedAt > 0)?.startedAt ?? now;
|
|
961
1000
|
tracks.push({
|
|
@@ -995,7 +1034,10 @@ export class ViewerRequests {
|
|
|
995
1034
|
this.#host.initialOutputBitsPerMediaSecondOf?.(output) ?? 0,
|
|
996
1035
|
durationSeconds: output.timeline?.publishedStartOf(output.timeline.segmentCount) ?? session.file.durationSeconds,
|
|
997
1036
|
segmentCount: output.timeline?.segmentCount ?? segments.length,
|
|
998
|
-
|
|
1037
|
+
// A projection is explicitly not a measured capture, but remains the
|
|
1038
|
+
// numeric seed it was before capture provenance was carried here.
|
|
1039
|
+
// Other invalid measured captures stay out of the forecast.
|
|
1040
|
+
readings: encoderCaptureValid || projectedRateCanSeedForecast ? trackRates : [],
|
|
999
1041
|
capture: encoderCapture,
|
|
1000
1042
|
segments,
|
|
1001
1043
|
tailSegments: forecastGeometry?.tailSegments ?? [],
|
|
@@ -1247,39 +1289,16 @@ export class ViewerRequests {
|
|
|
1247
1289
|
* would drop the later-told, earlier-taken one (torrent-tv/meta#178).
|
|
1248
1290
|
*/
|
|
1249
1291
|
#trackRateReadings(output, now) {
|
|
1250
|
-
const readings =
|
|
1251
|
-
const summary = readings.length > 0 ? this.#host.playbackReadiness.rateSummaryOf(readings) : null;
|
|
1252
|
-
if (summary) return { summary, captures: readings.map(reading => ({ owner: reading.captureOwner,
|
|
1253
|
-
clock: reading.captureClock, clockEpoch: reading.captureClockEpoch,
|
|
1254
|
-
startedAt: reading.captureStartedAtMonotonic, completedAt: reading.captureCompletedAtMonotonic,
|
|
1255
|
-
revision: reading.at,
|
|
1256
|
-
validity: reading.captureOwner === "proxy-encoder" && reading.captureClock === "performance" &&
|
|
1257
|
-
Number.isFinite(reading.captureClockEpoch) && Number.isFinite(reading.captureStartedAtMonotonic) &&
|
|
1258
|
-
Number.isFinite(reading.captureCompletedAtMonotonic) && Number.isFinite(reading.at) &&
|
|
1259
|
-
reading.captureCompletedAtMonotonic >= reading.captureStartedAtMonotonic
|
|
1260
|
-
? "valid" : "unknown",
|
|
1261
|
-
unknownReason: reading.captureOwner === "proxy-encoder" && reading.captureClock === "performance" &&
|
|
1262
|
-
Number.isFinite(reading.captureClockEpoch) && Number.isFinite(reading.captureStartedAtMonotonic) &&
|
|
1263
|
-
Number.isFinite(reading.captureCompletedAtMonotonic) && Number.isFinite(reading.at) &&
|
|
1264
|
-
reading.captureCompletedAtMonotonic >= reading.captureStartedAtMonotonic
|
|
1265
|
-
? null : "encoder-sample-capture-unavailable" })) };
|
|
1292
|
+
const readings = this.#host.encodeSpeedReadingsOf?.(output) ?? [];
|
|
1266
1293
|
// ONLY UNTIL A PIECE IS MEASURED does the prediction stand for the
|
|
1267
1294
|
// encoder, and it is not kept among the readings. Added on every poll
|
|
1268
1295
|
// between runs, it put the machine's share of that moment — 1 % at a
|
|
1269
1296
|
// cold start — on the whole film, and the forecast read 0.03x
|
|
1270
1297
|
// (torrent-tv/meta#178).
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
return { summary: seed.snapshot(), captures: [{ owner: "proxy-encoder", clock: "performance",
|
|
1276
|
-
clockEpoch: performance.timeOrigin, startedAt: now, completedAt: now, revision: now,
|
|
1277
|
-
validity: "valid", unknownReason: null }] };
|
|
1278
|
-
}
|
|
1279
|
-
// Progress over wall time includes source waits, which the forecast prices
|
|
1280
|
-
// separately. Keep the rate unknown until a measured or calibrated
|
|
1281
|
-
// processing rate exists; single-piece runs now publish their own rate.
|
|
1282
|
-
return null;
|
|
1298
|
+
return trackRateReadings(readings, {
|
|
1299
|
+
predicted: this.#host.predictedEncodeSpeedOf?.(output),
|
|
1300
|
+
projected: this.#host.projectedEncodeSpeedOf?.(output)
|
|
1301
|
+
}, now, this.#host.playbackReadiness);
|
|
1283
1302
|
}
|
|
1284
1303
|
|
|
1285
1304
|
}
|