@torrent-tv/proxy 2.87.9 → 2.87.11
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 +2186 -2177
- 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 +124 -101
- 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 +100 -100
- package/routes/api/sources/post.js +36 -36
- package/routes/api/sources/stats/get.js +132 -132
- 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 +136 -129
- package/routes/api/transcode-sessions/post.js +160 -160
- 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 +361 -361
- 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/services/encode/CoverageMap.js +428 -428
- package/services/encode/CushionReport.js +345 -345
- package/services/encode/EncodeAdmission.js +332 -332
- package/services/encode/EncodeOrchestrator.js +1217 -1217
- package/services/encode/EncodePlan.js +1366 -1366
- package/services/encode/EncodeRun.js +776 -776
- package/services/encode/EncodeRuns.js +1229 -1229
- 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 +755 -755
- package/services/encode/OutputTimes.js +579 -579
- package/services/encode/QsvEncoder.js +58 -58
- package/services/encode/Renditions.js +2184 -2162
- 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 +1110 -1083
- 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 +266 -266
- 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 +747 -747
- package/services/encode/run-costs.js +155 -155
- package/services/encode/run-inputs.js +42 -42
- package/services/encode/segment-formats/fmp4.js +437 -437
- package/services/encode/segment-formats/index.js +77 -77
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +311 -311
- 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/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 -928
- 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 +1146 -1146
- package/services/server/ViewerRequests.js +703 -522
- package/services/server/WaitLedger.js +142 -142
- package/services/server/controllers/SubtitleController.js +109 -109
- package/services/server/http-responses.js +60 -60
- package/services/server/playback-readiness.js +620 -0
- package/services/server/transcode-session-files.js +325 -325
- package/services/server/wire-outputs.js +989 -983
- 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 +516 -516
- package/services/storage/piece-store/piece-lru.js +495 -495
- package/services/storage/piece-store/shared-piece-store.js +1880 -1880
- package/services/storage/returns.js +103 -103
- package/services/storage/segment-store/SegmentStore.js +1196 -1196
- package/services/storage/wire.js +175 -175
- package/services/torrent/Contents.js +324 -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/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/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/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/PriorityMap.js +390 -390
- package/services/viewer/PriorityOrchestrator.js +325 -325
- package/services/viewer/Viewer.js +675 -657
- 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-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/dead-torrent-handle.test.js +52 -52
- package/test/declared-rates.test.js +116 -116
- package/test/declared-tracks.test.js +43 -35
- 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 +161 -161
- 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-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 +381 -381
- 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 +560 -560
- package/test/piece-store-never-refuses.test.js +153 -153
- package/test/piece-store-reservations.test.js +318 -318
- 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 +323 -0
- 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 +103 -103
- 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 +182 -182
- 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,53 +1,53 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file h264_v4l2m2m — the stateful memory-to-memory encoder on an ARM board
|
|
3
|
-
* (Raspberry Pi, HA Yellow).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Encoder } from "./Encoder.js";
|
|
7
|
-
import { keyFrameArgs, safeDimensions, TRANSCODE_FPS } from "./args.js";
|
|
8
|
-
|
|
9
|
-
export class V4l2m2mEncoder extends Encoder {
|
|
10
|
-
constructor() {
|
|
11
|
-
// ARM SoC (e.g. Raspberry Pi / HA Yellow) stateful M2M encoder. No GPU
|
|
12
|
-
// scaler — scale in software, hand YUV420 frames to the hardware encoder.
|
|
13
|
-
super({ name: "h264_v4l2m2m", kind: "v4l2m2m", device: null, inputArgs: [] });
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** @returns {import("./Encoder.js").SpeedLadder} */
|
|
17
|
-
get speedLadder() {
|
|
18
|
-
return {
|
|
19
|
-
flag: "",
|
|
20
|
-
values: [],
|
|
21
|
-
measured: false,
|
|
22
|
-
note:
|
|
23
|
-
"This kind has no speed setting at all — its levers are the bitrate " +
|
|
24
|
-
"and the number of capture buffers, which are not a trade of picture " +
|
|
25
|
-
"against speed. So there is nowhere to step, and a host that cannot " +
|
|
26
|
-
"keep up on it has to change something else."
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// `-g` aligns the GOP to the segment length so an IDR lands on every segment
|
|
31
|
-
// boundary; this is verified by the keyframe-alignment test before use,
|
|
32
|
-
// because v4l2m2m does not always honour these hints.
|
|
33
|
-
buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, fps, forcedKeyframeTimes }) {
|
|
34
|
-
const { w, h } = safeDimensions(targetWidth, targetHeight);
|
|
35
|
-
const outFps = Number.isInteger(fps) && fps > 0 ? fps : TRANSCODE_FPS;
|
|
36
|
-
return [
|
|
37
|
-
"-vf",
|
|
38
|
-
`scale=${w}:${h}:force_original_aspect_ratio=decrease:force_divisible_by=2,fps=${outFps},format=yuv420p`,
|
|
39
|
-
"-c:v", "h264_v4l2m2m",
|
|
40
|
-
// More capture buffers than the default 4 — the default deadlocks /
|
|
41
|
-
// drops frames on the CM4 encoder ("All capture buffers returned to
|
|
42
|
-
// userspace").
|
|
43
|
-
"-num_capture_buffers", "32",
|
|
44
|
-
"-b:v", "3M",
|
|
45
|
-
// Kept even with an explicit cut list, as an upper bound on the
|
|
46
|
-
// interval: this encoder is the one known not always to honour keyframe
|
|
47
|
-
// hints, and without any bound a list it ignores yields one segment for
|
|
48
|
-
// the whole file rather than a wrongly-cut one.
|
|
49
|
-
"-g", String(outFps * segmentDurationSec),
|
|
50
|
-
...keyFrameArgs(segmentDurationSec, forcedKeyframeTimes)
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file h264_v4l2m2m — the stateful memory-to-memory encoder on an ARM board
|
|
3
|
+
* (Raspberry Pi, HA Yellow).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Encoder } from "./Encoder.js";
|
|
7
|
+
import { keyFrameArgs, safeDimensions, TRANSCODE_FPS } from "./args.js";
|
|
8
|
+
|
|
9
|
+
export class V4l2m2mEncoder extends Encoder {
|
|
10
|
+
constructor() {
|
|
11
|
+
// ARM SoC (e.g. Raspberry Pi / HA Yellow) stateful M2M encoder. No GPU
|
|
12
|
+
// scaler — scale in software, hand YUV420 frames to the hardware encoder.
|
|
13
|
+
super({ name: "h264_v4l2m2m", kind: "v4l2m2m", device: null, inputArgs: [] });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** @returns {import("./Encoder.js").SpeedLadder} */
|
|
17
|
+
get speedLadder() {
|
|
18
|
+
return {
|
|
19
|
+
flag: "",
|
|
20
|
+
values: [],
|
|
21
|
+
measured: false,
|
|
22
|
+
note:
|
|
23
|
+
"This kind has no speed setting at all — its levers are the bitrate " +
|
|
24
|
+
"and the number of capture buffers, which are not a trade of picture " +
|
|
25
|
+
"against speed. So there is nowhere to step, and a host that cannot " +
|
|
26
|
+
"keep up on it has to change something else."
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// `-g` aligns the GOP to the segment length so an IDR lands on every segment
|
|
31
|
+
// boundary; this is verified by the keyframe-alignment test before use,
|
|
32
|
+
// because v4l2m2m does not always honour these hints.
|
|
33
|
+
buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, fps, forcedKeyframeTimes }) {
|
|
34
|
+
const { w, h } = safeDimensions(targetWidth, targetHeight);
|
|
35
|
+
const outFps = Number.isInteger(fps) && fps > 0 ? fps : TRANSCODE_FPS;
|
|
36
|
+
return [
|
|
37
|
+
"-vf",
|
|
38
|
+
`scale=${w}:${h}:force_original_aspect_ratio=decrease:force_divisible_by=2,fps=${outFps},format=yuv420p`,
|
|
39
|
+
"-c:v", "h264_v4l2m2m",
|
|
40
|
+
// More capture buffers than the default 4 — the default deadlocks /
|
|
41
|
+
// drops frames on the CM4 encoder ("All capture buffers returned to
|
|
42
|
+
// userspace").
|
|
43
|
+
"-num_capture_buffers", "32",
|
|
44
|
+
"-b:v", "3M",
|
|
45
|
+
// Kept even with an explicit cut list, as an upper bound on the
|
|
46
|
+
// interval: this encoder is the one known not always to honour keyframe
|
|
47
|
+
// hints, and without any bound a list it ignores yields one segment for
|
|
48
|
+
// the whole file rather than a wrongly-cut one.
|
|
49
|
+
"-g", String(outFps * segmentDurationSec),
|
|
50
|
+
...keyFrameArgs(segmentDurationSec, forcedKeyframeTimes)
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file h264_vaapi — encode on a VAAPI device, with the scale on the same
|
|
3
|
-
* device so frames never leave it.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Encoder } from "./Encoder.js";
|
|
7
|
-
import { keyFrameArgs, safeDimensions } from "./args.js";
|
|
8
|
-
|
|
9
|
-
export class VaapiEncoder extends Encoder {
|
|
10
|
-
/**
|
|
11
|
-
* @param {string} device - Render node, e.g. `/dev/dri/renderD128`.
|
|
12
|
-
*/
|
|
13
|
-
constructor(device) {
|
|
14
|
-
super({
|
|
15
|
-
name: "h264_vaapi",
|
|
16
|
-
kind: "vaapi",
|
|
17
|
-
device,
|
|
18
|
-
// Decode on the GPU into VAAPI surfaces; scale and encode stay on-GPU.
|
|
19
|
-
inputArgs: ["-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi", "-vaapi_device", device]
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** @returns {import("./Encoder.js").SpeedLadder} */
|
|
24
|
-
get speedLadder() {
|
|
25
|
-
return {
|
|
26
|
-
flag: "-quality",
|
|
27
|
-
// Read from ffmpeg's own option list on the addon host 2026-09-04:
|
|
28
|
-
// "Set encode quality (trades off against speed, higher is faster)
|
|
29
|
-
// (from -1 to INT_MAX) (default -1)". The upper end is the driver's, not
|
|
30
|
-
// the encoder's, so there is no list to state — only the name of the
|
|
31
|
-
// setting and the direction.
|
|
32
|
-
values: [],
|
|
33
|
-
measured: false,
|
|
34
|
-
note:
|
|
35
|
-
"The setting is `-quality`, higher is faster, and its range belongs to " +
|
|
36
|
-
"the driver rather than to ffmpeg. Nothing here has benchmarked it, " +
|
|
37
|
-
"and nothing passes it: a VAAPI encode runs at the driver's default."
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// No fps filter: VAAPI inherits the source rate and keeps keyframes on the
|
|
42
|
-
// grid via time-based -force_key_frames, so it already honours source fps.
|
|
43
|
-
/** @returns {string[]} */
|
|
44
|
-
benchmarkInputArgs() {
|
|
45
|
-
return this.device ? ["-vaapi_device", this.device] : [];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** @param {string | null} rung @returns {string[]} */
|
|
49
|
-
benchmarkArgs(rung = null) {
|
|
50
|
-
// Raw frames live in this process; VAAPI encodes what is in the device, so
|
|
51
|
-
// the upload is part of what this kind costs and belongs in the reading.
|
|
52
|
-
const quality = rung ? ["-quality", rung] : [];
|
|
53
|
-
return ["-vf", "format=nv12,hwupload", "-c:v", "h264_vaapi", "-qp", "24", ...quality];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, forcedKeyframeTimes }) {
|
|
57
|
-
const { w, h } = safeDimensions(targetWidth, targetHeight);
|
|
58
|
-
return [
|
|
59
|
-
"-vf",
|
|
60
|
-
`scale_vaapi=w=${w}:h=${h}:force_original_aspect_ratio=decrease`,
|
|
61
|
-
"-c:v", "h264_vaapi",
|
|
62
|
-
"-qp", "24",
|
|
63
|
-
...keyFrameArgs(segmentDurationSec, forcedKeyframeTimes)
|
|
64
|
-
];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file h264_vaapi — encode on a VAAPI device, with the scale on the same
|
|
3
|
+
* device so frames never leave it.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Encoder } from "./Encoder.js";
|
|
7
|
+
import { keyFrameArgs, safeDimensions } from "./args.js";
|
|
8
|
+
|
|
9
|
+
export class VaapiEncoder extends Encoder {
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} device - Render node, e.g. `/dev/dri/renderD128`.
|
|
12
|
+
*/
|
|
13
|
+
constructor(device) {
|
|
14
|
+
super({
|
|
15
|
+
name: "h264_vaapi",
|
|
16
|
+
kind: "vaapi",
|
|
17
|
+
device,
|
|
18
|
+
// Decode on the GPU into VAAPI surfaces; scale and encode stay on-GPU.
|
|
19
|
+
inputArgs: ["-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi", "-vaapi_device", device]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @returns {import("./Encoder.js").SpeedLadder} */
|
|
24
|
+
get speedLadder() {
|
|
25
|
+
return {
|
|
26
|
+
flag: "-quality",
|
|
27
|
+
// Read from ffmpeg's own option list on the addon host 2026-09-04:
|
|
28
|
+
// "Set encode quality (trades off against speed, higher is faster)
|
|
29
|
+
// (from -1 to INT_MAX) (default -1)". The upper end is the driver's, not
|
|
30
|
+
// the encoder's, so there is no list to state — only the name of the
|
|
31
|
+
// setting and the direction.
|
|
32
|
+
values: [],
|
|
33
|
+
measured: false,
|
|
34
|
+
note:
|
|
35
|
+
"The setting is `-quality`, higher is faster, and its range belongs to " +
|
|
36
|
+
"the driver rather than to ffmpeg. Nothing here has benchmarked it, " +
|
|
37
|
+
"and nothing passes it: a VAAPI encode runs at the driver's default."
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// No fps filter: VAAPI inherits the source rate and keeps keyframes on the
|
|
42
|
+
// grid via time-based -force_key_frames, so it already honours source fps.
|
|
43
|
+
/** @returns {string[]} */
|
|
44
|
+
benchmarkInputArgs() {
|
|
45
|
+
return this.device ? ["-vaapi_device", this.device] : [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @param {string | null} rung @returns {string[]} */
|
|
49
|
+
benchmarkArgs(rung = null) {
|
|
50
|
+
// Raw frames live in this process; VAAPI encodes what is in the device, so
|
|
51
|
+
// the upload is part of what this kind costs and belongs in the reading.
|
|
52
|
+
const quality = rung ? ["-quality", rung] : [];
|
|
53
|
+
return ["-vf", "format=nv12,hwupload", "-c:v", "h264_vaapi", "-qp", "24", ...quality];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
buildVideoArgs({ targetWidth, targetHeight, segmentDurationSec, forcedKeyframeTimes }) {
|
|
57
|
+
const { w, h } = safeDimensions(targetWidth, targetHeight);
|
|
58
|
+
return [
|
|
59
|
+
"-vf",
|
|
60
|
+
`scale_vaapi=w=${w}:h=${h}:force_original_aspect_ratio=decrease`,
|
|
61
|
+
"-c:v", "h264_vaapi",
|
|
62
|
+
"-qp", "24",
|
|
63
|
+
...keyFrameArgs(segmentDurationSec, forcedKeyframeTimes)
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
}
|