@torrent-tv/proxy 2.89.1 → 2.89.2
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/.claude/commands/opsx/apply.md +155 -155
- package/.claude/commands/opsx/archive.md +160 -160
- package/.claude/commands/opsx/explore.md +174 -174
- package/.claude/commands/opsx/propose.md +109 -109
- package/.claude/commands/opsx/sync.md +143 -143
- package/.claude/skills/openspec-apply-change/SKILL.md +159 -159
- package/.claude/skills/openspec-archive-change/SKILL.md +117 -117
- package/.claude/skills/openspec-explore/SKILL.md +289 -289
- package/.claude/skills/openspec-propose/SKILL.md +113 -113
- package/.claude/skills/openspec-sync-specs/SKILL.md +147 -147
- package/.dockerignore +5 -5
- package/AGENTS.md +6 -1
- package/CHANGELOG.md +2299 -2288
- package/Dockerfile +30 -30
- package/LICENSE +16 -16
- package/README.md +369 -369
- package/assets/calibration/NOTICE.md +100 -100
- package/assets/diagnostics/sctpstate.gdb +31 -31
- package/bin/cli.js +684 -684
- package/bin/thread-pool.js +30 -30
- package/docs/download-architecture.md +261 -261
- package/docs/encode-architecture.md +729 -729
- package/docs/encode-run-state.md +96 -96
- package/docs/logs.md +97 -97
- package/docs/playback-start-forecast.md +42 -8
- package/docs/socks5-egress-research.md +114 -114
- package/docs/storage-architecture.md +267 -267
- package/knip.json +14 -14
- package/openspec/changes/adaptive-bitrate/design.md +92 -92
- package/openspec/changes/adaptive-bitrate/proposal.md +56 -56
- package/openspec/changes/adaptive-bitrate/specs/adaptive-bitrate/spec.md +51 -51
- package/openspec/changes/adaptive-bitrate/tasks.md +40 -40
- package/openspec/changes/binary-distribution/.openspec.yaml +2 -2
- package/openspec/changes/binary-distribution/proposal.md +53 -53
- package/openspec/changes/chunked-request-bodies/design.md +81 -81
- package/openspec/changes/chunked-request-bodies/proposal.md +53 -53
- package/openspec/changes/chunked-request-bodies/specs/chunked-request-bodies/spec.md +30 -30
- package/openspec/changes/chunked-request-bodies/tasks.md +40 -40
- package/openspec/changes/cold-start/design.md +98 -98
- package/openspec/changes/cold-start/proposal.md +62 -62
- package/openspec/changes/cold-start/specs/cold-start/spec.md +47 -47
- package/openspec/changes/cold-start/tasks.md +48 -48
- package/openspec/changes/disk-cap/.openspec.yaml +2 -2
- package/openspec/changes/disk-cap/proposal.md +37 -37
- package/openspec/changes/disk-cap/specs/disk-cap/spec.md +25 -25
- package/openspec/changes/disk-cap/tasks.md +19 -19
- package/openspec/changes/proxy-observability/.openspec.yaml +2 -2
- package/openspec/changes/proxy-observability/design.md +38 -38
- package/openspec/changes/proxy-observability/proposal.md +49 -49
- package/openspec/changes/proxy-observability/specs/observability/spec.md +33 -33
- package/openspec/changes/proxy-observability/tasks.md +21 -21
- package/openspec/changes/seek-debounce/design.md +118 -118
- package/openspec/changes/seek-debounce/proposal.md +59 -59
- package/openspec/changes/seek-debounce/specs/seek-debounce/spec.md +41 -41
- package/openspec/changes/seek-debounce/tasks.md +33 -33
- package/openspec/changes/subtitle-language/.openspec.yaml +2 -2
- package/openspec/changes/subtitle-language/proposal.md +50 -50
- package/openspec/changes/subtitle-language/specs/subtitle-language/spec.md +34 -34
- package/openspec/changes/subtitle-language/tasks.md +26 -26
- package/openspec/changes/track-selection/.openspec.yaml +2 -2
- package/openspec/changes/track-selection/design.md +47 -47
- package/openspec/changes/track-selection/proposal.md +45 -45
- package/openspec/changes/track-selection/specs/track-selection/spec.md +41 -41
- package/openspec/changes/track-selection/tasks.md +20 -20
- package/openspec/changes/transcode-quality/.openspec.yaml +2 -2
- package/openspec/changes/transcode-quality/proposal.md +51 -51
- package/openspec/changes/transcode-quality/specs/transcode-quality/spec.md +139 -139
- package/openspec/changes/transcode-quality/tasks.md +63 -63
- package/openspec/config.yaml +38 -38
- package/package.json +1 -1
- package/public/.well-known/appspecific/com.chrome.devtools.json +1 -1
- package/research/delivery-wedge-stand-ladder-2026-09-13.md +329 -329
- package/research/double-spawn-2026-09-10.md +171 -171
- package/research/handover-2026-09-13.md +209 -209
- package/research/handover-reader-claims-removal-2026-09-12.md +166 -166
- package/research/piece-withdrawn-but-still-claimed-2026-09-12.md +175 -175
- package/research/preset-benchmark-size-scaling-2026-08-22.md +55 -55
- package/research/priority-map-is-the-truth-2026-09-12.md +225 -225
- package/routes/api/client-logs/post.js +86 -86
- package/routes/api/delivery-sink/get.js +72 -72
- package/routes/api/link-probe/get.js +51 -51
- package/routes/api/playback-plan/audio-tracks/post.js +29 -29
- package/routes/api/playback-plan/post.js +53 -53
- package/routes/api/sources/post.js +36 -36
- package/routes/api/sources/stats/get.js +132 -132
- package/routes/api/sources/warm/post.js +217 -217
- package/routes/api/subtitles/get.js +230 -230
- package/routes/api/transcode-sessions/fragment-far/post.js +60 -60
- package/routes/api/transcode-sessions/net-report/post.js +138 -138
- package/routes/api/transcode-sessions/post.js +178 -178
- package/routes/api/transcode-sessions/progress/get.js +27 -27
- package/routes/api/transcode-sessions/release/post.js +41 -41
- package/routes/api/transcode-sessions/seek/post.js +63 -63
- package/routes/health/get.js +13 -13
- package/routes/healthz/get.js +13 -13
- package/routes/stream/get.js +380 -380
- package/routes/transcode/audio-file/get.js +64 -64
- package/routes/transcode/audio-warm/get.js +95 -95
- package/routes/transcode/session-file/get.js +52 -52
- package/routes/transcode/variant-file/get.js +95 -95
- package/routes/transcode/variant-warm/get.js +84 -84
- package/scripts/render-run-graph.js +173 -173
- package/services/encode/CoverageMap.js +428 -428
- package/services/encode/CushionReport.js +345 -345
- package/services/encode/EncodeAdmission.js +376 -376
- package/services/encode/EncodeOrchestrator.js +1217 -1217
- package/services/encode/EncodePlan.js +1366 -1366
- package/services/encode/EncodeRun.js +813 -813
- package/services/encode/Encoder.js +142 -142
- package/services/encode/EncoderSelection.js +38 -38
- package/services/encode/LocalObservations.js +359 -359
- package/services/encode/NvencEncoder.js +50 -50
- package/services/encode/OutputTimes.js +579 -579
- package/services/encode/QsvEncoder.js +58 -58
- package/services/encode/Renditions.js +2282 -2282
- package/services/encode/RunProgress.js +84 -84
- package/services/encode/SegmentDemand.js +95 -95
- package/services/encode/SoftwareEncoder.js +121 -121
- package/services/encode/V4l2m2mEncoder.js +53 -53
- package/services/encode/VaapiEncoder.js +66 -66
- package/services/encode/args.js +418 -418
- package/services/encode/available-share.js +89 -89
- package/services/encode/calibration.js +361 -361
- package/services/encode/contention.js +128 -128
- package/services/encode/decode-cost-fit.js +363 -363
- package/services/encode/encode-exit.js +114 -114
- package/services/encode/encode-run-state.js +551 -551
- package/services/encode/encoder-readings.js +45 -45
- package/services/encode/fingerprint.js +322 -322
- package/services/encode/host-load.js +174 -174
- package/services/encode/index.js +9 -9
- package/services/encode/learned-median.js +90 -90
- package/services/encode/output/EncodedOutput.js +57 -57
- package/services/encode/output/Output.js +131 -131
- package/services/encode/output/OutputCatalog.js +414 -414
- package/services/encode/output/OutputSpec.js +390 -390
- package/services/encode/output/Timeline.js +308 -308
- package/services/encode/output/cut-grid.js +107 -107
- package/services/encode/output/ladder.js +32 -32
- package/services/encode/output/playlists.js +284 -284
- package/services/encode/output/rates.js +125 -125
- package/services/encode/output-key-format.js +21 -21
- package/services/encode/quality/HostLoad.js +525 -525
- package/services/encode/quality/HostTimings.js +249 -249
- package/services/encode/quality/OutputQualityState.js +28 -28
- package/services/encode/quality/QualityController.js +935 -935
- package/services/encode/quality/QualityOffer.js +416 -416
- package/services/encode/quality/drain-threat.js +47 -47
- package/services/encode/quality/link-budget.js +349 -349
- package/services/encode/quality/output-format.js +319 -319
- package/services/encode/quality/serving-output.js +216 -216
- package/services/encode/quality/visible-rung.js +57 -57
- package/services/encode/run-budget.js +97 -97
- package/services/encode/run-costs.js +155 -155
- package/services/encode/run-inputs.js +42 -42
- package/services/encode/segment-formats/fmp4.js +476 -458
- package/services/encode/segment-formats/index.js +103 -85
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +604 -541
- package/services/encode/segment-formats/mpegts.js +134 -134
- package/services/encode/start-stop-cost.js +178 -178
- package/services/encode/throughput.js +97 -97
- package/services/encode/torrent-cost.js +88 -88
- package/services/identity/installation-id.js +38 -38
- package/services/media/SourceFile.js +298 -298
- package/services/media/SubtitleOrchestrator.js +167 -167
- package/services/media/container/KeyframeTable.js +272 -272
- package/services/media/container/ebml-reader.js +159 -159
- package/services/media/ffmpeg-banner.js +260 -260
- package/services/media/keyframe-probe.js +157 -157
- package/services/media/media-info-probe.js +93 -93
- package/services/media/playback-planner.js +931 -931
- package/services/media/tracks/AudioTrack.js +143 -143
- package/services/media/tracks/ImageSubtitleTrack.js +19 -19
- package/services/media/tracks/SubtitleTrack.js +38 -38
- package/services/media/tracks/VideoTrack.js +33 -33
- package/services/media/tracks/audio-bound.js +233 -233
- package/services/media/tracks/index.js +15 -15
- package/services/media/tracks/language-detect.js +174 -174
- package/services/server/OutputLifecycle.js +418 -418
- package/services/server/SegmentServing.js +1150 -1150
- package/services/server/ViewerRequests.js +790 -786
- package/services/server/WaitLedger.js +142 -142
- package/services/server/controllers/PlaybackController.js +40 -40
- package/services/server/controllers/SubtitleController.js +109 -109
- package/services/server/http-responses.js +60 -60
- package/services/server/transcode-session-files.js +325 -325
- package/services/server/wire-outputs.js +1024 -1020
- package/services/storage/Diagnostics.js +202 -202
- package/services/storage/MachineBudget.js +235 -235
- package/services/storage/allowance.js +107 -107
- package/services/storage/core-dumps.js +106 -106
- package/services/storage/files/CompletedFiles.js +391 -391
- package/services/storage/files/piece-from-whole-file.js +118 -118
- package/services/storage/free.js +71 -71
- package/services/storage/keep.js +48 -48
- package/services/storage/machine-memory.js +56 -56
- package/services/storage/memory-report.js +575 -575
- package/services/storage/piece-store/piece-disk-store.js +539 -539
- package/services/storage/piece-store/piece-lru.js +495 -495
- package/services/storage/returns.js +103 -103
- package/services/storage/segment-store/SegmentStore.js +1255 -1255
- package/services/storage/wire.js +175 -175
- package/services/torrent/demand/DemandRegister.js +202 -202
- package/services/torrent/demand/Urgency.js +137 -137
- package/services/torrent/demand/Window.js +118 -118
- package/services/torrent/demand/index.js +8 -8
- package/services/torrent/demand/pieces.js +140 -140
- package/services/torrent/download/SwarmSelection.js +386 -386
- package/services/torrent/download/registry.js +102 -102
- package/services/torrent/download/withdraw-claim.js +80 -80
- package/services/torrent/files.js +455 -455
- package/services/torrent/naming.js +619 -619
- package/services/torrent/piece-store-of.js +29 -29
- package/services/torrent/supply-margin.js +262 -262
- package/services/torrent/worker/background-fill.js +213 -213
- package/services/torrent/worker/channel.js +271 -271
- package/services/torrent/worker/client.js +836 -836
- package/services/torrent/worker/fastest-wires.js +342 -342
- package/services/torrent/worker/handle-state.js +23 -23
- package/services/torrent/worker/install-webrtc-shim.js +32 -32
- package/services/torrent/worker/piece-reader.js +1078 -1078
- package/services/torrent/worker/pool-adapter.js +371 -371
- package/services/torrent/worker/protocol.js +184 -184
- package/services/torrent/worker/resume-warm.js +107 -107
- package/services/torrent/worker/webrtc-shim.js +219 -219
- package/services/transport/delivery-probe.js +842 -842
- package/services/transport/health-collector.js +53 -53
- package/services/transport/nat-classifier.js +231 -231
- package/services/transport/packet-witness.js +808 -808
- package/services/transport/port-mapper.js +235 -235
- package/services/transport/registry-api.js +81 -81
- package/services/transport/tunnel-client.js +447 -447
- package/services/transport/usrsctp-state.js +175 -175
- package/services/transport/webrtc-manager.js +484 -484
- package/services/viewer/Assignments.js +340 -340
- package/services/viewer/PriorityOrchestrator.js +325 -325
- package/services/viewer/Viewer.js +691 -691
- package/services/viewer/Viewers.js +368 -368
- package/services/viewer/active-output.js +37 -37
- package/services/viewer/audio-start.js +46 -46
- package/services/viewer/buffer-trend.js +81 -81
- package/services/viewer/choices.js +647 -647
- package/services/viewer/media-time.js +355 -0
- package/services/{server → viewer}/playback-readiness.js +635 -516
- package/services/viewer/positions.js +126 -126
- package/services/viewer/report-intake.js +46 -46
- package/store/source-registry.js +71 -71
- package/test/asset-paths.test.js +28 -28
- package/test/audio-buffer-continuity.test.js +77 -70
- package/test/audio-inventory.test.js +212 -212
- package/test/audio-track-bitrate.test.js +40 -40
- package/test/auto-quality-step.test.js +707 -707
- package/test/available-share.test.js +76 -76
- package/test/background-fill.test.js +190 -190
- package/test/client-log-file.test.js +110 -110
- package/test/completed-files.test.js +115 -115
- package/test/concurrent-cost.test.js +148 -148
- package/test/container-media-info.test.js +228 -228
- package/test/contention.test.js +76 -76
- package/test/core-dumps.test.js +57 -57
- package/test/coverage-follows-the-disk.test.js +228 -228
- package/test/coverage-map.test.js +195 -195
- package/test/cue-push-carries-what-the-walk-found.test.js +58 -58
- package/test/cut-times-timeline.test.js +65 -65
- package/test/cuts-follow-published-grid.test.js +109 -109
- package/test/data-channel-frame.test.js +63 -63
- package/test/data-channel-viewer-lifecycle.test.js +92 -92
- package/test/dead-torrent-handle.test.js +52 -52
- package/test/declared-rates.test.js +116 -116
- package/test/declared-tracks.test.js +43 -43
- package/test/decode-cost-fit.test.js +202 -202
- package/test/decode-cost.test.js +462 -462
- package/test/delivery-probe.test.js +393 -393
- package/test/demand-register.test.js +206 -206
- package/test/dht-bootstrap.test.js +72 -72
- package/test/drain-threat.test.js +65 -65
- package/test/duplicate-add.test.js +48 -48
- package/test/encode-admission.test.js +146 -146
- package/test/encode-cost.test.js +283 -283
- package/test/encode-exit.test.js +111 -111
- package/test/encode-orchestrator.test.js +419 -419
- package/test/encode-plan-viewers.test.js +718 -718
- package/test/encode-plan.test.js +545 -545
- package/test/encode-run-state.test.js +314 -314
- package/test/encode-run.test.js +162 -162
- package/test/encode-slope.test.js +46 -46
- package/test/encoded-output.test.js +39 -39
- package/test/encoder-kinds.test.js +122 -122
- package/test/encoder-readings.test.js +46 -46
- package/test/every-claimant-is-told-its-share.test.js +152 -152
- package/test/failed-encoder-still-serves-what-exists.test.js +354 -354
- package/test/failed-start-breaker.test.js +202 -202
- package/test/fastest-wires.test.js +143 -143
- package/test/ffmpeg-stream-counts.test.js +78 -78
- package/test/file-edges.test.js +191 -191
- package/test/fmp4-presentation-clock.test.js +146 -162
- package/test/fmp4-self-contained.test.js +80 -80
- package/test/fmp4-timestamps.test.js +140 -140
- package/test/fmp4-track-completeness.test.js +41 -41
- package/test/format-keyed-outputs.test.js +78 -78
- package/test/health-metrics.test.js +38 -38
- package/test/held-request-width.test.js +157 -157
- package/test/helpers/encode-run.js +136 -136
- package/test/helpers/manager.js +57 -57
- package/test/helpers/output-spec.js +63 -63
- package/test/host-load.test.js +68 -68
- package/test/index-accuracy-is-about-the-file.test.js +128 -128
- package/test/init-compat.test.js +219 -219
- package/test/input-lost-quiets-the-plan.test.js +261 -261
- package/test/input-unavailable.test.js +48 -48
- package/test/installation-id.test.js +39 -39
- package/test/keeping-period.test.js +83 -83
- package/test/keyframe-index-accuracy.test.js +188 -188
- package/test/keyframes-belong-to-the-file.test.js +249 -249
- package/test/learned-median.test.js +37 -37
- package/test/letting-go-asks-who-is-watching.test.js +191 -191
- package/test/limit-row-by-area.test.js +60 -60
- package/test/link-budget.test.js +112 -112
- package/test/link-probe.test.js +56 -56
- package/test/local-encoding-data.test.js +273 -273
- package/test/logger-repeats.test.js +134 -134
- package/test/look-ahead-coverage.test.js +56 -56
- package/test/manager-surface.test.js +292 -292
- package/test/matroska-cues-track.test.js +192 -192
- package/test/media-time.test.js +62 -0
- package/test/memory-budget.test.js +390 -390
- package/test/move-cost.test.js +216 -216
- package/test/mp4-subtitles.test.js +173 -173
- package/test/one-authority.test.js +285 -285
- package/test/one-budget.test.js +149 -149
- package/test/one-resource-divided.test.js +185 -185
- package/test/one-serving-output-per-height.test.js +458 -458
- package/test/orchestrator-wired.test.js +206 -206
- package/test/output-catalog.test.js +39 -39
- package/test/output-shape.test.js +21 -21
- package/test/output-spec.test.js +251 -251
- package/test/output-speed.test.js +88 -88
- package/test/outputs-being-prepared.test.js +40 -40
- package/test/packet-witness-ring.test.js +236 -236
- package/test/packet-witness.test.js +148 -148
- package/test/piece-disk-store.test.js +401 -401
- package/test/piece-from-whole-file.test.js +129 -129
- package/test/piece-lru.test.js +319 -319
- package/test/piece-reader.test.js +162 -162
- package/test/piece-selection-offset.test.js +85 -85
- package/test/piece-store-eviction.test.js +595 -595
- package/test/piece-store-never-refuses.test.js +153 -153
- package/test/piece-store-reservations.test.js +403 -403
- package/test/piece-store-slow-disk.test.js +159 -159
- package/test/piece-tail.test.js +97 -97
- package/test/plan-host-timings.test.js +68 -68
- package/test/plan-is-steady.test.js +225 -225
- package/test/playback-readiness.test.js +518 -483
- package/test/playback-start-regressions.test.js +101 -99
- package/test/priority-map-download.test.js +174 -174
- package/test/priority-map-emptied.test.js +204 -204
- package/test/priority-map-per-output.test.js +215 -215
- package/test/priority-map.test.js +163 -163
- package/test/probe-wedge-certainty.test.js +60 -60
- package/test/produced-copy-choice.test.js +213 -213
- package/test/published-timeline.test.js +83 -83
- package/test/quality-offer.test.js +162 -162
- package/test/quality-variants.test.js +1257 -1257
- package/test/rate-control-in-the-output.test.js +180 -180
- package/test/read-survives-withdrawal.test.js +164 -164
- package/test/read-window.test.js +365 -365
- package/test/resume-warm.test.js +39 -39
- package/test/run-graph-drift.test.js +37 -37
- package/test/run-inputs.test.js +80 -80
- package/test/run-intervals.test.js +100 -100
- package/test/run-position-follows-published-grid.test.js +89 -89
- package/test/run-progress.test.js +65 -65
- package/test/same-height-switch.test.js +664 -664
- package/test/seek-frees-the-viewers-requests.test.js +217 -217
- package/test/seek-landing.test.js +109 -109
- package/test/seek-target-not-superseded.test.js +195 -195
- package/test/segment-closed-on-both-branches.test.js +96 -96
- package/test/segment-cut-times.test.js +63 -63
- package/test/segment-demand.test.js +80 -80
- package/test/segment-hold-supersede.test.js +91 -91
- package/test/segment-judged-by-its-own-header.test.js +221 -221
- package/test/segment-store-eviction.test.js +247 -247
- package/test/segment-store.test.js +352 -352
- package/test/segment-true-start.test.js +86 -86
- package/test/segments-are-shared.test.js +176 -176
- package/test/send-chunk-bytes.test.js +86 -86
- package/test/serving-existing-output.test.js +105 -105
- package/test/serving-output.test.js +102 -102
- package/test/shared-piece-store.test.js +310 -310
- package/test/sidecar-naming.test.js +142 -142
- package/test/soundtrack-rate-bound.test.js +289 -289
- package/test/source-file.test.js +133 -133
- package/test/source-registry.test.js +18 -18
- package/test/split-a-stretch.test.js +139 -139
- package/test/stale-request-after-seek.test.js +158 -158
- package/test/startup-readings.test.js +124 -124
- package/test/stream-route.test.js +209 -209
- package/test/subtitle-cue-framing.test.js +200 -200
- package/test/subtitle-cue-source.test.js +102 -102
- package/test/subtitle-cursor.test.js +63 -63
- package/test/subtitle-defaults.test.js +118 -118
- package/test/subtitle-language.test.js +252 -252
- package/test/supply-margin.test.js +177 -177
- package/test/swarm-follows-readers.test.js +174 -174
- package/test/swarm-reach.test.js +130 -130
- package/test/swarm-selection.test.js +220 -220
- package/test/tail-duplication.test.js +167 -167
- package/test/the-channel-has-both-ends.test.js +91 -91
- package/test/the-torrent-thread-serves-bytes.test.js +107 -107
- package/test/thread-pool.test.js +53 -53
- package/test/timeline.test.js +84 -84
- package/test/torrent-contents.test.js +235 -235
- package/test/torrent-cost.test.js +71 -71
- package/test/torrent-files.test.js +221 -221
- package/test/torrent-naming.test.js +255 -255
- package/test/tracks-begin-together.test.js +209 -209
- package/test/tunnel-renewal.test.js +167 -167
- package/test/two-viewers-one-picture.test.js +504 -504
- package/test/upload-hurry.test.js +186 -186
- package/test/usrsctp-state.test.js +131 -131
- package/test/video-facts.test.js +102 -102
- package/test/viewer-assignments.test.js +143 -143
- package/test/viewer-outputs.test.js +285 -285
- package/test/viewer-presence.test.js +116 -116
- package/test/viewer-requests-admission.test.js +89 -89
- package/test/viewer-states.test.js +189 -189
- package/test/viewer-subtitle-subscription.test.js +96 -96
- package/test/viewer.test.js +139 -139
- package/test/viewing-generations.test.js +390 -390
- package/test/visible-rung.test.js +37 -37
- package/test/wait-ledger.test.js +100 -100
- package/test/webrtc-shim.test.js +149 -149
- package/test/wedge-certainty.test.js +131 -131
- package/test/whole-file-held-read.test.js +30 -30
- package/test/withdraw-piece-claim.test.js +212 -212
- package/test/worker-channel.test.js +158 -158
- package/utils/client-log-file.js +151 -151
- package/utils/logger.js +312 -312
- package/utils/parse-range.js +25 -25
- package/utils/perf.js +59 -59
- package/utils/torrent-source-key.js +38 -38
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file How much of the machine a new encoder can actually have.
|
|
3
|
-
*
|
|
4
|
-
* The encoder benchmark measures a QUIET host: one ffmpeg, nothing else. A real
|
|
5
|
-
* encode runs on a machine that is also downloading, hashing and serving, and
|
|
6
|
-
* on the addon host that machine was measured 99 % busy — `ffmpeg=52-60%
|
|
7
|
-
* proxy=17-24% system=99%` — while a step predicted at 1.83x ran at 1.01-1.12x
|
|
8
|
-
* (2026-08-17).
|
|
9
|
-
*
|
|
10
|
-
* What this corrects is ONLY the part nobody has been charged for. That
|
|
11
|
-
* distinction is the whole of the file, because the alternative has already
|
|
12
|
-
* shipped once and broke the product: in 2.21.0 the budget ADDED what else was
|
|
13
|
-
* running while the per-file costs were being LEARNED from runs that already
|
|
14
|
-
* contained that other work, so every cost was counted twice, every re-encoded
|
|
15
|
-
* step was refused, and the quality menu emptied itself down to the one copied
|
|
16
|
-
* height (fixed in 2.21.1).
|
|
17
|
-
*
|
|
18
|
-
* So: our own encoders are priced by the concurrency arithmetic, and the
|
|
19
|
-
* proxy's own work — the torrent, the hashing, the delivery — is priced per
|
|
20
|
-
* megabyte moved. Both are already in the budget. What is NOT in it is
|
|
21
|
-
* everything else the machine does: the kernel, the container runtime, whatever
|
|
22
|
-
* else the owner runs on their box. That is what is subtracted here, and
|
|
23
|
-
* nothing more.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The share of the machine available to a new encoder.
|
|
28
|
-
*
|
|
29
|
-
* @param {object} reading - Fractions of the WHOLE machine (all cores), as
|
|
30
|
-
* `shareOfMachine` reports them.
|
|
31
|
-
* @param {number | null} reading.systemBusy - Everything the machine is doing.
|
|
32
|
-
* @param {number | null} reading.encoderShare - Our own ffmpeg processes.
|
|
33
|
-
* @param {number | null} reading.proxyShare - The proxy process itself.
|
|
34
|
-
* @returns {{ share: number, unattributed: number, known: boolean }}
|
|
35
|
-
* `known` is false when the host does not report its own load — then the
|
|
36
|
-
* share is 1 and the caller must say it is uncorrected rather than pretend.
|
|
37
|
-
*/
|
|
38
|
-
export function availableShareFrom(reading = {}) {
|
|
39
|
-
const systemBusy = finite(reading.systemBusy);
|
|
40
|
-
if (systemBusy === null) {
|
|
41
|
-
// No reading at all: not every host has /proc. An uncorrected prediction is
|
|
42
|
-
// the honest answer, and the caller says so.
|
|
43
|
-
return { share: 1, unattributed: 0, known: false };
|
|
44
|
-
}
|
|
45
|
-
const ours = (finite(reading.encoderShare) ?? 0) + (finite(reading.proxyShare) ?? 0);
|
|
46
|
-
// Rounding, and the two readings being taken microseconds apart, can put our
|
|
47
|
-
// own share fractionally above the system total. Below zero is not a
|
|
48
|
-
// measurement of anything.
|
|
49
|
-
const unattributed = clamp(systemBusy - ours, 0, 1);
|
|
50
|
-
return { share: clamp(1 - unattributed, 0, 1), unattributed, known: true };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Apply the correction to a predicted speed.
|
|
55
|
-
*
|
|
56
|
-
* A speed is work per unit time, so a machine that can give a new encoder only
|
|
57
|
-
* `share` of itself produces `share ×` the speed the benchmark measured alone.
|
|
58
|
-
*
|
|
59
|
-
* @param {number} predictedSpeed - From the quiet-host benchmark.
|
|
60
|
-
* @param {{ share: number, known: boolean }} availability
|
|
61
|
-
* @returns {number}
|
|
62
|
-
*/
|
|
63
|
-
export function correctForAvailability(predictedSpeed, availability) {
|
|
64
|
-
if (!Number.isFinite(predictedSpeed) || predictedSpeed <= 0) {
|
|
65
|
-
return predictedSpeed;
|
|
66
|
-
}
|
|
67
|
-
if (!availability?.known) {
|
|
68
|
-
return predictedSpeed;
|
|
69
|
-
}
|
|
70
|
-
return predictedSpeed * availability.share;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @param {unknown} value
|
|
75
|
-
* @returns {number | null}
|
|
76
|
-
*/
|
|
77
|
-
function finite(value) {
|
|
78
|
-
return Number.isFinite(value) ? Number(value) : null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @param {number} value
|
|
83
|
-
* @param {number} low
|
|
84
|
-
* @param {number} high
|
|
85
|
-
* @returns {number}
|
|
86
|
-
*/
|
|
87
|
-
function clamp(value, low, high) {
|
|
88
|
-
return Math.min(high, Math.max(low, value));
|
|
89
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file How much of the machine a new encoder can actually have.
|
|
3
|
+
*
|
|
4
|
+
* The encoder benchmark measures a QUIET host: one ffmpeg, nothing else. A real
|
|
5
|
+
* encode runs on a machine that is also downloading, hashing and serving, and
|
|
6
|
+
* on the addon host that machine was measured 99 % busy — `ffmpeg=52-60%
|
|
7
|
+
* proxy=17-24% system=99%` — while a step predicted at 1.83x ran at 1.01-1.12x
|
|
8
|
+
* (2026-08-17).
|
|
9
|
+
*
|
|
10
|
+
* What this corrects is ONLY the part nobody has been charged for. That
|
|
11
|
+
* distinction is the whole of the file, because the alternative has already
|
|
12
|
+
* shipped once and broke the product: in 2.21.0 the budget ADDED what else was
|
|
13
|
+
* running while the per-file costs were being LEARNED from runs that already
|
|
14
|
+
* contained that other work, so every cost was counted twice, every re-encoded
|
|
15
|
+
* step was refused, and the quality menu emptied itself down to the one copied
|
|
16
|
+
* height (fixed in 2.21.1).
|
|
17
|
+
*
|
|
18
|
+
* So: our own encoders are priced by the concurrency arithmetic, and the
|
|
19
|
+
* proxy's own work — the torrent, the hashing, the delivery — is priced per
|
|
20
|
+
* megabyte moved. Both are already in the budget. What is NOT in it is
|
|
21
|
+
* everything else the machine does: the kernel, the container runtime, whatever
|
|
22
|
+
* else the owner runs on their box. That is what is subtracted here, and
|
|
23
|
+
* nothing more.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The share of the machine available to a new encoder.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} reading - Fractions of the WHOLE machine (all cores), as
|
|
30
|
+
* `shareOfMachine` reports them.
|
|
31
|
+
* @param {number | null} reading.systemBusy - Everything the machine is doing.
|
|
32
|
+
* @param {number | null} reading.encoderShare - Our own ffmpeg processes.
|
|
33
|
+
* @param {number | null} reading.proxyShare - The proxy process itself.
|
|
34
|
+
* @returns {{ share: number, unattributed: number, known: boolean }}
|
|
35
|
+
* `known` is false when the host does not report its own load — then the
|
|
36
|
+
* share is 1 and the caller must say it is uncorrected rather than pretend.
|
|
37
|
+
*/
|
|
38
|
+
export function availableShareFrom(reading = {}) {
|
|
39
|
+
const systemBusy = finite(reading.systemBusy);
|
|
40
|
+
if (systemBusy === null) {
|
|
41
|
+
// No reading at all: not every host has /proc. An uncorrected prediction is
|
|
42
|
+
// the honest answer, and the caller says so.
|
|
43
|
+
return { share: 1, unattributed: 0, known: false };
|
|
44
|
+
}
|
|
45
|
+
const ours = (finite(reading.encoderShare) ?? 0) + (finite(reading.proxyShare) ?? 0);
|
|
46
|
+
// Rounding, and the two readings being taken microseconds apart, can put our
|
|
47
|
+
// own share fractionally above the system total. Below zero is not a
|
|
48
|
+
// measurement of anything.
|
|
49
|
+
const unattributed = clamp(systemBusy - ours, 0, 1);
|
|
50
|
+
return { share: clamp(1 - unattributed, 0, 1), unattributed, known: true };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Apply the correction to a predicted speed.
|
|
55
|
+
*
|
|
56
|
+
* A speed is work per unit time, so a machine that can give a new encoder only
|
|
57
|
+
* `share` of itself produces `share ×` the speed the benchmark measured alone.
|
|
58
|
+
*
|
|
59
|
+
* @param {number} predictedSpeed - From the quiet-host benchmark.
|
|
60
|
+
* @param {{ share: number, known: boolean }} availability
|
|
61
|
+
* @returns {number}
|
|
62
|
+
*/
|
|
63
|
+
export function correctForAvailability(predictedSpeed, availability) {
|
|
64
|
+
if (!Number.isFinite(predictedSpeed) || predictedSpeed <= 0) {
|
|
65
|
+
return predictedSpeed;
|
|
66
|
+
}
|
|
67
|
+
if (!availability?.known) {
|
|
68
|
+
return predictedSpeed;
|
|
69
|
+
}
|
|
70
|
+
return predictedSpeed * availability.share;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {unknown} value
|
|
75
|
+
* @returns {number | null}
|
|
76
|
+
*/
|
|
77
|
+
function finite(value) {
|
|
78
|
+
return Number.isFinite(value) ? Number(value) : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {number} value
|
|
83
|
+
* @param {number} low
|
|
84
|
+
* @param {number} high
|
|
85
|
+
* @returns {number}
|
|
86
|
+
*/
|
|
87
|
+
function clamp(value, low, high) {
|
|
88
|
+
return Math.min(high, Math.max(low, value));
|
|
89
|
+
}
|