@torrent-tv/proxy 2.89.6 → 2.89.7
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 +338 -338
- package/CHANGELOG.md +5 -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/docs/download-architecture.md +261 -261
- package/docs/encode-architecture.md +765 -765
- package/docs/encode-run-state.md +96 -96
- package/docs/logs.md +97 -97
- package/docs/playback-start-forecast.md +17 -2
- package/docs/socks5-egress-research.md +114 -114
- package/docs/storage-architecture.md +273 -273
- 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 +416 -416
- 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/server.js +748 -748
- 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 +1192 -1192
- package/services/encode/EncodePlan.js +1368 -1368
- package/services/encode/EncodeRun.js +32 -4
- package/services/encode/EncodeRuns.js +19 -7
- 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 +2283 -2283
- package/services/encode/RunClock.js +87 -87
- package/services/encode/RunProgress.js +79 -79
- 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 +116 -114
- package/services/encode/encode-run-state.js +551 -551
- package/services/encode/encoder-readings.js +43 -43
- 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/piece-completeness.js +60 -2
- package/services/encode/quality/EncodeCost.js +1043 -1043
- package/services/encode/quality/HostLoad.js +525 -525
- package/services/encode/quality/HostTimings.js +249 -249
- package/services/encode/quality/OutputQualityState.js +24 -24
- package/services/encode/quality/QualityController.js +758 -758
- package/services/encode/quality/QualityOffer.js +416 -416
- package/services/encode/quality/drain-threat.js +47 -47
- package/services/encode/quality/link-budget.js +337 -337
- 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-command.js +3 -1
- package/services/encode/run-costs.js +155 -155
- package/services/encode/run-inputs.js +53 -53
- package/services/encode/segment-formats/fmp4.js +476 -476
- package/services/encode/segment-formats/index.js +1 -0
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +8 -1
- 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 +1152 -1152
- package/services/server/ViewerRequests.js +785 -785
- 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 +1029 -1029
- 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/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 +264 -264
- 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/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 -355
- package/services/viewer/playback-readiness.js +635 -635
- 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 -77
- package/test/audio-inventory.test.js +212 -212
- package/test/audio-track-bitrate.test.js +40 -40
- 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/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 +275 -275
- package/test/encode-exit.test.js +111 -111
- package/test/encode-orchestrator.test.js +426 -426
- package/test/encode-plan-viewers.test.js +725 -725
- package/test/encode-plan.test.js +545 -545
- package/test/encode-run-state.test.js +314 -314
- package/test/encode-run.test.js +38 -0
- 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 +68 -68
- 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/fixtures/refused-audio-20261002.json +10 -0
- package/test/fmp4-presentation-clock.test.js +4 -2
- 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/health-metrics.test.js +38 -38
- package/test/held-request-width.test.js +157 -157
- package/test/helpers/encode-run.js +240 -240
- 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 +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 +291 -291
- package/test/matroska-cues-track.test.js +192 -192
- package/test/media-time.test.js +62 -62
- 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 +207 -207
- 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 +87 -87
- 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-completeness.test.js +37 -1
- 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 -518
- package/test/playback-start-regressions.test.js +101 -101
- 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 +160 -160
- 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 +64 -64
- package/test/same-height-switch.test.js +663 -663
- 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-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-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-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 +237 -237
- 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 +190 -190
- 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/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-states.test.js +189 -189
- package/test/viewer-subtitle-subscription.test.js +96 -96
- package/test/viewer.test.js +139 -139
- 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,143 +1,143 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Audio track — extends ContainerTrack with audio-specific flags.
|
|
3
|
-
*
|
|
4
|
-
* Matroska RFC 9559 §5.1.4.1:
|
|
5
|
-
* - FlagOriginal 0x55AE (default 0) — track is original language.
|
|
6
|
-
* - FlagCommentary 0x55AF — commentary track.
|
|
7
|
-
* - FlagVisualImpaired 0x55AC — audio description for visually impaired.
|
|
8
|
-
* - FlagTextDescriptions 0x55AD, FlagHearingImpaired etc. may also appear
|
|
9
|
-
* but the three above drive the audio menu (research/container-spec-conformance).
|
|
10
|
-
* MP4 ISO/IEC 14496-12: tkhd alternate_group groups alternate audio tracks.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { codecParametersOf, peakKbpsOf } from "./audio-bound.js";
|
|
14
|
-
import { ContainerTrack } from "./ContainerTrack.js";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Codec identifiers as containers write them, against the name ffmpeg prints.
|
|
18
|
-
*
|
|
19
|
-
* Needed because the browser decides whether it can play a soundtrack from that
|
|
20
|
-
* name, and for a sidecar file there is no ffmpeg banner to read it from — the
|
|
21
|
-
* track came from the container's own table, where Matroska writes `A_AC3` and
|
|
22
|
-
* MP4 writes `ac-3` for the thing ffmpeg calls `ac3`. Only what a soundtrack can
|
|
23
|
-
* actually be is listed; an identifier not here is reported as it was written,
|
|
24
|
-
* which the browser treats as one it does not know and therefore transcodes.
|
|
25
|
-
*/
|
|
26
|
-
const CODEC_NAMES = new Map([
|
|
27
|
-
["A_AAC", "aac"],
|
|
28
|
-
["A_AC3", "ac3"],
|
|
29
|
-
["A_EAC3", "eac3"],
|
|
30
|
-
["A_DTS", "dts"],
|
|
31
|
-
["A_FLAC", "flac"],
|
|
32
|
-
["A_OPUS", "opus"],
|
|
33
|
-
["A_VORBIS", "vorbis"],
|
|
34
|
-
["A_TRUEHD", "truehd"],
|
|
35
|
-
["A_MPEG/L3", "mp3"],
|
|
36
|
-
["A_MPEG/L2", "mp2"],
|
|
37
|
-
["A_ALAC", "alac"],
|
|
38
|
-
["mp4a", "aac"],
|
|
39
|
-
["ac-3", "ac3"],
|
|
40
|
-
["ec-3", "eac3"],
|
|
41
|
-
["alac", "alac"],
|
|
42
|
-
["opus", "opus"],
|
|
43
|
-
["Opus", "opus"],
|
|
44
|
-
["fLaC", "flac"],
|
|
45
|
-
["flac", "flac"]
|
|
46
|
-
]);
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Extensions of raw elementary streams, against the codec they carry.
|
|
50
|
-
*
|
|
51
|
-
* A bare `.ac3` has no track table to read, and its extension is the only thing
|
|
52
|
-
* that states its codec — which for an elementary stream is exactly what the
|
|
53
|
-
* extension means.
|
|
54
|
-
*/
|
|
55
|
-
const CODEC_BY_EXTENSION = new Map([
|
|
56
|
-
[".aac", "aac"],
|
|
57
|
-
[".ac3", "ac3"],
|
|
58
|
-
[".eac3", "eac3"],
|
|
59
|
-
[".dts", "dts"],
|
|
60
|
-
[".dtshd", "dts"],
|
|
61
|
-
[".flac", "flac"],
|
|
62
|
-
[".mp3", "mp3"],
|
|
63
|
-
[".mp2", "mp2"],
|
|
64
|
-
[".opus", "opus"],
|
|
65
|
-
[".ogg", "vorbis"],
|
|
66
|
-
[".oga", "vorbis"],
|
|
67
|
-
[".wav", "pcm"],
|
|
68
|
-
[".thd", "truehd"],
|
|
69
|
-
[".mlp", "truehd"],
|
|
70
|
-
[".m4a", "aac"]
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
export class AudioTrack extends ContainerTrack {
|
|
74
|
-
/**
|
|
75
|
-
* @param {object} params - See ContainerTrack plus:
|
|
76
|
-
* @param {boolean} params.isOriginal - FlagOriginal
|
|
77
|
-
* @param {boolean} params.isCommentary - FlagCommentary
|
|
78
|
-
* @param {boolean} params.isVisualImpaired - FlagVisualImpaired / descriptive audio
|
|
79
|
-
* @param {number | null} params.channels
|
|
80
|
-
* @param {number | null} params.samplingFrequency
|
|
81
|
-
*/
|
|
82
|
-
constructor(params) {
|
|
83
|
-
super({ ...params, type: "audio" });
|
|
84
|
-
this.isOriginal = params.isOriginal === true;
|
|
85
|
-
this.isCommentary = params.isCommentary === true;
|
|
86
|
-
this.isVisualImpaired = params.isVisualImpaired === true;
|
|
87
|
-
this.channels = Number.isFinite(params.channels) ? params.channels : null;
|
|
88
|
-
this.samplingFrequency = Number.isFinite(params.samplingFrequency) ? params.samplingFrequency : null;
|
|
89
|
-
// What the codec is configured as, and the most that configuration allows
|
|
90
|
-
// the track to carry — a statement of the file, read with the rest of the
|
|
91
|
-
// track table (`audio-bound.js`). Own properties rather than getters, so a
|
|
92
|
-
// copy of the track made field by field keeps them.
|
|
93
|
-
this.codecParameters = codecParametersOf({
|
|
94
|
-
codec: AudioTrack.codecNameOf(params),
|
|
95
|
-
codecPrivateB64: params.codecPrivateB64,
|
|
96
|
-
channels: this.channels,
|
|
97
|
-
samplingFrequency: this.samplingFrequency
|
|
98
|
-
});
|
|
99
|
-
this.peakKbps = peakKbpsOf(this.codecParameters);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* The ffmpeg-side codec name for one track, from whatever the reading gave.
|
|
104
|
-
*
|
|
105
|
-
* @param {{ codec?: string, codecId?: string }} track
|
|
106
|
-
* @param {string} [extension] - The sidecar file's extension, when the track
|
|
107
|
-
* came from a file with no readable table.
|
|
108
|
-
* @returns {string}
|
|
109
|
-
*/
|
|
110
|
-
static codecNameOf(track, extension = "") {
|
|
111
|
-
const fromBanner = typeof track?.codec === "string" ? track.codec.trim() : "";
|
|
112
|
-
if (fromBanner.length > 0) {
|
|
113
|
-
return fromBanner.toLowerCase();
|
|
114
|
-
}
|
|
115
|
-
const codecId = typeof track?.codecId === "string" ? track.codecId.trim() : "";
|
|
116
|
-
if (codecId.length > 0) {
|
|
117
|
-
const known = CODEC_NAMES.get(codecId);
|
|
118
|
-
if (known) {
|
|
119
|
-
return known;
|
|
120
|
-
}
|
|
121
|
-
// Matroska allows a suffix — `A_AAC/MPEG4/LC`, `A_PCM/INT/LIT` — so the
|
|
122
|
-
// family is what the first two segments say.
|
|
123
|
-
const family = codecId.split("/").slice(0, 2).join("/");
|
|
124
|
-
const byFamily = CODEC_NAMES.get(family) ?? CODEC_NAMES.get(codecId.split("/")[0]);
|
|
125
|
-
if (byFamily) {
|
|
126
|
-
return byFamily;
|
|
127
|
-
}
|
|
128
|
-
if (codecId.startsWith("A_PCM")) {
|
|
129
|
-
return "pcm";
|
|
130
|
-
}
|
|
131
|
-
return codecId.toLowerCase();
|
|
132
|
-
}
|
|
133
|
-
return CODEC_BY_EXTENSION.get(extension) ?? "";
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** Human label helper — commentary and descriptive audio must not look like main track. */
|
|
137
|
-
audioRoleLabel() {
|
|
138
|
-
if (this.isCommentary) return "commentary";
|
|
139
|
-
if (this.isVisualImpaired) return "descriptive";
|
|
140
|
-
if (this.isOriginal) return "original";
|
|
141
|
-
return "";
|
|
142
|
-
}
|
|
143
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file Audio track — extends ContainerTrack with audio-specific flags.
|
|
3
|
+
*
|
|
4
|
+
* Matroska RFC 9559 §5.1.4.1:
|
|
5
|
+
* - FlagOriginal 0x55AE (default 0) — track is original language.
|
|
6
|
+
* - FlagCommentary 0x55AF — commentary track.
|
|
7
|
+
* - FlagVisualImpaired 0x55AC — audio description for visually impaired.
|
|
8
|
+
* - FlagTextDescriptions 0x55AD, FlagHearingImpaired etc. may also appear
|
|
9
|
+
* but the three above drive the audio menu (research/container-spec-conformance).
|
|
10
|
+
* MP4 ISO/IEC 14496-12: tkhd alternate_group groups alternate audio tracks.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { codecParametersOf, peakKbpsOf } from "./audio-bound.js";
|
|
14
|
+
import { ContainerTrack } from "./ContainerTrack.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Codec identifiers as containers write them, against the name ffmpeg prints.
|
|
18
|
+
*
|
|
19
|
+
* Needed because the browser decides whether it can play a soundtrack from that
|
|
20
|
+
* name, and for a sidecar file there is no ffmpeg banner to read it from — the
|
|
21
|
+
* track came from the container's own table, where Matroska writes `A_AC3` and
|
|
22
|
+
* MP4 writes `ac-3` for the thing ffmpeg calls `ac3`. Only what a soundtrack can
|
|
23
|
+
* actually be is listed; an identifier not here is reported as it was written,
|
|
24
|
+
* which the browser treats as one it does not know and therefore transcodes.
|
|
25
|
+
*/
|
|
26
|
+
const CODEC_NAMES = new Map([
|
|
27
|
+
["A_AAC", "aac"],
|
|
28
|
+
["A_AC3", "ac3"],
|
|
29
|
+
["A_EAC3", "eac3"],
|
|
30
|
+
["A_DTS", "dts"],
|
|
31
|
+
["A_FLAC", "flac"],
|
|
32
|
+
["A_OPUS", "opus"],
|
|
33
|
+
["A_VORBIS", "vorbis"],
|
|
34
|
+
["A_TRUEHD", "truehd"],
|
|
35
|
+
["A_MPEG/L3", "mp3"],
|
|
36
|
+
["A_MPEG/L2", "mp2"],
|
|
37
|
+
["A_ALAC", "alac"],
|
|
38
|
+
["mp4a", "aac"],
|
|
39
|
+
["ac-3", "ac3"],
|
|
40
|
+
["ec-3", "eac3"],
|
|
41
|
+
["alac", "alac"],
|
|
42
|
+
["opus", "opus"],
|
|
43
|
+
["Opus", "opus"],
|
|
44
|
+
["fLaC", "flac"],
|
|
45
|
+
["flac", "flac"]
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extensions of raw elementary streams, against the codec they carry.
|
|
50
|
+
*
|
|
51
|
+
* A bare `.ac3` has no track table to read, and its extension is the only thing
|
|
52
|
+
* that states its codec — which for an elementary stream is exactly what the
|
|
53
|
+
* extension means.
|
|
54
|
+
*/
|
|
55
|
+
const CODEC_BY_EXTENSION = new Map([
|
|
56
|
+
[".aac", "aac"],
|
|
57
|
+
[".ac3", "ac3"],
|
|
58
|
+
[".eac3", "eac3"],
|
|
59
|
+
[".dts", "dts"],
|
|
60
|
+
[".dtshd", "dts"],
|
|
61
|
+
[".flac", "flac"],
|
|
62
|
+
[".mp3", "mp3"],
|
|
63
|
+
[".mp2", "mp2"],
|
|
64
|
+
[".opus", "opus"],
|
|
65
|
+
[".ogg", "vorbis"],
|
|
66
|
+
[".oga", "vorbis"],
|
|
67
|
+
[".wav", "pcm"],
|
|
68
|
+
[".thd", "truehd"],
|
|
69
|
+
[".mlp", "truehd"],
|
|
70
|
+
[".m4a", "aac"]
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
export class AudioTrack extends ContainerTrack {
|
|
74
|
+
/**
|
|
75
|
+
* @param {object} params - See ContainerTrack plus:
|
|
76
|
+
* @param {boolean} params.isOriginal - FlagOriginal
|
|
77
|
+
* @param {boolean} params.isCommentary - FlagCommentary
|
|
78
|
+
* @param {boolean} params.isVisualImpaired - FlagVisualImpaired / descriptive audio
|
|
79
|
+
* @param {number | null} params.channels
|
|
80
|
+
* @param {number | null} params.samplingFrequency
|
|
81
|
+
*/
|
|
82
|
+
constructor(params) {
|
|
83
|
+
super({ ...params, type: "audio" });
|
|
84
|
+
this.isOriginal = params.isOriginal === true;
|
|
85
|
+
this.isCommentary = params.isCommentary === true;
|
|
86
|
+
this.isVisualImpaired = params.isVisualImpaired === true;
|
|
87
|
+
this.channels = Number.isFinite(params.channels) ? params.channels : null;
|
|
88
|
+
this.samplingFrequency = Number.isFinite(params.samplingFrequency) ? params.samplingFrequency : null;
|
|
89
|
+
// What the codec is configured as, and the most that configuration allows
|
|
90
|
+
// the track to carry — a statement of the file, read with the rest of the
|
|
91
|
+
// track table (`audio-bound.js`). Own properties rather than getters, so a
|
|
92
|
+
// copy of the track made field by field keeps them.
|
|
93
|
+
this.codecParameters = codecParametersOf({
|
|
94
|
+
codec: AudioTrack.codecNameOf(params),
|
|
95
|
+
codecPrivateB64: params.codecPrivateB64,
|
|
96
|
+
channels: this.channels,
|
|
97
|
+
samplingFrequency: this.samplingFrequency
|
|
98
|
+
});
|
|
99
|
+
this.peakKbps = peakKbpsOf(this.codecParameters);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The ffmpeg-side codec name for one track, from whatever the reading gave.
|
|
104
|
+
*
|
|
105
|
+
* @param {{ codec?: string, codecId?: string }} track
|
|
106
|
+
* @param {string} [extension] - The sidecar file's extension, when the track
|
|
107
|
+
* came from a file with no readable table.
|
|
108
|
+
* @returns {string}
|
|
109
|
+
*/
|
|
110
|
+
static codecNameOf(track, extension = "") {
|
|
111
|
+
const fromBanner = typeof track?.codec === "string" ? track.codec.trim() : "";
|
|
112
|
+
if (fromBanner.length > 0) {
|
|
113
|
+
return fromBanner.toLowerCase();
|
|
114
|
+
}
|
|
115
|
+
const codecId = typeof track?.codecId === "string" ? track.codecId.trim() : "";
|
|
116
|
+
if (codecId.length > 0) {
|
|
117
|
+
const known = CODEC_NAMES.get(codecId);
|
|
118
|
+
if (known) {
|
|
119
|
+
return known;
|
|
120
|
+
}
|
|
121
|
+
// Matroska allows a suffix — `A_AAC/MPEG4/LC`, `A_PCM/INT/LIT` — so the
|
|
122
|
+
// family is what the first two segments say.
|
|
123
|
+
const family = codecId.split("/").slice(0, 2).join("/");
|
|
124
|
+
const byFamily = CODEC_NAMES.get(family) ?? CODEC_NAMES.get(codecId.split("/")[0]);
|
|
125
|
+
if (byFamily) {
|
|
126
|
+
return byFamily;
|
|
127
|
+
}
|
|
128
|
+
if (codecId.startsWith("A_PCM")) {
|
|
129
|
+
return "pcm";
|
|
130
|
+
}
|
|
131
|
+
return codecId.toLowerCase();
|
|
132
|
+
}
|
|
133
|
+
return CODEC_BY_EXTENSION.get(extension) ?? "";
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Human label helper — commentary and descriptive audio must not look like main track. */
|
|
137
|
+
audioRoleLabel() {
|
|
138
|
+
if (this.isCommentary) return "commentary";
|
|
139
|
+
if (this.isVisualImpaired) return "descriptive";
|
|
140
|
+
if (this.isOriginal) return "original";
|
|
141
|
+
return "";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Image subtitle track — PGS / VobSub / subp / clcp. Not convertible to WebVTT.
|
|
3
|
-
*
|
|
4
|
-
* Matroska: S_HDMV/PGS, S_VOBSUB, S_IMAGE/BMP etc.
|
|
5
|
-
* MP4: stpp is TTML (XML, excluded from Text), subp (VobSub), clcp (closed captions)
|
|
6
|
-
* Kept in the model only to preserve declaredIndex alignment with ffmpeg 0:s:N.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { SubtitleTrack } from "./SubtitleTrack.js";
|
|
10
|
-
|
|
11
|
-
export class ImageSubtitleTrack extends SubtitleTrack {
|
|
12
|
-
constructor(params) {
|
|
13
|
-
super(params);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
isTextBased() {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file Image subtitle track — PGS / VobSub / subp / clcp. Not convertible to WebVTT.
|
|
3
|
+
*
|
|
4
|
+
* Matroska: S_HDMV/PGS, S_VOBSUB, S_IMAGE/BMP etc.
|
|
5
|
+
* MP4: stpp is TTML (XML, excluded from Text), subp (VobSub), clcp (closed captions)
|
|
6
|
+
* Kept in the model only to preserve declaredIndex alignment with ffmpeg 0:s:N.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { SubtitleTrack } from "./SubtitleTrack.js";
|
|
10
|
+
|
|
11
|
+
export class ImageSubtitleTrack extends SubtitleTrack {
|
|
12
|
+
constructor(params) {
|
|
13
|
+
super(params);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
isTextBased() {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Subtitle track — extends ContainerTrack with subtitle-only flags.
|
|
3
|
-
*
|
|
4
|
-
* Matroska RFC 9559:
|
|
5
|
-
* - FlagForced 0x55AA default 0, applies ONLY to subtitles.
|
|
6
|
-
* - FlagHearingImpaired 0x55AB, FlagVisualImpaired 0x55AC (SDH etc.)
|
|
7
|
-
* - FlagTextDescriptions 0x55AD also subtitle-related.
|
|
8
|
-
* - FlagEnabled 0xB9 still handled in base (disabled tracks counted but not offered).
|
|
9
|
-
* MP4 ISO 14496-12 + Apple tx3g extension:
|
|
10
|
-
* - handler sbtl/subt/text/wvtt vs subp/clcp (image)
|
|
11
|
-
* - tx3g displayFlags forced bits 0x40000000 / 0x80000000 (unconfirmed primary source, carried as raw flags)
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { ContainerTrack } from "./ContainerTrack.js";
|
|
15
|
-
|
|
16
|
-
export class SubtitleTrack extends ContainerTrack {
|
|
17
|
-
/**
|
|
18
|
-
* @param {object} params - See ContainerTrack plus:
|
|
19
|
-
* @param {boolean} params.isForced - FlagForced (matroska) or tx3g forced display flag.
|
|
20
|
-
* @param {boolean} params.isHearingImpaired - FlagHearingImpaired
|
|
21
|
-
* @param {boolean} params.isVisualImpaired - FlagVisualImpaired
|
|
22
|
-
* @param {number[]} params.clusterPositions - Matroska: file offsets of clusters whose CuePoints name this track (for push). Empty when indexless.
|
|
23
|
-
* @param {Array<{offset:number,size:number,startSeconds:number,endSeconds:number}>} params.samples - MP4: per-cue byte ranges from sample tables.
|
|
24
|
-
*/
|
|
25
|
-
constructor(params) {
|
|
26
|
-
super({ ...params, type: "subtitle" });
|
|
27
|
-
this.isForced = params.isForced === true;
|
|
28
|
-
this.isHearingImpaired = params.isHearingImpaired === true;
|
|
29
|
-
this.isVisualImpaired = params.isVisualImpaired === true;
|
|
30
|
-
this.clusterPositions = Array.isArray(params.clusterPositions) ? params.clusterPositions : [];
|
|
31
|
-
this.samples = Array.isArray(params.samples) ? params.samples : [];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Whether this track can be converted to WebVTT in current pipeline. Overridden by subclasses. */
|
|
35
|
-
isTextBased() {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file Subtitle track — extends ContainerTrack with subtitle-only flags.
|
|
3
|
+
*
|
|
4
|
+
* Matroska RFC 9559:
|
|
5
|
+
* - FlagForced 0x55AA default 0, applies ONLY to subtitles.
|
|
6
|
+
* - FlagHearingImpaired 0x55AB, FlagVisualImpaired 0x55AC (SDH etc.)
|
|
7
|
+
* - FlagTextDescriptions 0x55AD also subtitle-related.
|
|
8
|
+
* - FlagEnabled 0xB9 still handled in base (disabled tracks counted but not offered).
|
|
9
|
+
* MP4 ISO 14496-12 + Apple tx3g extension:
|
|
10
|
+
* - handler sbtl/subt/text/wvtt vs subp/clcp (image)
|
|
11
|
+
* - tx3g displayFlags forced bits 0x40000000 / 0x80000000 (unconfirmed primary source, carried as raw flags)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { ContainerTrack } from "./ContainerTrack.js";
|
|
15
|
+
|
|
16
|
+
export class SubtitleTrack extends ContainerTrack {
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} params - See ContainerTrack plus:
|
|
19
|
+
* @param {boolean} params.isForced - FlagForced (matroska) or tx3g forced display flag.
|
|
20
|
+
* @param {boolean} params.isHearingImpaired - FlagHearingImpaired
|
|
21
|
+
* @param {boolean} params.isVisualImpaired - FlagVisualImpaired
|
|
22
|
+
* @param {number[]} params.clusterPositions - Matroska: file offsets of clusters whose CuePoints name this track (for push). Empty when indexless.
|
|
23
|
+
* @param {Array<{offset:number,size:number,startSeconds:number,endSeconds:number}>} params.samples - MP4: per-cue byte ranges from sample tables.
|
|
24
|
+
*/
|
|
25
|
+
constructor(params) {
|
|
26
|
+
super({ ...params, type: "subtitle" });
|
|
27
|
+
this.isForced = params.isForced === true;
|
|
28
|
+
this.isHearingImpaired = params.isHearingImpaired === true;
|
|
29
|
+
this.isVisualImpaired = params.isVisualImpaired === true;
|
|
30
|
+
this.clusterPositions = Array.isArray(params.clusterPositions) ? params.clusterPositions : [];
|
|
31
|
+
this.samples = Array.isArray(params.samples) ? params.samples : [];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Whether this track can be converted to WebVTT in current pipeline. Overridden by subclasses. */
|
|
35
|
+
isTextBased() {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Video track — extends ContainerTrack with video-specific container fields.
|
|
3
|
-
*
|
|
4
|
-
* Matroska RFC 9559: TrackEntry/Video (PixelWidth/Height, DisplayWidth/Height)
|
|
5
|
-
* MP4 ISO/IEC 14496-12: tkhd width/height, mdhd timescale, stsd sample entry
|
|
6
|
-
* (avc1/hev1/etc.), stss/stts for keyframes, colr for HDR.
|
|
7
|
-
* No FlagForced / FlagHearingImpaired — those are subtitle-only per spec.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { ContainerTrack } from "./ContainerTrack.js";
|
|
11
|
-
|
|
12
|
-
export class VideoTrack extends ContainerTrack {
|
|
13
|
-
/**
|
|
14
|
-
* @param {object} params - See ContainerTrack plus:
|
|
15
|
-
* @param {number | null} params.width - Coded width (PixelWidth / tkhd width).
|
|
16
|
-
* @param {number | null} params.height - Coded height.
|
|
17
|
-
* @param {number | null} params.displayWidth
|
|
18
|
-
* @param {number | null} params.displayHeight
|
|
19
|
-
* @param {number | null} params.fps - From container when available (otherwise from ffmpeg banner elsewhere).
|
|
20
|
-
* @param {boolean} params.isHdr - From container colr / ffmpeg detection later.
|
|
21
|
-
* @param {number | null} params.bitDepth
|
|
22
|
-
*/
|
|
23
|
-
constructor(params) {
|
|
24
|
-
super({ ...params, type: "video" });
|
|
25
|
-
this.width = Number.isFinite(params.width) ? params.width : null;
|
|
26
|
-
this.height = Number.isFinite(params.height) ? params.height : null;
|
|
27
|
-
this.displayWidth = Number.isFinite(params.displayWidth) ? params.displayWidth : null;
|
|
28
|
-
this.displayHeight = Number.isFinite(params.displayHeight) ? params.displayHeight : null;
|
|
29
|
-
this.fps = Number.isFinite(params.fps) ? params.fps : null;
|
|
30
|
-
this.isHdr = params.isHdr === true;
|
|
31
|
-
this.bitDepth = Number.isFinite(params.bitDepth) ? params.bitDepth : null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file Video track — extends ContainerTrack with video-specific container fields.
|
|
3
|
+
*
|
|
4
|
+
* Matroska RFC 9559: TrackEntry/Video (PixelWidth/Height, DisplayWidth/Height)
|
|
5
|
+
* MP4 ISO/IEC 14496-12: tkhd width/height, mdhd timescale, stsd sample entry
|
|
6
|
+
* (avc1/hev1/etc.), stss/stts for keyframes, colr for HDR.
|
|
7
|
+
* No FlagForced / FlagHearingImpaired — those are subtitle-only per spec.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ContainerTrack } from "./ContainerTrack.js";
|
|
11
|
+
|
|
12
|
+
export class VideoTrack extends ContainerTrack {
|
|
13
|
+
/**
|
|
14
|
+
* @param {object} params - See ContainerTrack plus:
|
|
15
|
+
* @param {number | null} params.width - Coded width (PixelWidth / tkhd width).
|
|
16
|
+
* @param {number | null} params.height - Coded height.
|
|
17
|
+
* @param {number | null} params.displayWidth
|
|
18
|
+
* @param {number | null} params.displayHeight
|
|
19
|
+
* @param {number | null} params.fps - From container when available (otherwise from ffmpeg banner elsewhere).
|
|
20
|
+
* @param {boolean} params.isHdr - From container colr / ffmpeg detection later.
|
|
21
|
+
* @param {number | null} params.bitDepth
|
|
22
|
+
*/
|
|
23
|
+
constructor(params) {
|
|
24
|
+
super({ ...params, type: "video" });
|
|
25
|
+
this.width = Number.isFinite(params.width) ? params.width : null;
|
|
26
|
+
this.height = Number.isFinite(params.height) ? params.height : null;
|
|
27
|
+
this.displayWidth = Number.isFinite(params.displayWidth) ? params.displayWidth : null;
|
|
28
|
+
this.displayHeight = Number.isFinite(params.displayHeight) ? params.displayHeight : null;
|
|
29
|
+
this.fps = Number.isFinite(params.fps) ? params.fps : null;
|
|
30
|
+
this.isHdr = params.isHdr === true;
|
|
31
|
+
this.bitDepth = Number.isFinite(params.bitDepth) ? params.bitDepth : null;
|
|
32
|
+
}
|
|
33
|
+
}
|