@torrent-tv/proxy 2.87.21 → 2.88.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.
- 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 +322 -322
- package/CHANGELOG.md +4 -0
- 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/biome.json +411 -411
- package/docs/browser-proxy-contract.md +133 -133
- package/docs/container-architecture.md +218 -218
- 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/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 +50 -50
- 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/files/get.js +106 -100
- 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 +173 -173
- 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 +84 -84
- 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/server.js +725 -725
- 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/EncodeRuns.js +1235 -1235
- 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/OutputOpening.js +758 -758
- package/services/encode/OutputTimes.js +579 -579
- package/services/encode/QsvEncoder.js +58 -58
- package/services/encode/Renditions.js +2184 -2184
- 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 +416 -416
- 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/hwaccel.js +1894 -1894
- 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/index.js +20 -20
- 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/EncodeCost.js +1141 -1141
- 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 +254 -254
- package/services/encode/quality/output-format.js +315 -315
- 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-command.js +754 -754
- package/services/encode/run-costs.js +155 -155
- package/services/encode/run-inputs.js +42 -42
- package/services/encode/segment-formats/fmp4.js +456 -456
- package/services/encode/segment-formats/index.js +85 -85
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +515 -515
- 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/ContainerOrchestrator.js +149 -149
- package/services/media/KeyframeTables.js +316 -316
- package/services/media/SourceFile.js +298 -298
- package/services/media/SubtitleCues.js +520 -520
- package/services/media/SubtitleOrchestrator.js +167 -167
- package/services/media/audio-inventory.js +245 -245
- package/services/media/container/AviContainer.js +266 -266
- package/services/media/container/Container.js +603 -603
- package/services/media/container/ContainerFactory.js +56 -56
- package/services/media/container/KeyframeTable.js +272 -272
- package/services/media/container/MatroskaContainer.js +1494 -1494
- package/services/media/container/Mp4Container.js +1244 -1244
- package/services/media/container/SubtitleFileContainer.js +322 -322
- 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 +131 -131
- package/services/media/tracks/ContainerTrack.js +75 -75
- package/services/media/tracks/ImageSubtitleTrack.js +19 -19
- package/services/media/tracks/SubtitleTrack.js +38 -38
- package/services/media/tracks/TextSubtitleTrack.js +287 -287
- package/services/media/tracks/VideoTrack.js +33 -33
- 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 +760 -760
- 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/playback-readiness.js +696 -696
- package/services/server/transcode-session-files.js +325 -325
- package/services/server/wire-outputs.js +992 -992
- 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/piece-store/shared-piece-store.js +1931 -1931
- package/services/storage/returns.js +103 -103
- package/services/storage/segment-store/SegmentStore.js +1240 -1240
- package/services/storage/wire.js +175 -175
- package/services/torrent/Contents.js +382 -324
- 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/episode-naming.js +182 -0
- 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/torrent-pool.js +2675 -2675
- package/services/torrent/worker/background-fill.js +213 -213
- package/services/torrent/worker/channel.js +271 -271
- package/services/torrent/worker/client.js +765 -765
- package/services/torrent/worker/fastest-wires.js +342 -342
- package/services/torrent/worker/handle-state.js +23 -23
- package/services/torrent/worker/held-bytes.js +155 -155
- 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/torrent/worker/worker.js +1129 -1129
- package/services/transport/data-channel-handler.js +1369 -1369
- 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/PriorityMap.js +390 -390
- 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/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-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/episode-naming.test.js +131 -0
- 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 +147 -147
- 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/held-file.js +29 -29
- 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/keyframe-table-budget.test.js +102 -102
- 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 +111 -111
- 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/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-output-one-session.test.js +204 -204
- 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 +453 -453
- package/test/playback-start-regressions.test.js +99 -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 +1229 -1229
- 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-serve-wiring.test.js +475 -475
- package/test/segment-store-eviction.test.js +247 -247
- package/test/segment-store.test.js +323 -323
- 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 +102 -102
- 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/source-file.test.js +133 -133
- package/test/source-files-route.test.js +12 -2
- 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-cue-walk.test.js +370 -370
- 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/subtitle-track-numbering.test.js +386 -386
- 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 +407 -407
- 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/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,88 +1,88 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file How fast this machine produces one output.
|
|
3
|
-
*
|
|
4
|
-
* The figure every decision in the encoding layer rests on: where an encoder
|
|
5
|
-
* goes and how many run are both worked out from arrivals, and an arrival is a
|
|
6
|
-
* distance divided by this. There must therefore ALWAYS be an answer, and each
|
|
7
|
-
* of the three that can be given is a measurement rather than a guess.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import test from "node:test";
|
|
11
|
-
import assert from "node:assert/strict";
|
|
12
|
-
import { EncodeCost } from "../services/encode/quality/EncodeCost.js";
|
|
13
|
-
import { OutputCatalog } from "../services/encode/output/OutputCatalog.js";
|
|
14
|
-
import { outputSpec } from "./helpers/output-spec.js";
|
|
15
|
-
|
|
16
|
-
const PICTURE = "torrent:abc:fmt=fmp4:grid=kf@0:video-only:v=0/copy";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {object[]} sessions
|
|
20
|
-
* @param {{ copySpeedX?: number | null, benchmark?: object[] | null }} host
|
|
21
|
-
*/
|
|
22
|
-
function costOf(sessions, host = {}) {
|
|
23
|
-
const outputs = new OutputCatalog();
|
|
24
|
-
sessions.forEach((session, index) => outputs.set(String(index), session));
|
|
25
|
-
return new EncodeCost({
|
|
26
|
-
runsFor: () => [],
|
|
27
|
-
stateFor: () => "IDLE",
|
|
28
|
-
progressFor: () => null,
|
|
29
|
-
outputs,
|
|
30
|
-
host: () => ({
|
|
31
|
-
benchmark: host.benchmark ?? null,
|
|
32
|
-
decodeModel: null,
|
|
33
|
-
contentionPenalties: null,
|
|
34
|
-
copySpeedX: host.copySpeedX ?? null,
|
|
35
|
-
availability: null
|
|
36
|
-
}),
|
|
37
|
-
audioCostKey: () => "",
|
|
38
|
-
runningEncoders: () => 0,
|
|
39
|
-
encodersRunningNow: () => 0,
|
|
40
|
-
torrentCostSecFor: () => 0
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
test("a run on this output outranks every prediction", () => {
|
|
45
|
-
// It is this machine, this material and these settings. Nothing said before
|
|
46
|
-
// the fact beats something seen happening.
|
|
47
|
-
const cost = costOf(
|
|
48
|
-
[{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 9.5 }],
|
|
49
|
-
{ copySpeedX: 600 }
|
|
50
|
-
);
|
|
51
|
-
assert.equal(cost.speedForOutput(PICTURE), 9.5);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("a copied picture is priced by the startup copy measurement", () => {
|
|
55
|
-
// The branch that had no figure at all until it was measured: copying neither
|
|
56
|
-
// decodes nor encodes, so neither the preset benchmark nor the decode model
|
|
57
|
-
// describes it, and a copied output was planned with no speed until its own
|
|
58
|
-
// run had been running long enough to report one.
|
|
59
|
-
const cost = costOf(
|
|
60
|
-
[{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: null }],
|
|
61
|
-
{ copySpeedX: 602 }
|
|
62
|
-
);
|
|
63
|
-
assert.equal(cost.speedForOutput(PICTURE), 602);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("the fastest reading wins where several sessions produce one output", () => {
|
|
67
|
-
// Two sessions whose output parameters agree ARE one output, so what either
|
|
68
|
-
// of them measured about this machine is true of the other.
|
|
69
|
-
const cost = costOf([
|
|
70
|
-
{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 4 },
|
|
71
|
-
{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 7 }
|
|
72
|
-
]);
|
|
73
|
-
assert.equal(cost.speedForOutput(PICTURE), 7);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("an output absent from the live registry says nothing about what the machine is doing", () => {
|
|
77
|
-
const cost = costOf([], { copySpeedX: 602 });
|
|
78
|
-
assert.equal(cost.speedForOutput(PICTURE), 0, "no registered output, so nothing to say");
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("another output's reading is not borrowed", () => {
|
|
82
|
-
// Two outputs are two different pieces of work — a picture re-encoded to 480p
|
|
83
|
-
// and the same picture copied are not the same speed.
|
|
84
|
-
const cost = costOf([
|
|
85
|
-
{ outputKey: "other", spec: outputSpec(), lastAloneSpeed: 40 }
|
|
86
|
-
]);
|
|
87
|
-
assert.equal(cost.speedForOutput(PICTURE), 0);
|
|
88
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* @file How fast this machine produces one output.
|
|
3
|
+
*
|
|
4
|
+
* The figure every decision in the encoding layer rests on: where an encoder
|
|
5
|
+
* goes and how many run are both worked out from arrivals, and an arrival is a
|
|
6
|
+
* distance divided by this. There must therefore ALWAYS be an answer, and each
|
|
7
|
+
* of the three that can be given is a measurement rather than a guess.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import test from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import { EncodeCost } from "../services/encode/quality/EncodeCost.js";
|
|
13
|
+
import { OutputCatalog } from "../services/encode/output/OutputCatalog.js";
|
|
14
|
+
import { outputSpec } from "./helpers/output-spec.js";
|
|
15
|
+
|
|
16
|
+
const PICTURE = "torrent:abc:fmt=fmp4:grid=kf@0:video-only:v=0/copy";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {object[]} sessions
|
|
20
|
+
* @param {{ copySpeedX?: number | null, benchmark?: object[] | null }} host
|
|
21
|
+
*/
|
|
22
|
+
function costOf(sessions, host = {}) {
|
|
23
|
+
const outputs = new OutputCatalog();
|
|
24
|
+
sessions.forEach((session, index) => outputs.set(String(index), session));
|
|
25
|
+
return new EncodeCost({
|
|
26
|
+
runsFor: () => [],
|
|
27
|
+
stateFor: () => "IDLE",
|
|
28
|
+
progressFor: () => null,
|
|
29
|
+
outputs,
|
|
30
|
+
host: () => ({
|
|
31
|
+
benchmark: host.benchmark ?? null,
|
|
32
|
+
decodeModel: null,
|
|
33
|
+
contentionPenalties: null,
|
|
34
|
+
copySpeedX: host.copySpeedX ?? null,
|
|
35
|
+
availability: null
|
|
36
|
+
}),
|
|
37
|
+
audioCostKey: () => "",
|
|
38
|
+
runningEncoders: () => 0,
|
|
39
|
+
encodersRunningNow: () => 0,
|
|
40
|
+
torrentCostSecFor: () => 0
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test("a run on this output outranks every prediction", () => {
|
|
45
|
+
// It is this machine, this material and these settings. Nothing said before
|
|
46
|
+
// the fact beats something seen happening.
|
|
47
|
+
const cost = costOf(
|
|
48
|
+
[{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 9.5 }],
|
|
49
|
+
{ copySpeedX: 600 }
|
|
50
|
+
);
|
|
51
|
+
assert.equal(cost.speedForOutput(PICTURE), 9.5);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("a copied picture is priced by the startup copy measurement", () => {
|
|
55
|
+
// The branch that had no figure at all until it was measured: copying neither
|
|
56
|
+
// decodes nor encodes, so neither the preset benchmark nor the decode model
|
|
57
|
+
// describes it, and a copied output was planned with no speed until its own
|
|
58
|
+
// run had been running long enough to report one.
|
|
59
|
+
const cost = costOf(
|
|
60
|
+
[{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: null }],
|
|
61
|
+
{ copySpeedX: 602 }
|
|
62
|
+
);
|
|
63
|
+
assert.equal(cost.speedForOutput(PICTURE), 602);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("the fastest reading wins where several sessions produce one output", () => {
|
|
67
|
+
// Two sessions whose output parameters agree ARE one output, so what either
|
|
68
|
+
// of them measured about this machine is true of the other.
|
|
69
|
+
const cost = costOf([
|
|
70
|
+
{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 4 },
|
|
71
|
+
{ outputKey: PICTURE, spec: outputSpec(), lastAloneSpeed: 7 }
|
|
72
|
+
]);
|
|
73
|
+
assert.equal(cost.speedForOutput(PICTURE), 7);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("an output absent from the live registry says nothing about what the machine is doing", () => {
|
|
77
|
+
const cost = costOf([], { copySpeedX: 602 });
|
|
78
|
+
assert.equal(cost.speedForOutput(PICTURE), 0, "no registered output, so nothing to say");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("another output's reading is not borrowed", () => {
|
|
82
|
+
// Two outputs are two different pieces of work — a picture re-encoded to 480p
|
|
83
|
+
// and the same picture copied are not the same speed.
|
|
84
|
+
const cost = costOf([
|
|
85
|
+
{ outputKey: "other", spec: outputSpec(), lastAloneSpeed: 40 }
|
|
86
|
+
]);
|
|
87
|
+
assert.equal(cost.speedForOutput(PICTURE), 0);
|
|
88
|
+
});
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file The places preparations hold on the machine are read off the viewers'
|
|
3
|
-
* own records (roadmap item 97, step 13): a step being warmed and a move to
|
|
4
|
-
* another limit of the height on screen are one list, and a place ends with
|
|
5
|
-
* the record — or the viewer — that holds it.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import test from "node:test";
|
|
9
|
-
import assert from "node:assert/strict";
|
|
10
|
-
import { Viewers } from "../services/viewer/Viewers.js";
|
|
11
|
-
import { outputsBeingPrepared } from "../services/viewer/choices.js";
|
|
12
|
-
|
|
13
|
-
const PICTURE = { id: "1111111122223333", outputKey: "picture" };
|
|
14
|
-
|
|
15
|
-
test("a warmed step and a move between limits are one list of places", () => {
|
|
16
|
-
const viewers = new Viewers();
|
|
17
|
-
const warming = viewers.of(PICTURE, "viewer-a");
|
|
18
|
-
warming.warmingVariantId = "2222222233334444";
|
|
19
|
-
const moving = viewers.of(PICTURE, "viewer-b");
|
|
20
|
-
moving.sameHeightSwitch = { outputId: "3333333344445555", outputKey: "limit", askedHeights: [720] };
|
|
21
|
-
assert.deepEqual([...outputsBeingPrepared(viewers)].sort(), ["2222222233334444", "3333333344445555"]);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("one output prepared for two viewers is one place", () => {
|
|
25
|
-
const viewers = new Viewers();
|
|
26
|
-
viewers.of(PICTURE, "viewer-a").warmingVariantId = "2222222233334444";
|
|
27
|
-
viewers.of(PICTURE, "viewer-b").sameHeightSwitch = { outputId: "2222222233334444", outputKey: "step" };
|
|
28
|
-
assert.equal(outputsBeingPrepared(viewers).size, 1);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("a place ends with its record, and with the viewer", () => {
|
|
32
|
-
const viewers = new Viewers();
|
|
33
|
-
const viewer = viewers.of(PICTURE, "viewer-a");
|
|
34
|
-
viewer.warmingVariantId = "2222222233334444";
|
|
35
|
-
viewer.warmingVariantId = null;
|
|
36
|
-
assert.equal(outputsBeingPrepared(viewers).size, 0, "the record cleared");
|
|
37
|
-
viewers.of(PICTURE, "viewer-b").warmingVariantId = "2222222233334444";
|
|
38
|
-
viewers.hasGone("viewer-b");
|
|
39
|
-
assert.equal(outputsBeingPrepared(viewers).size, 0, "the viewer gone");
|
|
40
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* @file The places preparations hold on the machine are read off the viewers'
|
|
3
|
+
* own records (roadmap item 97, step 13): a step being warmed and a move to
|
|
4
|
+
* another limit of the height on screen are one list, and a place ends with
|
|
5
|
+
* the record — or the viewer — that holds it.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { Viewers } from "../services/viewer/Viewers.js";
|
|
11
|
+
import { outputsBeingPrepared } from "../services/viewer/choices.js";
|
|
12
|
+
|
|
13
|
+
const PICTURE = { id: "1111111122223333", outputKey: "picture" };
|
|
14
|
+
|
|
15
|
+
test("a warmed step and a move between limits are one list of places", () => {
|
|
16
|
+
const viewers = new Viewers();
|
|
17
|
+
const warming = viewers.of(PICTURE, "viewer-a");
|
|
18
|
+
warming.warmingVariantId = "2222222233334444";
|
|
19
|
+
const moving = viewers.of(PICTURE, "viewer-b");
|
|
20
|
+
moving.sameHeightSwitch = { outputId: "3333333344445555", outputKey: "limit", askedHeights: [720] };
|
|
21
|
+
assert.deepEqual([...outputsBeingPrepared(viewers)].sort(), ["2222222233334444", "3333333344445555"]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("one output prepared for two viewers is one place", () => {
|
|
25
|
+
const viewers = new Viewers();
|
|
26
|
+
viewers.of(PICTURE, "viewer-a").warmingVariantId = "2222222233334444";
|
|
27
|
+
viewers.of(PICTURE, "viewer-b").sameHeightSwitch = { outputId: "2222222233334444", outputKey: "step" };
|
|
28
|
+
assert.equal(outputsBeingPrepared(viewers).size, 1);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("a place ends with its record, and with the viewer", () => {
|
|
32
|
+
const viewers = new Viewers();
|
|
33
|
+
const viewer = viewers.of(PICTURE, "viewer-a");
|
|
34
|
+
viewer.warmingVariantId = "2222222233334444";
|
|
35
|
+
viewer.warmingVariantId = null;
|
|
36
|
+
assert.equal(outputsBeingPrepared(viewers).size, 0, "the record cleared");
|
|
37
|
+
viewers.of(PICTURE, "viewer-b").warmingVariantId = "2222222233334444";
|
|
38
|
+
viewers.hasGone("viewer-b");
|
|
39
|
+
assert.equal(outputsBeingPrepared(viewers).size, 0, "the viewer gone");
|
|
40
|
+
});
|