demuxe 0.3.0-beta.3

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.
Files changed (124) hide show
  1. package/LICENSE +352 -0
  2. package/README.md +75 -0
  3. package/bin/demuxe.mjs +30 -0
  4. package/docs/API-MIGRATION.md +54 -0
  5. package/docs/BETA.md +98 -0
  6. package/docs/BRANDING-MIGRATION.md +77 -0
  7. package/docs/COMPATIBILITY-EXPANSION.md +181 -0
  8. package/docs/LICENSING.md +83 -0
  9. package/docs/OPTIMIZATION-COMPLETION.md +511 -0
  10. package/docs/OPTIMIZATION-FLAC.md +178 -0
  11. package/docs/OPTIMIZATION-INTEGRATION.md +221 -0
  12. package/docs/OPTIMIZATION-REVIEW-FIXES.md +78 -0
  13. package/docs/PLAYER-COMPONENT.md +247 -0
  14. package/docs/PUBLIC-API-VALIDATION.md +163 -0
  15. package/docs/PUBLIC-API.md +245 -0
  16. package/docs/RELEASE.md +181 -0
  17. package/docs/RUNTIME-ASSETS.md +127 -0
  18. package/engine-build.json +8781 -0
  19. package/examples/custom-controls.html +14 -0
  20. package/examples/player-element.html +5 -0
  21. package/fixtures/DejaVuSans.ttf +0 -0
  22. package/fixtures/FONT-LICENSE.txt +187 -0
  23. package/index.d.ts +1 -0
  24. package/index.js +1 -0
  25. package/package.json +46 -0
  26. package/player.d.ts +1 -0
  27. package/player.js +1 -0
  28. package/release-manifest.json +541 -0
  29. package/sources.lock.json +96 -0
  30. package/third_party/notices/dav1d/COPYING +23 -0
  31. package/third_party/notices/emscripten/LICENSE +102 -0
  32. package/third_party/notices/emscripten/system/lib/compiler-rt/LICENSE.TXT +311 -0
  33. package/third_party/notices/emscripten/system/lib/libc/musl/COPYRIGHT +193 -0
  34. package/third_party/notices/emscripten/system/lib/libcxx/LICENSE.TXT +311 -0
  35. package/third_party/notices/emscripten/system/lib/libcxxabi/LICENSE.TXT +311 -0
  36. package/third_party/notices/emsdk/LICENSE +27 -0
  37. package/third_party/notices/ffmpeg/COPYING.GPLv2 +339 -0
  38. package/third_party/notices/ffmpeg/COPYING.GPLv3 +674 -0
  39. package/third_party/notices/ffmpeg/COPYING.LGPLv2.1 +502 -0
  40. package/third_party/notices/ffmpeg/LICENSE.md +129 -0
  41. package/third_party/notices/ffmpeg-adaptation/COPYING.LGPLv2.1 +502 -0
  42. package/third_party/notices/ffmpeg-adaptation/LICENSE.md +127 -0
  43. package/third_party/notices/freetype/LICENSE.TXT +46 -0
  44. package/third_party/notices/freetype/docs/FTL.TXT +169 -0
  45. package/third_party/notices/freetype/docs/GPLv2.TXT +340 -0
  46. package/third_party/notices/fribidi/COPYING +504 -0
  47. package/third_party/notices/harfbuzz/COPYING +42 -0
  48. package/third_party/notices/libass/COPYING +15 -0
  49. package/third_party/notices/libplacebo/LICENSE +458 -0
  50. package/third_party/notices/libxml2/Copyright +23 -0
  51. package/third_party/notices/libxml2/dict.c.notice +17 -0
  52. package/third_party/notices/libxml2/list.c.notice +16 -0
  53. package/third_party/notices/mpv/Copyright +78 -0
  54. package/third_party/notices/mpv/LICENSE.GPL +338 -0
  55. package/third_party/notices/mpv/LICENSE.LGPL +501 -0
  56. package/third_party/notices/vulkan-headers/LICENSE.txt +202 -0
  57. package/third_party/notices/zimg/COPYING +14 -0
  58. package/third_party/notices/zlib/LICENSE +22 -0
  59. package/third_party/notices.json +166 -0
  60. package/toolchain.lock.json +204 -0
  61. package/web/audio-worklet.js +45 -0
  62. package/web/cheap-mp4-probe.js +82 -0
  63. package/web/engine-adaptation/manifest.json +75 -0
  64. package/web/engine-adaptation/remux.mjs +2 -0
  65. package/web/engine-adaptation/remux.wasm +0 -0
  66. package/web/engine-ass/manifest.json +55 -0
  67. package/web/engine-ass/subtitles.mjs +2 -0
  68. package/web/engine-ass/subtitles.wasm +0 -0
  69. package/web/engine-hybrid/player.mjs +2 -0
  70. package/web/engine-hybrid/player.wasm +0 -0
  71. package/web/engine-remux/remux.mjs +2 -0
  72. package/web/engine-remux/remux.wasm +0 -0
  73. package/web/engine-software-full/player.mjs +2 -0
  74. package/web/engine-software-full/player.wasm +0 -0
  75. package/web/file-reader.js +34 -0
  76. package/web/filter-retained-engine-worker.js +292 -0
  77. package/web/generated/index.d.ts +6 -0
  78. package/web/generated/index.js +4 -0
  79. package/web/generated/internal/assets.d.ts +2 -0
  80. package/web/generated/internal/assets.js +7 -0
  81. package/web/generated/internal/backend.d.ts +27 -0
  82. package/web/generated/internal/backend.js +1 -0
  83. package/web/generated/internal/errors.d.ts +13 -0
  84. package/web/generated/internal/errors.js +54 -0
  85. package/web/generated/internal/native-ass.d.ts +38 -0
  86. package/web/generated/internal/native-ass.js +206 -0
  87. package/web/generated/internal/native-player.d.ts +95 -0
  88. package/web/generated/internal/native-player.js +502 -0
  89. package/web/generated/internal/playback-plans.d.ts +526 -0
  90. package/web/generated/internal/playback-plans.js +110 -0
  91. package/web/generated/internal/selection.d.ts +45 -0
  92. package/web/generated/internal/selection.js +45 -0
  93. package/web/generated/internal/state.d.ts +8 -0
  94. package/web/generated/internal/state.js +56 -0
  95. package/web/generated/internal/wasm-player.d.ts +127 -0
  96. package/web/generated/internal/wasm-player.js +372 -0
  97. package/web/generated/player/index.d.ts +198 -0
  98. package/web/generated/player/index.js +873 -0
  99. package/web/generated/player/interaction.d.ts +6 -0
  100. package/web/generated/player/interaction.js +14 -0
  101. package/web/generated/player/styles.d.ts +1 -0
  102. package/web/generated/player/styles.js +86 -0
  103. package/web/generated/types.d.ts +227 -0
  104. package/web/generated/types.js +2 -0
  105. package/web/generated/unified-player.d.ts +129 -0
  106. package/web/generated/unified-player.js +1074 -0
  107. package/web/io-worker.js +65 -0
  108. package/web/native-ass-worker.js +26 -0
  109. package/web/native-remux-player.js +301 -0
  110. package/web/native-remux-source-worker.js +25 -0
  111. package/web/native-remux-worker.js +46 -0
  112. package/web/range-reader.js +130 -0
  113. package/web/remux-packaging.js +11 -0
  114. package/web/resource-loader.js +173 -0
  115. package/web/retained-decoder-worker.js +200 -0
  116. package/web/retained-video.js +15 -0
  117. package/web/segmented-subtitles.js +37 -0
  118. package/web/software-full-engine-worker.js +234 -0
  119. package/web/source-probe.js +28 -0
  120. package/web/split-mp4.js +159 -0
  121. package/web/streaming-manifest.js +136 -0
  122. package/web/subtitle-overlay.js +26 -0
  123. package/web/video-codec-config.js +59 -0
  124. package/web/vod-manifest.js +54 -0
@@ -0,0 +1,77 @@
1
+ # Beta.3 branding and migration audit
2
+
3
+ Public package/executable: `demuxe`. Component: `<demuxe-player>`; exported class:
4
+ `DemuxePlayerElement`. CSS variables use `--demuxe-*`. There is no legacy element
5
+ alias: no public Demuxe npm release previously established that name.
6
+
7
+ ## Deplexr to Demuxe
8
+
9
+ The attempted first publication as `deplexr` was rejected by npm's name-similarity
10
+ check. It was never published. The replacement identity is `demuxe`; version
11
+ `0.3.0-beta.3` remains the first proposed npm beta for this new package name.
12
+
13
+ Update imports from `deplexr` and `deplexr/player` to `demuxe` and `demuxe/player`,
14
+ the executable to `demuxe`, `<deplexr-player>` to `<demuxe-player>`,
15
+ `DeplexrPlayerElement` to `DemuxePlayerElement`, and `--deplexr-*` variables to
16
+ `--demuxe-*`. Asset examples now use `/assets/demuxe/`. Recopy assets with the new
17
+ CLI into a fresh directory so the `demuxe-runtime.json` manifest describes them.
18
+ Public `DEPLEXR_*` environment knobs become `DEMUXE_*`; older internal `WEBMPV_*`
19
+ fallbacks remain as documented below. No Deplexr component or CSS aliases remain.
20
+
21
+ The repository is `Jagalite/demuxe`. Historical Git commits, release tags, archive
22
+ filenames, checksums and result records retain their original identity. They do
23
+ not qualify renamed package bytes; a new clean tagged candidate must be built and
24
+ tested before publishing Demuxe. The active local checkout directory may retain
25
+ its old name until the workspace is reopened at a new location.
26
+
27
+ The CLI is `bin/demuxe.mjs`; copied assets record `demuxe-runtime.json`. AudioWorklet
28
+ registration and internal browser virtual URLs migrated together. Engine filenames
29
+ remain `player.mjs`, `player.wasm`, `remux.mjs`, `remux.wasm`; their native C symbols
30
+ and upstream names are not a public package identity and are preserved.
31
+
32
+ Public docs, examples, install paths and package/source archive names use Demuxe.
33
+ The following historical names are intentionally retained:
34
+
35
+ * `LICENSE` and `docs/LICENSING.md`: the original copyright holder text remains
36
+ verbatim. Renaming a product does not rewrite attribution.
37
+ * `results/`, `docs/validation/`, `docs/HANDOFF.md`, and experimental Markdown:
38
+ historical evidence, commands, paths and old artifact identities retain provenance.
39
+ * `native/`, `patches/`, experimental native hooks: `webmpv_*` private C ABI symbols
40
+ remain to avoid cosmetic native changes. The source companion includes these
41
+ preferred sources and historical materials for GPL correspondence.
42
+ * No legacy branded runtime filename or public custom-element alias is shipped.
43
+
44
+ ## Environment variable classification
45
+
46
+ Maintained public knobs: `DEMUXE_SDK`, `DEMUXE_JOBS`, `DEMUXE_DECODER_SIMD`,
47
+ `DEMUXE_REMUX_FFMPEG_DIR`, `DEMUXE_TEST_MEDIA`. Their old spellings remain fallback
48
+ aliases in existing consumers; the new spelling wins. The standard clean-release
49
+ recipe fixes the decoder/remux profile, regardless of optional overrides.
50
+
51
+ `DEMUXE_RUNTIME_ROOT` is an internal qualification server mount used to test the
52
+ installed archive, never a runtime API. Other unprefixed test knobs (`BETA_ARCHIVE`,
53
+ `BROWSER`, `STREAMING_FIXTURE`, etc.) remain unchanged.
54
+
55
+ The remaining legacy environment names are internal build/experimental harness
56
+ wiring. Migrating their recorded configure scripts and historical experiments is
57
+ technical debt, not a public runtime requirement. Inventory at this revision:
58
+
59
+ * `WEBMPV_AUDIO_BRIDGE_H`: internal build/experiment variable; retained for beta.3.
60
+ * `WEBMPV_BROWSER_DECODER`: internal build/experiment variable; retained for beta.3.
61
+ * `WEBMPV_BROWSER_DECODER1`: internal build/experiment variable; retained for beta.3.
62
+ * `WEBMPV_CACHE`: internal build/experiment variable; retained for beta.3.
63
+ * `WEBMPV_DECODER_SIMD`: temporary compatibility alias.
64
+ * `WEBMPV_DECODER_SIMD0`: internal build/experiment variable; retained for beta.3.
65
+ * `WEBMPV_EM_CONFIG`: internal build/experiment variable; retained for beta.3.
66
+ * `WEBMPV_ENGINE_DIR`: internal build/experiment variable; retained for beta.3.
67
+ * `WEBMPV_FFMPEG_OBJ`: internal build/experiment variable; retained for beta.3.
68
+ * `WEBMPV_FULL_MANIFEST_DIR`: internal build/experiment variable; retained for beta.3.
69
+ * `WEBMPV_JOBS`: temporary compatibility alias.
70
+ * `WEBMPV_KERNEL_OPT`: internal build/experiment variable; retained for beta.3.
71
+ * `WEBMPV_LINK_OPT`: internal build/experiment variable; retained for beta.3.
72
+ * `WEBMPV_MANIFEST_DIR`: internal build/experiment variable; retained for beta.3.
73
+ * `WEBMPV_ORIGIN`: internal build/experiment variable; retained for beta.3.
74
+ * `WEBMPV_PERFORMANCE_CONFIG`: internal build/experiment variable; retained for beta.3.
75
+ * `WEBMPV_REMUX_FFMPEG_DIR`: temporary compatibility alias.
76
+ * `WEBMPV_SDK`: temporary compatibility alias.
77
+ * `WEBMPV_TEST_MEDIA`: temporary compatibility alias.
@@ -0,0 +1,181 @@
1
+ # Compatibility expansion — 0.3.0-beta.1
2
+
3
+ This increment extends Native, Hybrid and Software without adding a public mode.
4
+ It is a functional beta increment; performance, physical output and production
5
+ qualification remain separate. The original result files remain historical evidence.
6
+
7
+ | Addition | Implementation | Functional acceptance |
8
+ | --- | --- | --- |
9
+ | External subtitles/fonts | SRT, ASS, SSA, WebVTT, TTF and OTF | Pixels, custom glyphs, track language/selection, seeks and mode changes |
10
+ | Software AV1 | Pinned dav1d 1.5.1 | 8/10-bit decoding with browser codecs disabled, visible frames, seeks and filters |
11
+ | Recorded format gaps | SBC hints, DFPWM/Dirac packet admission, SWF durations, RealAudio Matroska mapping, MPEG seek preroll | Corrected and original generated fixtures replayed separately |
12
+ | 4K Software input | Configurable decode/allocation budgets | 3840×2160 input, bounded output, lower-budget rejection and rollback |
13
+ | Remux resilience | One transient worker/MSE restart; short-hole recovery; AVC TS without audio | Recovery, bounded retries, seeks and automatic fallback at configuration changes |
14
+ | Multichannel PCM | Stereo, 5.1 and 7.1 ring/output layouts | Per-channel values through native decoding and Web Audio, wrap/reset and device fallback |
15
+ | HDR to SDR | zimg 3.0.6 plus FFmpeg Mobius tone mapping | Tagged PQ/HLG colors compared against a separate native reference |
16
+ | Broader streaming | HLS/DASH rendition selection, finite segmented WebVTT, finite DASH periods and standard live audio/video | Playback, seeks, period boundaries, live reload/cancellation and resource cleanup |
17
+
18
+ The final verification record below identifies the exact artifacts checked.
19
+
20
+ ## API
21
+
22
+ ```ts
23
+ import {Player} from '/vendor/demuxe/index.js';
24
+
25
+ const player = new Player(container, {
26
+ // Omit mode to allow automatic feature-aware selection.
27
+ audioOutput: 'auto', // 'stereo' (default), '5.1', '7.1', or 'auto'
28
+ audioFallback: 'stereo', // or 'reject' when the device cannot supply the layout
29
+ resourceLimits: {
30
+ maxDecodePixels: 3840 * 2160,
31
+ maxAllocationBytes: 128 * 1024 * 1024,
32
+ },
33
+ });
34
+ await player.addFont(fontFile); // optional TTF/OTF; survives new sources
35
+ await player.open(movieFile);
36
+ await player.addSubtitle(srtOrAssFile, {
37
+ label: 'English', language: 'eng', select: true,
38
+ });
39
+ await player.setToneMapping('hdr-to-sdr'); // Software; 'off' restores normal filters
40
+ await player.play();
41
+ await player.destroy();
42
+ ```
43
+
44
+ External mpv subtitles require Hybrid or Software. Automatic selection can move a
45
+ Native session into an mpv mode; explicit Native pins reject that operation.
46
+ `addTextTrack()` remains the separate browser URL/text-track API. `capabilities`
47
+ reports `externalSubtitles`, `customFonts` and `externalTextTracks` separately.
48
+ Subtitle tracks survive same-source mode/filter changes and clear on a new source.
49
+ Fonts survive new sources and clear on destruction. Additions reopen transactionally,
50
+ retaining the previous session if the candidate fails; these changes are not gapless.
51
+
52
+ Each subtitle/font file is limited to 8 MiB. A player retains at most 16 subtitles
53
+ and 16 fonts, with aggregate limits of 16 MiB and 32 MiB respectively. Use `select:
54
+ false` to add an unselected subtitle; existing `selectTrack()` and
55
+ `subtitleVisible()` controls continue to apply.
56
+
57
+ Raw SBC lacks a reliable probe signature. Named `.sbc` Files are recognized; byte
58
+ buffers or extensionless remote sources can supply a demuxer hint:
59
+
60
+ ```ts
61
+ await player.open(bytes, {demuxer: 'sbc'});
62
+ await player.openRemote({url, demuxer: 'sbc'});
63
+ ```
64
+
65
+ ## Output and resource contract
66
+
67
+ Software's decode cap defaults to 8,294,400 pixels and can be reduced. The permitted
68
+ individual FFmpeg allocation cap is 32–256 MiB, default 128 MiB. Each mpv Wasm engine
69
+ starts at 128 MiB and may grow to 1 GiB. Canvas output remains within 1920×1080.
70
+ A source replacement temporarily owns two engines, and browser decoder/DOM memory
71
+ is additional. These are allocation bounds, not a universal real-time 4K guarantee.
72
+ ArrayBuffers remain limited to 32 MiB; larger Files use bounded reads.
73
+
74
+ `audioOutput: 'auto'` selects 7.1, 5.1 or stereo from Web Audio's advertised device
75
+ capacity. An explicit PCM layout uses an mpv mode. `audioDiagnostics()` reports the
76
+ requested layout, selected channels and device capacity. Native packet remux keeps
77
+ its existing browser-controlled audio output. The multichannel functional tests use
78
+ an explicit virtual output graph and verify each channel; they do not certify a
79
+ physical surround receiver or speaker arrangement. Encoded surround bitstream
80
+ passthrough and object-based audio rendering are not included.
81
+
82
+ `toneMapping: 'hdr-to-sdr'` (constructor or setter) runs a linear-light conversion,
83
+ BT.2020-to-BT.709 primaries conversion, Mobius compression, and limited-range BT.709
84
+ output before user video filters. Inputs must carry valid color metadata. The
85
+ reference checks cover tagged PQ and HLG; native HDR output, Dolby Vision dynamic
86
+ metadata, display calibration and all mastering-peak combinations are not covered.
87
+
88
+ ## Streaming contract
89
+
90
+ ```ts
91
+ await player.openRemote({
92
+ url: masterURL,
93
+ format: 'hls',
94
+ streaming: {maxBandwidth: 2_000_000},
95
+ });
96
+ await player.openRemote({
97
+ url: mpdURL,
98
+ format: 'dash',
99
+ streaming: {representation: 'video-720p'},
100
+ });
101
+ await player.openRemote({
102
+ url: liveURL, format: 'hls', streaming: {live: true},
103
+ });
104
+ ```
105
+
106
+ Selection chooses one rendition for the session; it does not continually switch
107
+ bitrates. With `maxBandwidth`, the highest advertised bandwidth within the limit is
108
+ chosen, or the lowest when none fit. With no preference, the highest is chosen.
109
+ `representation` is a zero-based variant index string for HLS and a representation
110
+ ID for DASH video. Associated audio/subtitle groups remain available.
111
+
112
+ Finite HLS WebVTT playlists are combined into one indexed subtitle resource,
113
+ preserving cue settings, absolute MPEGTS/LOCAL maps, wrap and discontinuities.
114
+ The combined subtitle window is bounded to 1 MiB. Native cue queues are reset on
115
+ seek. Rolling live subtitle-window replacement is not included in this profile.
116
+
117
+ Finite multiple-period DASH is adapted to discontinuity playlists while FFmpeg
118
+ continues to demux the compressed segments. This profile requires contiguous finite
119
+ periods, stable track identities, fMP4 audio/video, aligned first segments, and
120
+ SegmentTemplate/SegmentTimeline or SegmentList addressing. Separate byte-range
121
+ SegmentLists, multiple video adaptation sets, period gaps/overlaps and changing
122
+ track sets reject explicitly. Single-period DASH retains FFmpeg's demuxer.
123
+
124
+ Standard HLS live and single-period dynamic DASH require `live: true`. Live seeking
125
+ is limited by the upstream demuxer and available window; dynamic DASH seeking is
126
+ not supported by the pinned FFmpeg demuxer. LL-HLS parts, DRM/encryption, live
127
+ multi-period DASH, manifest patching and universal live-subtitle support remain out
128
+ of scope. HTTP(S), origin/credential policy, bounded requests and cancellation still
129
+ apply. Active resources retain the existing 16-handle/16-MiB bounds; generated
130
+ manifest/subtitle resources have a separate 4-MiB budget. Each finite playlist has
131
+ at most 10,000 segments. Live playback does not consume a finite lifetime-open cap.
132
+
133
+ ## Format and remux corrections
134
+
135
+ The old comfort-noise fixture encoded 48-kHz timestamps for an 8-kHz decoder. Its
136
+ replacement uses 8 kHz. The old generated RealMedia 14.4 stream had repeated zero
137
+ packet timestamps and a truncated tail. Qualification uses valid RealAudio 14.4 in
138
+ Matroska, whose mapping was missing from mpv's native Matroska demuxer. These fixture
139
+ corrections do not establish support for those malformed historical files.
140
+
141
+ DFPWM and generated intra Dirac/VC-2 NUT packets lacked keyframe flags; bounded
142
+ codec-specific admission prevents their loss during startup/seek. Dirac admission
143
+ checks for a sequence header and an intra picture parse unit. DFPWM decoder state
144
+ is reset on seek. SWF ADPCM block durations now supply the missing audio timeline.
145
+ One second of mpv demux preroll resolves the recorded MPEG-1/MPEG-2 seek cases.
146
+
147
+ Native remux retries a transient worker/MSE fault once per explicit open, preserving
148
+ source identity, position and playback intent. Small coded-range holes (up to half
149
+ a second) can be crossed when a playing output stalls. Configuration changes and
150
+ unrepairable timeline failures invoke the existing automatic Hybrid/Software
151
+ fallback. Explicit Native pins report unsupported transitions. This is not a claim
152
+ of gapless MSE reconfiguration for every sample-description change. Recovery and
153
+ buffer diagnostics remain bounded and available under `diagnostics.backend.remux`.
154
+
155
+ ## Build and verification
156
+
157
+ The locked-source engine recipe is `bash scripts/build-beta-engines.sh`. It builds
158
+ portable dav1d and zimg into a separate playback dependency prefix. The complete
159
+ patch series is replayed against verified upstream archives before updating source
160
+ files, so overlapping patches remain idempotent and unrecognized edits are preserved.
161
+ Optional YUV must be rebuilt with `npm run build:software-yuv`; it stays experimental.
162
+
163
+ Generate functional fixtures with `npm run fixtures:compatibility`. This requires a
164
+ host FFmpeg with SVT-AV1 and the existing DejaVu font archive. HDR reference generation
165
+ uses the small native executable built by `bash scripts/build-color-reference.sh`
166
+ (with a host zimg development package). Then run `npm run test:compatibility`.
167
+ Fixture manifests record host encoder versions, commands and input hashes.
168
+
169
+ Functional acceptance: 38 unit checks and 26 Chrome browser scenarios passed against
170
+ unchanged input hashes. The repository record is
171
+ `results/compatibility-expansion/2026-09-11T16-52-40.192Z/result.json`.
172
+ PQ/HLG mean absolute RGB errors against the native reference were 1.857/0.709
173
+ on the 0–255 scale. Six/eight-channel tests preserved each channel's expected
174
+ PCM value through the native ring and Web Audio graph. The 4K-to-1080p case used
175
+ 161,087,488 bytes of Wasm heap in this short generated test.
176
+
177
+ Package validation uses `node tests/beta-consumer.mjs` and
178
+ `BROWSER=firefox node tests/beta-consumer.mjs`; those records include the installed
179
+ archive SHA-256, type check, asset hashes and browser version. See repository
180
+ `results/compatibility-expansion/README.md` for the completed regression and
181
+ clean-consumer record. No production or long-duration qualification is inferred.
@@ -0,0 +1,83 @@
1
+ # Licensing and distribution
2
+
3
+ ## Original demuxe code
4
+
5
+ Original demuxe code is licensed under **GPL-2.0-or-later**. The copyright notice
6
+ is **Copyright (C) 2026 webmpv contributors**. See the root `LICENSE` for the grant,
7
+ warranty disclaimer and complete GPL text. Upstream-derived files and dependencies
8
+ retain their own notices and licenses.
9
+
10
+ The distributed package is GPL-2.0-or-later. Commercial use is allowed under the
11
+ license's conditions. Redistributing a covered combined work entails GPL source
12
+ and license obligations; this package does not provide a proprietary embedding
13
+ exception. A particular application's relationship to the library and distribution
14
+ terms may need review.
15
+
16
+ ## Current linked engines
17
+
18
+ These classifications follow the actual configured builds, not just the dependency
19
+ names. `build/beta-build.json` records the configuration and hashes for each build.
20
+
21
+ | Shipped artifact | Linked configuration | Applicable engine terms |
22
+ | --- | --- | --- |
23
+ | `web/engine-software-full/player.{mjs,wasm}` | mpv with `gpl=true`; FFmpeg with `CONFIG_GPL=1`, `CONFIG_VERSION3=0`, `CONFIG_NONFREE=0`; static libraries | GPL-2.0-or-later, plus retained component notices |
24
+ | `web/engine-hybrid/player.{mjs,wasm}` | The same mpv and full FFmpeg archives, browser decoder bridge, and modified mpv subtitle renderer | GPL-2.0-or-later, plus retained component notices |
25
+ | `web/engine-remux/remux.{mjs,wasm}` | Independent FFmpeg packet-only build; `CONFIG_GPL=0`, `CONFIG_VERSION3=0`, `CONFIG_NONFREE=0`; static libraries | FFmpeg library: LGPL-2.1-or-later; original wrapper and combined engine: GPL-2.0-or-later; retain the LGPL notices and source/relink materials |
26
+
27
+ The optional YUV engine is outside the standard three-engine candidate and must be
28
+ qualified and recorded separately before distribution.
29
+
30
+ Additional linked components include libass (ISC), FriBidi and libplacebo
31
+ (LGPL-2.1-or-later), HarfBuzz (MIT-style notices), FreeType (GPLv2 alternative for a GPLv2 combined distribution; retain
32
+ both its FTL and GPLv2 texts), zlib (Zlib), libxml2 (MIT-style notices), dav1d
33
+ (BSD-2-Clause), zimg (WTFPL), and Emscripten runtime libraries (the licenses and
34
+ exceptions under `third_party/notices/emscripten`). Inspect each component's source
35
+ headers for file-specific terms. Vulkan headers are build inputs; their notice is
36
+ retained without claiming that a Vulkan runtime is shipped. The bundled DejaVu font
37
+ has its separate copyright/license in `fixtures/FONT-LICENSE.txt`.
38
+
39
+ This software uses FreeType. Portions are copyright the FreeType Project
40
+ (https://freetype.org). The upstream notices identify the respective authors.
41
+
42
+ The patched upstream sources, including `experiments/retained-subtitles/vo_libmpv.c`,
43
+ retain their upstream licensing and any individual license headers. mpv's
44
+ `Copyright` inventory also covers its C files without individual headers. The
45
+ original-code license does not replace those upstream terms. The dated release record and `patches/` identify our modifications.
46
+
47
+ ## Source and build materials accompanying a distribution
48
+
49
+ Ship the runtime archive and its matching `demuxe-*-source.tar.gz` together from the
50
+ same download location. The source companion must contain:
51
+
52
+ - The exact demuxe source revision, native wrappers, browser bindings, patches,
53
+ build scripts, source/toolchain locks, package lock, notices and font asset.
54
+ - Every SHA-256-verified upstream archive in `sources.lock.json`, including the
55
+ SDK installer source, plus the actual installed Emscripten sources and runtime
56
+ library sources used in the build (excluding compiler caches).
57
+ - Actual FFmpeg configuration headers and configure arguments, mpv configuration,
58
+ compiler/tool versions and hashes, the build log, and the engine build record.
59
+ - Instructions to rebuild all engines and to relink the remux wrapper with a
60
+ modified FFmpeg. The supplied wrapper source and link command are part of the
61
+ static LGPL relinking materials; do not remove them from the source companion.
62
+
63
+ The release manifest binds both archives to the source revision and engine hashes.
64
+ Archive assembly must fail if the linked configuration or inputs disagree with the
65
+ build record. Notices alone and a link to generic upstream sources do not substitute
66
+ for matching source/build materials. Keep the companion downloadable alongside the
67
+ runtime for recipients; do not rely on an unfulfilled written-source offer.
68
+
69
+ The public download page and integrator documentation must identify the GPL engines
70
+ and LGPL remux library and link the matching source archive. Preserve license texts,
71
+ copyright notices and change identification when redistributing. Do not impose terms
72
+ that conflict with the supplied licenses, including restrictions on the LGPL rights
73
+ to modify/relink and debug those modifications.
74
+
75
+ The build audit establishes the inputs/configuration and presence of these materials.
76
+ It does not establish legal approval of a particular host application, EULA, store,
77
+ patent jurisdiction, or distribution arrangement. Have those arrangements reviewed
78
+ where needed, especially before embedding the GPL engines in a proprietary product.
79
+
80
+ References: [FFmpeg's license and distribution guidance](https://ffmpeg.org/legal.html),
81
+ [mpv's copyright and licensing statement](https://github.com/mpv-player/mpv/blob/v0.40.0/Copyright),
82
+ [GPL version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html),
83
+ [LGPL version 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html).