@osmo.inc/cli 0.1.15

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 (949) hide show
  1. package/DEPLOY.md +87 -0
  2. package/README.md +243 -0
  3. package/RELEASE.md +164 -0
  4. package/SETUP.md +60 -0
  5. package/THIRD_PARTY_NOTICES.md +18 -0
  6. package/bin/osmo.mjs +12 -0
  7. package/dist/osmo.js +7817 -0
  8. package/node_modules/@esbuild/darwin-arm64/README.md +3 -0
  9. package/node_modules/@esbuild/darwin-arm64/bin/esbuild +0 -0
  10. package/node_modules/@esbuild/darwin-arm64/package.json +20 -0
  11. package/node_modules/esbuild/LICENSE.md +21 -0
  12. package/node_modules/esbuild/README.md +3 -0
  13. package/node_modules/esbuild/bin/esbuild +223 -0
  14. package/node_modules/esbuild/install.js +289 -0
  15. package/node_modules/esbuild/lib/main.d.ts +716 -0
  16. package/node_modules/esbuild/lib/main.js +2532 -0
  17. package/node_modules/esbuild/package.json +49 -0
  18. package/node_modules/fflate/LICENSE +21 -0
  19. package/node_modules/fflate/esm/index.mjs +2710 -0
  20. package/node_modules/fflate/package.json +128 -0
  21. package/node_modules/typescript/LICENSE.txt +55 -0
  22. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  23. package/node_modules/typescript/lib/lib.d.ts +22 -0
  24. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  25. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  26. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  27. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  28. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  29. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  30. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  31. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  32. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  33. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  34. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  35. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  36. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  37. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  38. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  39. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  40. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  41. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  42. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  43. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  44. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  45. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  46. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  47. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  48. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  49. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  50. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  51. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  52. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  53. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  54. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  55. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  56. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  57. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  58. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  59. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  60. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  61. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  62. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  63. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  64. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  65. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  66. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  67. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  68. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  69. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  70. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  71. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  72. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  73. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  74. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  75. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  76. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  77. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  78. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  79. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  80. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  81. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  82. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  83. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  84. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  85. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  86. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  87. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  88. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  89. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  90. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  91. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  92. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  93. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  94. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  95. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  96. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  97. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  98. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  99. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  100. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  101. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  102. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  103. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  104. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  105. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  106. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  107. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  108. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  109. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  110. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  111. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  112. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  113. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  114. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  115. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  116. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  117. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  118. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  119. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  120. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  121. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  122. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  123. package/node_modules/typescript/lib/typescript.js +382 -0
  124. package/node_modules/typescript/package.json +57 -0
  125. package/package.json +54 -0
  126. package/release.json +136 -0
  127. package/runtime/apps/native/tools/compile.mjs +217 -0
  128. package/runtime/packages/scene/scripts/validate-strict.mjs +246 -0
  129. package/runtime/packages/scene/src/clip.d.mts +14 -0
  130. package/runtime/packages/scene/src/clip.mjs +15 -0
  131. package/runtime/packages/scene/src/color-value.d.mts +5 -0
  132. package/runtime/packages/scene/src/color-value.mjs +19 -0
  133. package/runtime/packages/scene/src/color.ts +1 -0
  134. package/runtime/packages/scene/src/effects.ts +213 -0
  135. package/runtime/packages/scene/src/elements.ts +491 -0
  136. package/runtime/packages/scene/src/evaluate.ts +919 -0
  137. package/runtime/packages/scene/src/index.ts +69 -0
  138. package/runtime/packages/scene/src/jsx-runtime.ts +73 -0
  139. package/runtime/packages/scene/src/knob-schema.ts +115 -0
  140. package/runtime/packages/scene/src/knobs.ts +118 -0
  141. package/runtime/packages/scene/src/mask.d.mts +6 -0
  142. package/runtime/packages/scene/src/mask.mjs +17 -0
  143. package/runtime/packages/scene/src/metadata.d.mts +23 -0
  144. package/runtime/packages/scene/src/metadata.mjs +44 -0
  145. package/runtime/packages/scene/src/motion-sampling.d.mts +2 -0
  146. package/runtime/packages/scene/src/motion-sampling.mjs +50 -0
  147. package/runtime/packages/scene/src/motion.ts +121 -0
  148. package/runtime/packages/scene/src/shader.ts +57 -0
  149. package/src/resource-examples/example-image/landscape.svg +7 -0
  150. package/src/resource-examples/example-image/resource.json +8 -0
  151. package/src/resource-examples/example-model/gem.glb +0 -0
  152. package/src/resource-examples/example-model/preview.svg +1 -0
  153. package/src/resource-examples/example-model/resource.json +7 -0
  154. package/src/resource-examples/example-scene/resource.json +1 -0
  155. package/src/resource-examples/example-scene/scene.tsx +8 -0
  156. package/src/resource-examples/example-shader/effect.wgsl +7 -0
  157. package/src/resource-examples/example-shader/preview.svg +1 -0
  158. package/src/resource-examples/example-shader/resource.json +27 -0
  159. package/src/resource-examples/example-shader/tint.wgsl +7 -0
  160. package/src/resource-examples/example-video/ambient.mp4 +0 -0
  161. package/src/resource-examples/example-video/resource.json +9 -0
  162. package/src/starter/scene.tsx +20 -0
  163. package/studio/index.html +2 -0
  164. package/studio/public/check-circle-filled.svg +3 -0
  165. package/studio/public/comment-cursor/active-outer.svg +3 -0
  166. package/studio/public/comment-cursor/default.svg +6 -0
  167. package/studio/public/osmo-studio-logo.svg +12 -0
  168. package/studio/public/pencil-simple.svg +5 -0
  169. package/studio/src/active-outer-TVYUEURE.svg +3 -0
  170. package/studio/src/app.css +4 -0
  171. package/studio/src/app.js +705 -0
  172. package/studio/src/default-6CTRH4V5.svg +6 -0
  173. package/studio/src/engine_bg.wasm +0 -0
  174. package/studio/src/inter-cyrillic-ext-wght-normal-IYF56FF6.woff2 +0 -0
  175. package/studio/src/inter-cyrillic-wght-normal-JEOLYBOO.woff2 +0 -0
  176. package/studio/src/inter-greek-ext-wght-normal-EOVOK2B5.woff2 +0 -0
  177. package/studio/src/inter-greek-wght-normal-IRE366VL.woff2 +0 -0
  178. package/studio/src/inter-latin-ext-wght-normal-HA22NDSG.woff2 +0 -0
  179. package/studio/src/inter-latin-wght-normal-NRMW37G5.woff2 +0 -0
  180. package/studio/src/inter-vietnamese-wght-normal-CE5GGD3W.woff2 +0 -0
  181. package/studio/src/osmo-studio-logo-D5R2V77B.svg +12 -0
  182. package/third-party/cargo/adler2@2.0.1/Cargo.toml +91 -0
  183. package/third-party/cargo/adler2@2.0.1/LICENSE-0BSD +12 -0
  184. package/third-party/cargo/adler2@2.0.1/LICENSE-APACHE +201 -0
  185. package/third-party/cargo/adler2@2.0.1/LICENSE-MIT +23 -0
  186. package/third-party/cargo/allocator-api2@0.2.21/Cargo.toml +48 -0
  187. package/third-party/cargo/allocator-api2@0.2.21/LICENSE-APACHE +176 -0
  188. package/third-party/cargo/allocator-api2@0.2.21/LICENSE-MIT +23 -0
  189. package/third-party/cargo/arrayref@0.3.9/Cargo.toml +23 -0
  190. package/third-party/cargo/arrayref@0.3.9/LICENSE +26 -0
  191. package/third-party/cargo/arrayvec@0.7.8/Cargo.toml +112 -0
  192. package/third-party/cargo/arrayvec@0.7.8/LICENSE-APACHE +201 -0
  193. package/third-party/cargo/arrayvec@0.7.8/LICENSE-MIT +25 -0
  194. package/third-party/cargo/ascii@1.1.0/Cargo.toml +41 -0
  195. package/third-party/cargo/ascii@1.1.0/LICENSE-APACHE +201 -0
  196. package/third-party/cargo/ascii@1.1.0/LICENSE-MIT +22 -0
  197. package/third-party/cargo/ash@0.38.0+1.3.281/Cargo.toml +66 -0
  198. package/third-party/cargo/ash@0.38.0+1.3.281/LICENSE-APACHE +67 -0
  199. package/third-party/cargo/ash@0.38.0+1.3.281/LICENSE-MIT +25 -0
  200. package/third-party/cargo/autocfg@1.5.1/Cargo.toml +75 -0
  201. package/third-party/cargo/autocfg@1.5.1/LICENSE-APACHE +201 -0
  202. package/third-party/cargo/autocfg@1.5.1/LICENSE-MIT +25 -0
  203. package/third-party/cargo/base64@0.13.1/Cargo.toml +53 -0
  204. package/third-party/cargo/base64@0.13.1/LICENSE-APACHE +201 -0
  205. package/third-party/cargo/base64@0.13.1/LICENSE-MIT +21 -0
  206. package/third-party/cargo/base64@0.22.1/Cargo.toml +85 -0
  207. package/third-party/cargo/base64@0.22.1/LICENSE-APACHE +201 -0
  208. package/third-party/cargo/base64@0.22.1/LICENSE-MIT +21 -0
  209. package/third-party/cargo/bit-set@0.10.0/Cargo.toml +108 -0
  210. package/third-party/cargo/bit-set@0.10.0/LICENSE-APACHE +201 -0
  211. package/third-party/cargo/bit-set@0.10.0/LICENSE-MIT +25 -0
  212. package/third-party/cargo/bit-vec@0.9.1/Cargo.toml +94 -0
  213. package/third-party/cargo/bit-vec@0.9.1/LICENSE-APACHE +201 -0
  214. package/third-party/cargo/bit-vec@0.9.1/LICENSE-MIT +25 -0
  215. package/third-party/cargo/bitflags@2.13.0/Cargo.toml +120 -0
  216. package/third-party/cargo/bitflags@2.13.0/LICENSE-APACHE +201 -0
  217. package/third-party/cargo/bitflags@2.13.0/LICENSE-MIT +25 -0
  218. package/third-party/cargo/block2@0.6.2/Cargo.toml +115 -0
  219. package/third-party/cargo/block2@0.6.2/MIT-terms.txt +22 -0
  220. package/third-party/cargo/block2@0.6.2/madsmtm-objc2-b4167b582b2f-LICENSE.md +34 -0
  221. package/third-party/cargo/bumpalo@3.20.3/Cargo.toml +99 -0
  222. package/third-party/cargo/bumpalo@3.20.3/LICENSE-APACHE +201 -0
  223. package/third-party/cargo/bumpalo@3.20.3/LICENSE-MIT +25 -0
  224. package/third-party/cargo/bytemuck@1.25.1/Cargo.toml +153 -0
  225. package/third-party/cargo/bytemuck@1.25.1/LICENSE-APACHE +61 -0
  226. package/third-party/cargo/bytemuck@1.25.1/LICENSE-MIT +9 -0
  227. package/third-party/cargo/bytemuck@1.25.1/LICENSE-ZLIB +11 -0
  228. package/third-party/cargo/bytemuck_derive@1.11.0/Cargo.toml +60 -0
  229. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-APACHE +61 -0
  230. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-MIT +9 -0
  231. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-ZLIB +11 -0
  232. package/third-party/cargo/byteorder-lite@0.1.0/Cargo.toml +57 -0
  233. package/third-party/cargo/byteorder-lite@0.1.0/LICENSE-MIT +21 -0
  234. package/third-party/cargo/byteorder-lite@0.1.0/UNLICENSE +24 -0
  235. package/third-party/cargo/byteorder@1.5.0/COPYING +3 -0
  236. package/third-party/cargo/byteorder@1.5.0/Cargo.toml +54 -0
  237. package/third-party/cargo/byteorder@1.5.0/LICENSE-MIT +21 -0
  238. package/third-party/cargo/byteorder@1.5.0/UNLICENSE +24 -0
  239. package/third-party/cargo/cfg-if@1.0.4/Cargo.toml +47 -0
  240. package/third-party/cargo/cfg-if@1.0.4/LICENSE-APACHE +201 -0
  241. package/third-party/cargo/cfg-if@1.0.4/LICENSE-MIT +25 -0
  242. package/third-party/cargo/cfg_aliases@0.2.1/Cargo.toml +43 -0
  243. package/third-party/cargo/cfg_aliases@0.2.1/LICENSE +9 -0
  244. package/third-party/cargo/chunked_transfer@1.5.0/Cargo.toml +27 -0
  245. package/third-party/cargo/chunked_transfer@1.5.0/LICENSE-APACHE +201 -0
  246. package/third-party/cargo/chunked_transfer@1.5.0/LICENSE-MIT +22 -0
  247. package/third-party/cargo/codespan-reporting@0.13.1/Cargo.toml +115 -0
  248. package/third-party/cargo/codespan-reporting@0.13.1/LICENSE +201 -0
  249. package/third-party/cargo/color_quant@1.1.0/Cargo.toml +20 -0
  250. package/third-party/cargo/color_quant@1.1.0/LICENSE +21 -0
  251. package/third-party/cargo/console_error_panic_hook@0.1.7/Cargo.toml +27 -0
  252. package/third-party/cargo/console_error_panic_hook@0.1.7/LICENSE-APACHE +201 -0
  253. package/third-party/cargo/console_error_panic_hook@0.1.7/LICENSE-MIT +25 -0
  254. package/third-party/cargo/core_maths@0.1.1/Cargo.toml +37 -0
  255. package/third-party/cargo/core_maths@0.1.1/LICENSE +21 -0
  256. package/third-party/cargo/cosmic-text@0.19.0/Cargo.toml +214 -0
  257. package/third-party/cargo/cosmic-text@0.19.0/LICENSE-APACHE +201 -0
  258. package/third-party/cargo/cosmic-text@0.19.0/LICENSE-MIT +21 -0
  259. package/third-party/cargo/crc32fast@1.5.0/Cargo.toml +68 -0
  260. package/third-party/cargo/crc32fast@1.5.0/LICENSE-APACHE +202 -0
  261. package/third-party/cargo/crc32fast@1.5.0/LICENSE-MIT +21 -0
  262. package/third-party/cargo/data-url@0.3.2/Cargo.toml +63 -0
  263. package/third-party/cargo/data-url@0.3.2/LICENSE-APACHE +201 -0
  264. package/third-party/cargo/data-url@0.3.2/LICENSE-MIT +25 -0
  265. package/third-party/cargo/dispatch2@0.3.1/Cargo.toml +122 -0
  266. package/third-party/cargo/dispatch2@0.3.1/MIT-terms.txt +22 -0
  267. package/third-party/cargo/dispatch2@0.3.1/madsmtm-objc2-8852b424193c-LICENSE.md +34 -0
  268. package/third-party/cargo/dlib@0.5.3/Cargo.toml +43 -0
  269. package/third-party/cargo/dlib@0.5.3/LICENSE.txt +19 -0
  270. package/third-party/cargo/document-features@0.2.12/Cargo.toml +51 -0
  271. package/third-party/cargo/document-features@0.2.12/LICENSE-APACHE +73 -0
  272. package/third-party/cargo/document-features@0.2.12/LICENSE-MIT +19 -0
  273. package/third-party/cargo/equivalent@1.0.2/Cargo.toml +37 -0
  274. package/third-party/cargo/equivalent@1.0.2/LICENSE-APACHE +201 -0
  275. package/third-party/cargo/equivalent@1.0.2/LICENSE-MIT +25 -0
  276. package/third-party/cargo/errno@0.3.14/Cargo.toml +67 -0
  277. package/third-party/cargo/errno@0.3.14/LICENSE-APACHE +201 -0
  278. package/third-party/cargo/errno@0.3.14/LICENSE-MIT +25 -0
  279. package/third-party/cargo/etagere@0.3.0/Cargo.toml +57 -0
  280. package/third-party/cargo/etagere@0.3.0/LICENSE-APACHE +13 -0
  281. package/third-party/cargo/etagere@0.3.0/LICENSE-MIT +20 -0
  282. package/third-party/cargo/euclid@0.22.14/COPYRIGHT +5 -0
  283. package/third-party/cargo/euclid@0.22.14/Cargo.toml +66 -0
  284. package/third-party/cargo/euclid@0.22.14/LICENSE-APACHE +201 -0
  285. package/third-party/cargo/euclid@0.22.14/LICENSE-MIT +25 -0
  286. package/third-party/cargo/fastrand@2.5.0/Cargo.toml +89 -0
  287. package/third-party/cargo/fastrand@2.5.0/LICENSE-APACHE +201 -0
  288. package/third-party/cargo/fastrand@2.5.0/LICENSE-MIT +23 -0
  289. package/third-party/cargo/fdeflate@0.3.7/Cargo.toml +55 -0
  290. package/third-party/cargo/fdeflate@0.3.7/LICENSE-APACHE +177 -0
  291. package/third-party/cargo/fdeflate@0.3.7/LICENSE-MIT +25 -0
  292. package/third-party/cargo/flate2@1.1.9/Cargo.toml +274 -0
  293. package/third-party/cargo/flate2@1.1.9/LICENSE-APACHE +201 -0
  294. package/third-party/cargo/flate2@1.1.9/LICENSE-MIT +25 -0
  295. package/third-party/cargo/float-cmp@0.9.0/Cargo.toml +39 -0
  296. package/third-party/cargo/float-cmp@0.9.0/LICENSE +19 -0
  297. package/third-party/cargo/float_next_after@1.0.0/Cargo.toml +43 -0
  298. package/third-party/cargo/float_next_after@1.0.0/LICENSE +23 -0
  299. package/third-party/cargo/foldhash@0.2.0/Cargo.toml +80 -0
  300. package/third-party/cargo/foldhash@0.2.0/LICENSE +19 -0
  301. package/third-party/cargo/font-types@0.11.3/Cargo.toml +55 -0
  302. package/third-party/cargo/font-types@0.11.3/LICENSE-APACHE +67 -0
  303. package/third-party/cargo/font-types@0.11.3/LICENSE-MIT +25 -0
  304. package/third-party/cargo/fontdb@0.23.0/Cargo.toml +83 -0
  305. package/third-party/cargo/fontdb@0.23.0/LICENSE +21 -0
  306. package/third-party/cargo/futures-core@0.3.32/Cargo.toml +66 -0
  307. package/third-party/cargo/futures-core@0.3.32/LICENSE-APACHE +202 -0
  308. package/third-party/cargo/futures-core@0.3.32/LICENSE-MIT +26 -0
  309. package/third-party/cargo/futures-task@0.3.32/Cargo.toml +58 -0
  310. package/third-party/cargo/futures-task@0.3.32/LICENSE-APACHE +202 -0
  311. package/third-party/cargo/futures-task@0.3.32/LICENSE-MIT +26 -0
  312. package/third-party/cargo/futures-util@0.3.32/Cargo.toml +181 -0
  313. package/third-party/cargo/futures-util@0.3.32/LICENSE-APACHE +202 -0
  314. package/third-party/cargo/futures-util@0.3.32/LICENSE-MIT +26 -0
  315. package/third-party/cargo/getrandom@0.4.3/Cargo.toml +165 -0
  316. package/third-party/cargo/getrandom@0.4.3/LICENSE-APACHE +201 -0
  317. package/third-party/cargo/getrandom@0.4.3/LICENSE-MIT +26 -0
  318. package/third-party/cargo/gif@0.14.2/Cargo.toml +84 -0
  319. package/third-party/cargo/gif@0.14.2/LICENSE-APACHE +201 -0
  320. package/third-party/cargo/gif@0.14.2/LICENSE-MIT +21 -0
  321. package/third-party/cargo/glam@0.33.2/Cargo.toml +354 -0
  322. package/third-party/cargo/glam@0.33.2/LICENSE-APACHE +201 -0
  323. package/third-party/cargo/glam@0.33.2/LICENSE-MIT +23 -0
  324. package/third-party/cargo/glow@0.17.0/Cargo.toml +122 -0
  325. package/third-party/cargo/glow@0.17.0/LICENSE-APACHE +201 -0
  326. package/third-party/cargo/glow@0.17.0/LICENSE-MIT +23 -0
  327. package/third-party/cargo/glow@0.17.0/LICENSE-ZLIB +15 -0
  328. package/third-party/cargo/gltf-derive@1.4.1/Cargo.toml +34 -0
  329. package/third-party/cargo/gltf-derive@1.4.1/LICENSE-APACHE +202 -0
  330. package/third-party/cargo/gltf-derive@1.4.1/LICENSE-MIT +26 -0
  331. package/third-party/cargo/gltf-json@1.4.1/Cargo.toml +50 -0
  332. package/third-party/cargo/gltf-json@1.4.1/LICENSE-APACHE +202 -0
  333. package/third-party/cargo/gltf-json@1.4.1/LICENSE-MIT +26 -0
  334. package/third-party/cargo/gltf@1.4.1/Cargo.toml +122 -0
  335. package/third-party/cargo/gltf@1.4.1/LICENSE-APACHE +202 -0
  336. package/third-party/cargo/gltf@1.4.1/LICENSE-MIT +26 -0
  337. package/third-party/cargo/glyphon@0.12.0/Cargo.toml +35 -0
  338. package/third-party/cargo/glyphon@0.12.0/LICENSE-APACHE +201 -0
  339. package/third-party/cargo/glyphon@0.12.0/LICENSE-MIT +23 -0
  340. package/third-party/cargo/glyphon@0.12.0/LICENSE-ZLIB +15 -0
  341. package/third-party/cargo/gpu-allocator@0.28.0/Cargo.toml +180 -0
  342. package/third-party/cargo/gpu-allocator@0.28.0/LICENSE-APACHE +201 -0
  343. package/third-party/cargo/gpu-allocator@0.28.0/LICENSE-MIT +7 -0
  344. package/third-party/cargo/grid@1.0.1/Cargo.toml +77 -0
  345. package/third-party/cargo/grid@1.0.1/LICENSE +21 -0
  346. package/third-party/cargo/half@2.7.1/Cargo.toml +137 -0
  347. package/third-party/cargo/half@2.7.1/LICENSE-APACHE +176 -0
  348. package/third-party/cargo/half@2.7.1/LICENSE-MIT +19 -0
  349. package/third-party/cargo/harfrust@0.5.2/Cargo.toml +115 -0
  350. package/third-party/cargo/harfrust@0.5.2/harfbuzz-harfrust-efdae3142ab7-LICENSE +22 -0
  351. package/third-party/cargo/hashbrown@0.16.1/Cargo.toml +180 -0
  352. package/third-party/cargo/hashbrown@0.16.1/LICENSE-APACHE +201 -0
  353. package/third-party/cargo/hashbrown@0.16.1/LICENSE-MIT +25 -0
  354. package/third-party/cargo/hashbrown@0.17.1/Cargo.toml +201 -0
  355. package/third-party/cargo/hashbrown@0.17.1/LICENSE-APACHE +201 -0
  356. package/third-party/cargo/hashbrown@0.17.1/LICENSE-MIT +25 -0
  357. package/third-party/cargo/httpdate@1.0.3/Cargo.toml +35 -0
  358. package/third-party/cargo/httpdate@1.0.3/LICENSE-APACHE +201 -0
  359. package/third-party/cargo/httpdate@1.0.3/LICENSE-MIT +19 -0
  360. package/third-party/cargo/image-webp@0.2.4/Cargo.toml +63 -0
  361. package/third-party/cargo/image-webp@0.2.4/LICENSE-APACHE +177 -0
  362. package/third-party/cargo/image-webp@0.2.4/LICENSE-MIT +25 -0
  363. package/third-party/cargo/image@0.25.10/Cargo.toml +248 -0
  364. package/third-party/cargo/image@0.25.10/LICENSE-APACHE +177 -0
  365. package/third-party/cargo/image@0.25.10/LICENSE-MIT +25 -0
  366. package/third-party/cargo/imagesize@0.14.0/Cargo.toml +104 -0
  367. package/third-party/cargo/imagesize@0.14.0/LICENSE +21 -0
  368. package/third-party/cargo/indexmap@2.14.0/Cargo.toml +167 -0
  369. package/third-party/cargo/indexmap@2.14.0/LICENSE-APACHE +201 -0
  370. package/third-party/cargo/indexmap@2.14.0/LICENSE-MIT +25 -0
  371. package/third-party/cargo/inflections@1.1.1/Cargo.toml +21 -0
  372. package/third-party/cargo/inflections@1.1.1/LICENSE +20 -0
  373. package/third-party/cargo/itoa@1.0.18/Cargo.toml +66 -0
  374. package/third-party/cargo/itoa@1.0.18/LICENSE-APACHE +176 -0
  375. package/third-party/cargo/itoa@1.0.18/LICENSE-MIT +23 -0
  376. package/third-party/cargo/js-sys@0.3.103/Cargo.toml +98 -0
  377. package/third-party/cargo/js-sys@0.3.103/LICENSE-APACHE +201 -0
  378. package/third-party/cargo/js-sys@0.3.103/LICENSE-MIT +25 -0
  379. package/third-party/cargo/khronos-egl@6.0.0/Cargo.toml +82 -0
  380. package/third-party/cargo/khronos-egl@6.0.0/LICENSE-APACHE +201 -0
  381. package/third-party/cargo/khronos-egl@6.0.0/LICENSE-MIT +23 -0
  382. package/third-party/cargo/kurbo@0.13.1/Cargo.toml +230 -0
  383. package/third-party/cargo/kurbo@0.13.1/LICENSE-APACHE +202 -0
  384. package/third-party/cargo/kurbo@0.13.1/LICENSE-MIT +25 -0
  385. package/third-party/cargo/lazy_static@1.5.0/Cargo.toml +46 -0
  386. package/third-party/cargo/lazy_static@1.5.0/LICENSE-APACHE +201 -0
  387. package/third-party/cargo/lazy_static@1.5.0/LICENSE-MIT +25 -0
  388. package/third-party/cargo/libc@0.2.186/Cargo.toml +229 -0
  389. package/third-party/cargo/libc@0.2.186/LICENSE-APACHE +176 -0
  390. package/third-party/cargo/libc@0.2.186/LICENSE-MIT +25 -0
  391. package/third-party/cargo/libloading@0.8.9/Cargo.toml +90 -0
  392. package/third-party/cargo/libloading@0.8.9/LICENSE +12 -0
  393. package/third-party/cargo/libm@0.2.16/Cargo.toml +61 -0
  394. package/third-party/cargo/libm@0.2.16/LICENSE.txt +258 -0
  395. package/third-party/cargo/linebender_resource_handle@0.1.1/Cargo.toml +107 -0
  396. package/third-party/cargo/linebender_resource_handle@0.1.1/LICENSE-APACHE +176 -0
  397. package/third-party/cargo/linebender_resource_handle@0.1.1/LICENSE-MIT +19 -0
  398. package/third-party/cargo/litrs@1.0.0/Cargo.toml +63 -0
  399. package/third-party/cargo/litrs@1.0.0/LICENSE-APACHE +176 -0
  400. package/third-party/cargo/litrs@1.0.0/LICENSE-MIT +25 -0
  401. package/third-party/cargo/lock_api@0.4.14/Cargo.toml +68 -0
  402. package/third-party/cargo/lock_api@0.4.14/LICENSE-APACHE +201 -0
  403. package/third-party/cargo/lock_api@0.4.14/LICENSE-MIT +25 -0
  404. package/third-party/cargo/log@0.4.33/Cargo.toml +152 -0
  405. package/third-party/cargo/log@0.4.33/LICENSE-APACHE +201 -0
  406. package/third-party/cargo/log@0.4.33/LICENSE-MIT +25 -0
  407. package/third-party/cargo/lru@0.16.4/Cargo.toml +47 -0
  408. package/third-party/cargo/lru@0.16.4/LICENSE +21 -0
  409. package/third-party/cargo/lyon_geom@1.0.19/Cargo.toml +69 -0
  410. package/third-party/cargo/lyon_geom@1.0.19/nical-lyon-56219c95c658-LICENSE-APACHE +13 -0
  411. package/third-party/cargo/lyon_geom@1.0.19/nical-lyon-56219c95c658-LICENSE-MIT +20 -0
  412. package/third-party/cargo/lyon_path@1.0.19/Cargo.toml +58 -0
  413. package/third-party/cargo/lyon_path@1.0.19/nical-lyon-56219c95c658-LICENSE-APACHE +13 -0
  414. package/third-party/cargo/lyon_path@1.0.19/nical-lyon-56219c95c658-LICENSE-MIT +20 -0
  415. package/third-party/cargo/lyon_tessellation@1.0.20/Cargo.toml +71 -0
  416. package/third-party/cargo/lyon_tessellation@1.0.20/nical-lyon-7fa75ea8eea3-LICENSE-APACHE +13 -0
  417. package/third-party/cargo/lyon_tessellation@1.0.20/nical-lyon-7fa75ea8eea3-LICENSE-MIT +20 -0
  418. package/third-party/cargo/memchr@2.8.3/COPYING +3 -0
  419. package/third-party/cargo/memchr@2.8.3/Cargo.toml +89 -0
  420. package/third-party/cargo/memchr@2.8.3/LICENSE-MIT +21 -0
  421. package/third-party/cargo/memchr@2.8.3/UNLICENSE +24 -0
  422. package/third-party/cargo/memmap2@0.9.11/Cargo.toml +59 -0
  423. package/third-party/cargo/memmap2@0.9.11/LICENSE-APACHE +201 -0
  424. package/third-party/cargo/memmap2@0.9.11/LICENSE-MIT +26 -0
  425. package/third-party/cargo/miniz_oxide@0.8.9/Cargo.toml +91 -0
  426. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE +25 -0
  427. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-APACHE.md +177 -0
  428. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-MIT.md +24 -0
  429. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-ZLIB.md +14 -0
  430. package/third-party/cargo/moxcms@0.8.1/Cargo.toml +113 -0
  431. package/third-party/cargo/moxcms@0.8.1/LICENSE-APACHE.md +201 -0
  432. package/third-party/cargo/moxcms@0.8.1/LICENSE.md +26 -0
  433. package/third-party/cargo/naga-types@30.0.0/Cargo.toml +94 -0
  434. package/third-party/cargo/naga-types@30.0.0/LICENSE.APACHE +176 -0
  435. package/third-party/cargo/naga-types@30.0.0/LICENSE.MIT +21 -0
  436. package/third-party/cargo/naga@30.0.0/Cargo.toml +246 -0
  437. package/third-party/cargo/naga@30.0.0/LICENSE.APACHE +176 -0
  438. package/third-party/cargo/naga@30.0.0/LICENSE.MIT +21 -0
  439. package/third-party/cargo/num-traits@0.2.19/Cargo.toml +54 -0
  440. package/third-party/cargo/num-traits@0.2.19/LICENSE-APACHE +201 -0
  441. package/third-party/cargo/num-traits@0.2.19/LICENSE-MIT +25 -0
  442. package/third-party/cargo/objc2-core-foundation@0.3.2/Cargo.toml +221 -0
  443. package/third-party/cargo/objc2-core-foundation@0.3.2/MIT-terms.txt +22 -0
  444. package/third-party/cargo/objc2-core-foundation@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  445. package/third-party/cargo/objc2-core-graphics@0.3.2/Cargo.toml +331 -0
  446. package/third-party/cargo/objc2-core-graphics@0.3.2/MIT-terms.txt +22 -0
  447. package/third-party/cargo/objc2-core-graphics@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  448. package/third-party/cargo/objc2-encode@4.1.0/Cargo.toml +81 -0
  449. package/third-party/cargo/objc2-encode@4.1.0/MIT-terms.txt +22 -0
  450. package/third-party/cargo/objc2-encode@4.1.0/madsmtm-objc2-8d214f547736-LICENSE.md +34 -0
  451. package/third-party/cargo/objc2-foundation@0.3.2/Cargo.toml +529 -0
  452. package/third-party/cargo/objc2-foundation@0.3.2/MIT-terms.txt +22 -0
  453. package/third-party/cargo/objc2-foundation@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  454. package/third-party/cargo/objc2-io-surface@0.3.2/Cargo.toml +139 -0
  455. package/third-party/cargo/objc2-io-surface@0.3.2/MIT-terms.txt +22 -0
  456. package/third-party/cargo/objc2-io-surface@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  457. package/third-party/cargo/objc2-metal@0.3.2/Cargo.toml +601 -0
  458. package/third-party/cargo/objc2-metal@0.3.2/MIT-terms.txt +22 -0
  459. package/third-party/cargo/objc2-metal@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  460. package/third-party/cargo/objc2-quartz-core@0.3.2/Cargo.toml +302 -0
  461. package/third-party/cargo/objc2-quartz-core@0.3.2/MIT-terms.txt +22 -0
  462. package/third-party/cargo/objc2-quartz-core@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  463. package/third-party/cargo/objc2@0.6.4/Cargo.toml +232 -0
  464. package/third-party/cargo/objc2@0.6.4/MIT-terms.txt +22 -0
  465. package/third-party/cargo/objc2@0.6.4/madsmtm-objc2-8852b424193c-LICENSE.md +34 -0
  466. package/third-party/cargo/once_cell@1.21.4/Cargo.toml +119 -0
  467. package/third-party/cargo/once_cell@1.21.4/LICENSE-APACHE +201 -0
  468. package/third-party/cargo/once_cell@1.21.4/LICENSE-MIT +23 -0
  469. package/third-party/cargo/ordered-float@5.3.0/Cargo.toml +162 -0
  470. package/third-party/cargo/ordered-float@5.3.0/LICENSE-MIT +25 -0
  471. package/third-party/cargo/parking_lot@0.12.5/Cargo.toml +87 -0
  472. package/third-party/cargo/parking_lot@0.12.5/LICENSE-APACHE +201 -0
  473. package/third-party/cargo/parking_lot@0.12.5/LICENSE-MIT +25 -0
  474. package/third-party/cargo/parking_lot_core@0.9.12/Cargo.toml +72 -0
  475. package/third-party/cargo/parking_lot_core@0.9.12/LICENSE-APACHE +201 -0
  476. package/third-party/cargo/parking_lot_core@0.9.12/LICENSE-MIT +25 -0
  477. package/third-party/cargo/pico-args@0.5.0/Cargo.toml +32 -0
  478. package/third-party/cargo/pico-args@0.5.0/LICENSE +20 -0
  479. package/third-party/cargo/pin-project-lite@0.2.17/Cargo.toml +198 -0
  480. package/third-party/cargo/pin-project-lite@0.2.17/LICENSE-APACHE +177 -0
  481. package/third-party/cargo/pin-project-lite@0.2.17/LICENSE-MIT +23 -0
  482. package/third-party/cargo/pkg-config@0.3.33/Cargo.toml +43 -0
  483. package/third-party/cargo/pkg-config@0.3.33/LICENSE-APACHE +201 -0
  484. package/third-party/cargo/pkg-config@0.3.33/LICENSE-MIT +25 -0
  485. package/third-party/cargo/png@0.18.1/Cargo.toml +130 -0
  486. package/third-party/cargo/png@0.18.1/LICENSE-APACHE +201 -0
  487. package/third-party/cargo/png@0.18.1/LICENSE-MIT +25 -0
  488. package/third-party/cargo/pollster@0.4.0/Cargo.toml +53 -0
  489. package/third-party/cargo/pollster@0.4.0/LICENSE-APACHE +201 -0
  490. package/third-party/cargo/pollster@0.4.0/LICENSE-MIT +25 -0
  491. package/third-party/cargo/polycool@0.4.0/Cargo.toml +83 -0
  492. package/third-party/cargo/polycool@0.4.0/LICENSE-APACHE +202 -0
  493. package/third-party/cargo/polycool@0.4.0/LICENSE-MIT +25 -0
  494. package/third-party/cargo/pp-rs@0.2.1/Cargo.toml +23 -0
  495. package/third-party/cargo/pp-rs@0.2.1/LICENSE +29 -0
  496. package/third-party/cargo/presser@0.3.1/Cargo.toml +58 -0
  497. package/third-party/cargo/presser@0.3.1/LICENSE-APACHE +201 -0
  498. package/third-party/cargo/presser@0.3.1/LICENSE-MIT +25 -0
  499. package/third-party/cargo/proc-macro2@1.0.106/Cargo.toml +105 -0
  500. package/third-party/cargo/proc-macro2@1.0.106/LICENSE-APACHE +176 -0
  501. package/third-party/cargo/proc-macro2@1.0.106/LICENSE-MIT +23 -0
  502. package/third-party/cargo/profiling@1.0.18/Cargo.toml +96 -0
  503. package/third-party/cargo/profiling@1.0.18/aclysma-profiling-8271551172eb-LICENSE-APACHE +201 -0
  504. package/third-party/cargo/profiling@1.0.18/aclysma-profiling-8271551172eb-LICENSE-MIT +21 -0
  505. package/third-party/cargo/pxfm@0.1.30/Cargo.toml +53 -0
  506. package/third-party/cargo/pxfm@0.1.30/LICENSE-APACHE.md +201 -0
  507. package/third-party/cargo/pxfm@0.1.30/LICENSE.md +26 -0
  508. package/third-party/cargo/quick-error@2.0.1/Cargo.toml +24 -0
  509. package/third-party/cargo/quick-error@2.0.1/LICENSE-APACHE +202 -0
  510. package/third-party/cargo/quick-error@2.0.1/LICENSE-MIT +19 -0
  511. package/third-party/cargo/quote@1.0.46/Cargo.toml +70 -0
  512. package/third-party/cargo/quote@1.0.46/LICENSE-APACHE +176 -0
  513. package/third-party/cargo/quote@1.0.46/LICENSE-MIT +23 -0
  514. package/third-party/cargo/rangemap@1.7.1/Cargo.toml +91 -0
  515. package/third-party/cargo/rangemap@1.7.1/LICENSE-APACHE +191 -0
  516. package/third-party/cargo/rangemap@1.7.1/LICENSE-MIT +7 -0
  517. package/third-party/cargo/raw-window-handle@0.6.2/Cargo.toml +56 -0
  518. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-APACHE.md +177 -0
  519. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-MIT.md +21 -0
  520. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-ZLIB.md +11 -0
  521. package/third-party/cargo/raw-window-metal@1.1.0/Cargo.toml +111 -0
  522. package/third-party/cargo/raw-window-metal@1.1.0/LICENSE-APACHE +202 -0
  523. package/third-party/cargo/raw-window-metal@1.1.0/LICENSE-MIT +17 -0
  524. package/third-party/cargo/read-fonts@0.37.0/Cargo.toml +95 -0
  525. package/third-party/cargo/read-fonts@0.37.0/LICENSE-APACHE +67 -0
  526. package/third-party/cargo/read-fonts@0.37.0/LICENSE-MIT +25 -0
  527. package/third-party/cargo/read-fonts@0.39.2/Cargo.toml +96 -0
  528. package/third-party/cargo/read-fonts@0.39.2/LICENSE-APACHE +67 -0
  529. package/third-party/cargo/read-fonts@0.39.2/LICENSE-MIT +25 -0
  530. package/third-party/cargo/renderdoc-sys@1.1.0/Cargo.toml +39 -0
  531. package/third-party/cargo/renderdoc-sys@1.1.0/LICENSE-APACHE +201 -0
  532. package/third-party/cargo/renderdoc-sys@1.1.0/LICENSE-MIT +25 -0
  533. package/third-party/cargo/resvg@0.47.0/Cargo.toml +112 -0
  534. package/third-party/cargo/resvg@0.47.0/LICENSE-APACHE +176 -0
  535. package/third-party/cargo/resvg@0.47.0/LICENSE-MIT +25 -0
  536. package/third-party/cargo/rgb@0.8.53/Cargo.toml +110 -0
  537. package/third-party/cargo/rgb@0.8.53/LICENSE +21 -0
  538. package/third-party/cargo/roxmltree@0.21.1/Cargo.toml +75 -0
  539. package/third-party/cargo/roxmltree@0.21.1/LICENSE-APACHE +201 -0
  540. package/third-party/cargo/roxmltree@0.21.1/LICENSE-MIT +21 -0
  541. package/third-party/cargo/rustc-hash@1.1.0/Cargo.toml +25 -0
  542. package/third-party/cargo/rustc-hash@1.1.0/LICENSE-APACHE +201 -0
  543. package/third-party/cargo/rustc-hash@1.1.0/LICENSE-MIT +23 -0
  544. package/third-party/cargo/rustc-hash@2.1.3/Cargo.toml +50 -0
  545. package/third-party/cargo/rustc-hash@2.1.3/LICENSE-APACHE +176 -0
  546. package/third-party/cargo/rustc-hash@2.1.3/LICENSE-MIT +23 -0
  547. package/third-party/cargo/rustix@1.1.4/COPYRIGHT +29 -0
  548. package/third-party/cargo/rustix@1.1.4/Cargo.toml +292 -0
  549. package/third-party/cargo/rustix@1.1.4/LICENSE-APACHE +201 -0
  550. package/third-party/cargo/rustix@1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
  551. package/third-party/cargo/rustix@1.1.4/LICENSE-MIT +23 -0
  552. package/third-party/cargo/rustversion@1.0.23/Cargo.toml +69 -0
  553. package/third-party/cargo/rustversion@1.0.23/LICENSE-APACHE +176 -0
  554. package/third-party/cargo/rustversion@1.0.23/LICENSE-MIT +23 -0
  555. package/third-party/cargo/rustybuzz@0.20.1/Cargo.toml +110 -0
  556. package/third-party/cargo/rustybuzz@0.20.1/LICENSE +22 -0
  557. package/third-party/cargo/scopeguard@1.2.0/Cargo.toml +43 -0
  558. package/third-party/cargo/scopeguard@1.2.0/LICENSE-APACHE +201 -0
  559. package/third-party/cargo/scopeguard@1.2.0/LICENSE-MIT +25 -0
  560. package/third-party/cargo/self_cell@1.2.2/Cargo.toml +33 -0
  561. package/third-party/cargo/self_cell@1.2.2/LICENSE-APACHE +201 -0
  562. package/third-party/cargo/self_cell@1.2.2/LICENSE-GPLv2 +339 -0
  563. package/third-party/cargo/self_cell@1.3.0/Cargo.toml +33 -0
  564. package/third-party/cargo/self_cell@1.3.0/LICENSE-APACHE +201 -0
  565. package/third-party/cargo/self_cell@1.3.0/LICENSE-GPLv2 +339 -0
  566. package/third-party/cargo/serde@1.0.228/Cargo.toml +84 -0
  567. package/third-party/cargo/serde@1.0.228/LICENSE-APACHE +176 -0
  568. package/third-party/cargo/serde@1.0.228/LICENSE-MIT +23 -0
  569. package/third-party/cargo/serde_core@1.0.228/Cargo.toml +87 -0
  570. package/third-party/cargo/serde_core@1.0.228/LICENSE-APACHE +176 -0
  571. package/third-party/cargo/serde_core@1.0.228/LICENSE-MIT +23 -0
  572. package/third-party/cargo/serde_derive@1.0.228/Cargo.toml +87 -0
  573. package/third-party/cargo/serde_derive@1.0.228/LICENSE-APACHE +176 -0
  574. package/third-party/cargo/serde_derive@1.0.228/LICENSE-MIT +23 -0
  575. package/third-party/cargo/serde_json@1.0.150/Cargo.toml +162 -0
  576. package/third-party/cargo/serde_json@1.0.150/LICENSE-APACHE +176 -0
  577. package/third-party/cargo/serde_json@1.0.150/LICENSE-MIT +23 -0
  578. package/third-party/cargo/simd-adler32@0.3.10/Cargo.toml +68 -0
  579. package/third-party/cargo/simd-adler32@0.3.10/LICENSE.md +21 -0
  580. package/third-party/cargo/simplecss@0.2.2/Cargo.toml +146 -0
  581. package/third-party/cargo/simplecss@0.2.2/LICENSE-APACHE +201 -0
  582. package/third-party/cargo/simplecss@0.2.2/LICENSE-MIT +21 -0
  583. package/third-party/cargo/siphasher@1.0.3/COPYING +7 -0
  584. package/third-party/cargo/siphasher@1.0.3/Cargo.toml +64 -0
  585. package/third-party/cargo/skrifa@0.40.0/Cargo.toml +86 -0
  586. package/third-party/cargo/skrifa@0.40.0/LICENSE-APACHE +67 -0
  587. package/third-party/cargo/skrifa@0.40.0/LICENSE-MIT +25 -0
  588. package/third-party/cargo/skrifa@0.42.1/Cargo.toml +86 -0
  589. package/third-party/cargo/skrifa@0.42.1/LICENSE-APACHE +67 -0
  590. package/third-party/cargo/skrifa@0.42.1/LICENSE-MIT +25 -0
  591. package/third-party/cargo/slab@0.4.12/Cargo.toml +67 -0
  592. package/third-party/cargo/slab@0.4.12/LICENSE +25 -0
  593. package/third-party/cargo/slotmap@1.1.1/Cargo.toml +83 -0
  594. package/third-party/cargo/slotmap@1.1.1/LICENSE +19 -0
  595. package/third-party/cargo/smallvec@1.15.2/Cargo.toml +103 -0
  596. package/third-party/cargo/smallvec@1.15.2/LICENSE-APACHE +201 -0
  597. package/third-party/cargo/smallvec@1.15.2/LICENSE-MIT +25 -0
  598. package/third-party/cargo/smol_str@0.3.6/Cargo.toml +155 -0
  599. package/third-party/cargo/smol_str@0.3.6/LICENSE-APACHE +201 -0
  600. package/third-party/cargo/smol_str@0.3.6/LICENSE-MIT +23 -0
  601. package/third-party/cargo/spirv@0.4.0+sdk-1.4.341.0/Cargo.toml +56 -0
  602. package/third-party/cargo/spirv@0.4.0+sdk-1.4.341.0/gfx-rs-rspirv-8afc3d0ac8e1-LICENSE +202 -0
  603. package/third-party/cargo/static_assertions@1.1.0/Cargo.toml +39 -0
  604. package/third-party/cargo/static_assertions@1.1.0/LICENSE-APACHE +202 -0
  605. package/third-party/cargo/static_assertions@1.1.0/LICENSE-MIT +21 -0
  606. package/third-party/cargo/strict-num@0.1.1/Cargo.toml +35 -0
  607. package/third-party/cargo/strict-num@0.1.1/LICENSE +19 -0
  608. package/third-party/cargo/svgtypes@0.16.1/Cargo.toml +57 -0
  609. package/third-party/cargo/svgtypes@0.16.1/LICENSE-APACHE +201 -0
  610. package/third-party/cargo/svgtypes@0.16.1/LICENSE-MIT +20 -0
  611. package/third-party/cargo/swash@0.2.9/Cargo.toml +93 -0
  612. package/third-party/cargo/swash@0.2.9/LICENSE-APACHE +201 -0
  613. package/third-party/cargo/swash@0.2.9/LICENSE-MIT +25 -0
  614. package/third-party/cargo/syn@2.0.118/Cargo.toml +272 -0
  615. package/third-party/cargo/syn@2.0.118/LICENSE-APACHE +176 -0
  616. package/third-party/cargo/syn@2.0.118/LICENSE-MIT +23 -0
  617. package/third-party/cargo/sys-locale@0.3.2/Cargo.toml +73 -0
  618. package/third-party/cargo/sys-locale@0.3.2/LICENSE-APACHE +201 -0
  619. package/third-party/cargo/sys-locale@0.3.2/LICENSE-MIT +21 -0
  620. package/third-party/cargo/taffy@0.12.1/Cargo.toml +171 -0
  621. package/third-party/cargo/taffy@0.12.1/DioxusLabs-taffy-1c9e37a0a1cf-LICENSE.md +25 -0
  622. package/third-party/cargo/tempfile@3.27.0/Cargo.toml +105 -0
  623. package/third-party/cargo/tempfile@3.27.0/LICENSE-APACHE +201 -0
  624. package/third-party/cargo/tempfile@3.27.0/LICENSE-MIT +25 -0
  625. package/third-party/cargo/termcolor@1.4.1/COPYING +3 -0
  626. package/third-party/cargo/termcolor@1.4.1/Cargo.toml +40 -0
  627. package/third-party/cargo/termcolor@1.4.1/LICENSE-MIT +21 -0
  628. package/third-party/cargo/termcolor@1.4.1/UNLICENSE +24 -0
  629. package/third-party/cargo/thiserror-impl@2.0.18/Cargo.toml +52 -0
  630. package/third-party/cargo/thiserror-impl@2.0.18/LICENSE-APACHE +176 -0
  631. package/third-party/cargo/thiserror-impl@2.0.18/LICENSE-MIT +23 -0
  632. package/third-party/cargo/thiserror@2.0.18/Cargo.toml +119 -0
  633. package/third-party/cargo/thiserror@2.0.18/LICENSE-APACHE +176 -0
  634. package/third-party/cargo/thiserror@2.0.18/LICENSE-MIT +23 -0
  635. package/third-party/cargo/tiny-skia-path@0.12.0/Cargo.toml +58 -0
  636. package/third-party/cargo/tiny-skia-path@0.12.0/LICENSE +30 -0
  637. package/third-party/cargo/tiny-skia@0.12.0/Cargo.toml +116 -0
  638. package/third-party/cargo/tiny-skia@0.12.0/LICENSE +30 -0
  639. package/third-party/cargo/tiny_http@0.12.0/Cargo.toml +82 -0
  640. package/third-party/cargo/tiny_http@0.12.0/LICENSE-APACHE +201 -0
  641. package/third-party/cargo/tiny_http@0.12.0/LICENSE-MIT +25 -0
  642. package/third-party/cargo/tinyvec@1.12.0/Cargo.toml +184 -0
  643. package/third-party/cargo/tinyvec@1.12.0/LICENSE-APACHE.md +202 -0
  644. package/third-party/cargo/tinyvec@1.12.0/LICENSE-MIT.md +5 -0
  645. package/third-party/cargo/tinyvec@1.12.0/LICENSE-ZLIB.md +11 -0
  646. package/third-party/cargo/tinyvec_macros@0.1.1/Cargo.toml +19 -0
  647. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-APACHE.md +202 -0
  648. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-MIT.md +21 -0
  649. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-ZLIB.md +20 -0
  650. package/third-party/cargo/ttf-parser@0.25.1/Cargo.toml +101 -0
  651. package/third-party/cargo/ttf-parser@0.25.1/LICENSE-APACHE +201 -0
  652. package/third-party/cargo/ttf-parser@0.25.1/LICENSE-MIT +20 -0
  653. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/Cargo.toml +22 -0
  654. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/LICENSE-APACHE +201 -0
  655. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/LICENSE-MIT +21 -0
  656. package/third-party/cargo/unicode-bidi@0.3.18/COPYRIGHT +8 -0
  657. package/third-party/cargo/unicode-bidi@0.3.18/Cargo.toml +90 -0
  658. package/third-party/cargo/unicode-bidi@0.3.18/LICENSE-APACHE +201 -0
  659. package/third-party/cargo/unicode-bidi@0.3.18/LICENSE-MIT +25 -0
  660. package/third-party/cargo/unicode-ccc@0.4.0/Cargo.toml +22 -0
  661. package/third-party/cargo/unicode-ccc@0.4.0/LICENSE-APACHE +201 -0
  662. package/third-party/cargo/unicode-ccc@0.4.0/LICENSE-MIT +21 -0
  663. package/third-party/cargo/unicode-ident@1.0.24/Cargo.toml +84 -0
  664. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-APACHE +176 -0
  665. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-MIT +23 -0
  666. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-UNICODE +39 -0
  667. package/third-party/cargo/unicode-linebreak@0.1.5/Cargo.toml +32 -0
  668. package/third-party/cargo/unicode-linebreak@0.1.5/LICENSE +201 -0
  669. package/third-party/cargo/unicode-properties@0.1.4/COPYRIGHT +7 -0
  670. package/third-party/cargo/unicode-properties@0.1.4/Cargo.toml +65 -0
  671. package/third-party/cargo/unicode-properties@0.1.4/LICENSE-APACHE +201 -0
  672. package/third-party/cargo/unicode-properties@0.1.4/LICENSE-MIT +25 -0
  673. package/third-party/cargo/unicode-script@0.5.8/Cargo.toml +63 -0
  674. package/third-party/cargo/unicode-script@0.5.8/LICENSE-APACHE +201 -0
  675. package/third-party/cargo/unicode-script@0.5.8/LICENSE-MIT +27 -0
  676. package/third-party/cargo/unicode-segmentation@1.13.3/COPYRIGHT +7 -0
  677. package/third-party/cargo/unicode-segmentation@1.13.3/Cargo.toml +91 -0
  678. package/third-party/cargo/unicode-segmentation@1.13.3/LICENSE-APACHE +201 -0
  679. package/third-party/cargo/unicode-segmentation@1.13.3/LICENSE-MIT +25 -0
  680. package/third-party/cargo/unicode-vo@0.1.0/Cargo.toml +22 -0
  681. package/third-party/cargo/unicode-vo@0.1.0/LICENSE-APACHE +201 -0
  682. package/third-party/cargo/unicode-vo@0.1.0/LICENSE-MIT +21 -0
  683. package/third-party/cargo/unicode-width@0.2.2/COPYRIGHT +7 -0
  684. package/third-party/cargo/unicode-width@0.2.2/Cargo.toml +77 -0
  685. package/third-party/cargo/unicode-width@0.2.2/LICENSE-APACHE +201 -0
  686. package/third-party/cargo/unicode-width@0.2.2/LICENSE-MIT +25 -0
  687. package/third-party/cargo/unicode-xid@0.2.6/COPYRIGHT +7 -0
  688. package/third-party/cargo/unicode-xid@0.2.6/Cargo.toml +65 -0
  689. package/third-party/cargo/unicode-xid@0.2.6/LICENSE-APACHE +201 -0
  690. package/third-party/cargo/unicode-xid@0.2.6/LICENSE-MIT +25 -0
  691. package/third-party/cargo/urlencoding@2.1.3/Cargo.toml +41 -0
  692. package/third-party/cargo/urlencoding@2.1.3/LICENSE +20 -0
  693. package/third-party/cargo/usvg@0.47.0/Cargo.toml +138 -0
  694. package/third-party/cargo/usvg@0.47.0/LICENSE-APACHE +176 -0
  695. package/third-party/cargo/usvg@0.47.0/LICENSE-MIT +25 -0
  696. package/third-party/cargo/version_check@0.9.5/Cargo.toml +38 -0
  697. package/third-party/cargo/version_check@0.9.5/LICENSE-APACHE +201 -0
  698. package/third-party/cargo/version_check@0.9.5/LICENSE-MIT +19 -0
  699. package/third-party/cargo/wasm-bindgen-futures@0.4.76/Cargo.toml +88 -0
  700. package/third-party/cargo/wasm-bindgen-futures@0.4.76/LICENSE-APACHE +201 -0
  701. package/third-party/cargo/wasm-bindgen-futures@0.4.76/LICENSE-MIT +25 -0
  702. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/Cargo.toml +83 -0
  703. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/LICENSE-APACHE +201 -0
  704. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/LICENSE-MIT +25 -0
  705. package/third-party/cargo/wasm-bindgen-macro@0.2.126/Cargo.toml +73 -0
  706. package/third-party/cargo/wasm-bindgen-macro@0.2.126/LICENSE-APACHE +201 -0
  707. package/third-party/cargo/wasm-bindgen-macro@0.2.126/LICENSE-MIT +25 -0
  708. package/third-party/cargo/wasm-bindgen-shared@0.2.126/Cargo.toml +66 -0
  709. package/third-party/cargo/wasm-bindgen-shared@0.2.126/LICENSE-APACHE +201 -0
  710. package/third-party/cargo/wasm-bindgen-shared@0.2.126/LICENSE-MIT +25 -0
  711. package/third-party/cargo/wasm-bindgen@0.2.126/Cargo.toml +122 -0
  712. package/third-party/cargo/wasm-bindgen@0.2.126/LICENSE-APACHE +201 -0
  713. package/third-party/cargo/wasm-bindgen@0.2.126/LICENSE-MIT +25 -0
  714. package/third-party/cargo/wayland-sys@0.31.11/Cargo.toml +81 -0
  715. package/third-party/cargo/wayland-sys@0.31.11/LICENSE.txt +19 -0
  716. package/third-party/cargo/web-sys@0.3.103/Cargo.toml +2823 -0
  717. package/third-party/cargo/web-sys@0.3.103/LICENSE-APACHE +201 -0
  718. package/third-party/cargo/web-sys@0.3.103/LICENSE-MIT +25 -0
  719. package/third-party/cargo/weezl@0.1.12/Cargo.toml +120 -0
  720. package/third-party/cargo/weezl@0.1.12/LICENSE-APACHE +201 -0
  721. package/third-party/cargo/weezl@0.1.12/LICENSE-MIT +22 -0
  722. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/Cargo.toml +53 -0
  723. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/LICENSE.APACHE +176 -0
  724. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/LICENSE.MIT +21 -0
  725. package/third-party/cargo/wgpu-core@30.0.0/Cargo.toml +237 -0
  726. package/third-party/cargo/wgpu-core@30.0.0/LICENSE.APACHE +176 -0
  727. package/third-party/cargo/wgpu-core@30.0.0/LICENSE.MIT +21 -0
  728. package/third-party/cargo/wgpu-hal@30.0.0/Cargo.toml +541 -0
  729. package/third-party/cargo/wgpu-hal@30.0.0/LICENSE.APACHE +176 -0
  730. package/third-party/cargo/wgpu-hal@30.0.0/LICENSE.MIT +21 -0
  731. package/third-party/cargo/wgpu-naga-bridge@30.0.0/Cargo.toml +46 -0
  732. package/third-party/cargo/wgpu-naga-bridge@30.0.0/LICENSE.APACHE +176 -0
  733. package/third-party/cargo/wgpu-naga-bridge@30.0.0/LICENSE.MIT +21 -0
  734. package/third-party/cargo/wgpu-types@30.0.0/Cargo.toml +161 -0
  735. package/third-party/cargo/wgpu-types@30.0.0/LICENSE.APACHE +176 -0
  736. package/third-party/cargo/wgpu-types@30.0.0/LICENSE.MIT +21 -0
  737. package/third-party/cargo/wgpu@30.0.0/Cargo.toml +278 -0
  738. package/third-party/cargo/wgpu@30.0.0/LICENSE.APACHE +176 -0
  739. package/third-party/cargo/wgpu@30.0.0/LICENSE.MIT +21 -0
  740. package/third-party/cargo/xmlwriter@0.1.0/Cargo.toml +23 -0
  741. package/third-party/cargo/xmlwriter@0.1.0/LICENSE +21 -0
  742. package/third-party/cargo/yazi@0.2.1/Cargo.toml +45 -0
  743. package/third-party/cargo/yazi@0.2.1/LICENSE-APACHE +201 -0
  744. package/third-party/cargo/yazi@0.2.1/LICENSE-MIT +19 -0
  745. package/third-party/cargo/zeno@0.3.3/Cargo.toml +65 -0
  746. package/third-party/cargo/zeno@0.3.3/LICENSE-APACHE +201 -0
  747. package/third-party/cargo/zeno@0.3.3/LICENSE-MIT +25 -0
  748. package/third-party/cargo/zerocopy-derive@0.8.54/Cargo.toml +209 -0
  749. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-APACHE +202 -0
  750. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-BSD +24 -0
  751. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-MIT +26 -0
  752. package/third-party/cargo/zerocopy@0.8.54/Cargo.toml +419 -0
  753. package/third-party/cargo/zerocopy@0.8.54/LICENSE-APACHE +202 -0
  754. package/third-party/cargo/zerocopy@0.8.54/LICENSE-BSD +24 -0
  755. package/third-party/cargo/zerocopy@0.8.54/LICENSE-MIT +26 -0
  756. package/third-party/cargo/zmij@1.0.23/Cargo.toml +90 -0
  757. package/third-party/cargo/zmij@1.0.23/LICENSE-MIT +23 -0
  758. package/third-party/cargo/zune-core@0.5.1/Cargo.toml +47 -0
  759. package/third-party/cargo/zune-core@0.5.1/LICENSE-APACHE +201 -0
  760. package/third-party/cargo/zune-core@0.5.1/LICENSE-MIT +21 -0
  761. package/third-party/cargo/zune-core@0.5.1/LICENSE-ZLIB +19 -0
  762. package/third-party/cargo/zune-jpeg@0.5.15/Cargo.toml +67 -0
  763. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-APACHE +201 -0
  764. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-MIT +21 -0
  765. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-ZLIB +19 -0
  766. package/third-party/inventory.json +3614 -0
  767. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/esbuild-0.27.4-LICENSE.md +21 -0
  768. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/go-LICENSE +27 -0
  769. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/golang-x-sys-c0bba94af5f8-LICENSE +27 -0
  770. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/package.json +20 -0
  771. package/third-party/npm/@floating-ui__core@1.7.5/LICENSE +20 -0
  772. package/third-party/npm/@floating-ui__core@1.7.5/package.json +63 -0
  773. package/third-party/npm/@floating-ui__dom@1.7.6/LICENSE +20 -0
  774. package/third-party/npm/@floating-ui__dom@1.7.6/package.json +71 -0
  775. package/third-party/npm/@floating-ui__react-dom@2.1.8/LICENSE +20 -0
  776. package/third-party/npm/@floating-ui__react-dom@2.1.8/package.json +76 -0
  777. package/third-party/npm/@floating-ui__utils@0.2.11/LICENSE +20 -0
  778. package/third-party/npm/@floating-ui__utils@0.2.11/package.json +70 -0
  779. package/third-party/npm/@radix-ui__primitive@1.1.7/LICENSE +21 -0
  780. package/third-party/npm/@radix-ui__primitive@1.1.7/package.json +79 -0
  781. package/third-party/npm/@radix-ui__react-arrow@1.1.15/LICENSE +21 -0
  782. package/third-party/npm/@radix-ui__react-arrow@1.1.15/package.json +68 -0
  783. package/third-party/npm/@radix-ui__react-collection@1.1.15/LICENSE +21 -0
  784. package/third-party/npm/@radix-ui__react-collection@1.1.15/package.json +71 -0
  785. package/third-party/npm/@radix-ui__react-compose-refs@1.1.5/LICENSE +21 -0
  786. package/third-party/npm/@radix-ui__react-compose-refs@1.1.5/package.json +60 -0
  787. package/third-party/npm/@radix-ui__react-context-menu@2.3.7/LICENSE +21 -0
  788. package/third-party/npm/@radix-ui__react-context-menu@2.3.7/package.json +73 -0
  789. package/third-party/npm/@radix-ui__react-context@1.2.2/LICENSE +21 -0
  790. package/third-party/npm/@radix-ui__react-context@1.2.2/package.json +60 -0
  791. package/third-party/npm/@radix-ui__react-direction@1.1.4/LICENSE +21 -0
  792. package/third-party/npm/@radix-ui__react-direction@1.1.4/package.json +60 -0
  793. package/third-party/npm/@radix-ui__react-dismissable-layer@1.1.19/LICENSE +21 -0
  794. package/third-party/npm/@radix-ui__react-dismissable-layer@1.1.19/package.json +74 -0
  795. package/third-party/npm/@radix-ui__react-focus-guards@1.1.6/LICENSE +21 -0
  796. package/third-party/npm/@radix-ui__react-focus-guards@1.1.6/package.json +60 -0
  797. package/third-party/npm/@radix-ui__react-focus-scope@1.1.16/LICENSE +21 -0
  798. package/third-party/npm/@radix-ui__react-focus-scope@1.1.16/package.json +71 -0
  799. package/third-party/npm/@radix-ui__react-id@1.1.4/LICENSE +21 -0
  800. package/third-party/npm/@radix-ui__react-id@1.1.4/package.json +63 -0
  801. package/third-party/npm/@radix-ui__react-menu@2.1.24/LICENSE +21 -0
  802. package/third-party/npm/@radix-ui__react-menu@2.1.24/package.json +86 -0
  803. package/third-party/npm/@radix-ui__react-popper@1.3.7/LICENSE +21 -0
  804. package/third-party/npm/@radix-ui__react-popper@1.3.7/package.json +78 -0
  805. package/third-party/npm/@radix-ui__react-portal@1.1.17/LICENSE +21 -0
  806. package/third-party/npm/@radix-ui__react-portal@1.1.17/package.json +69 -0
  807. package/third-party/npm/@radix-ui__react-presence@1.1.10/LICENSE +21 -0
  808. package/third-party/npm/@radix-ui__react-presence@1.1.10/package.json +68 -0
  809. package/third-party/npm/@radix-ui__react-primitive@2.1.10/LICENSE +21 -0
  810. package/third-party/npm/@radix-ui__react-primitive@2.1.10/package.json +68 -0
  811. package/third-party/npm/@radix-ui__react-roving-focus@1.1.19/LICENSE +21 -0
  812. package/third-party/npm/@radix-ui__react-roving-focus@1.1.19/package.json +78 -0
  813. package/third-party/npm/@radix-ui__react-slot@1.3.3/LICENSE +21 -0
  814. package/third-party/npm/@radix-ui__react-slot@1.3.3/package.json +63 -0
  815. package/third-party/npm/@radix-ui__react-use-callback-ref@1.1.4/LICENSE +21 -0
  816. package/third-party/npm/@radix-ui__react-use-callback-ref@1.1.4/package.json +60 -0
  817. package/third-party/npm/@radix-ui__react-use-controllable-state@1.2.6/LICENSE +21 -0
  818. package/third-party/npm/@radix-ui__react-use-controllable-state@1.2.6/package.json +65 -0
  819. package/third-party/npm/@radix-ui__react-use-effect-event@0.0.5/LICENSE +21 -0
  820. package/third-party/npm/@radix-ui__react-use-effect-event@0.0.5/package.json +65 -0
  821. package/third-party/npm/@radix-ui__react-use-is-hydrated@0.1.3/LICENSE +21 -0
  822. package/third-party/npm/@radix-ui__react-use-is-hydrated@0.1.3/package.json +61 -0
  823. package/third-party/npm/@radix-ui__react-use-layout-effect@1.1.4/LICENSE +21 -0
  824. package/third-party/npm/@radix-ui__react-use-layout-effect@1.1.4/package.json +60 -0
  825. package/third-party/npm/@radix-ui__react-use-size@1.1.4/LICENSE +21 -0
  826. package/third-party/npm/@radix-ui__react-use-size@1.1.4/package.json +63 -0
  827. package/third-party/npm/aria-hidden@1.2.6/LICENSE +21 -0
  828. package/third-party/npm/aria-hidden@1.2.6/package.json +71 -0
  829. package/third-party/npm/detect-node-es@1.1.0/LICENSE +21 -0
  830. package/third-party/npm/detect-node-es@1.1.0/package.json +29 -0
  831. package/third-party/npm/esbuild@0.27.4/LICENSE.md +21 -0
  832. package/third-party/npm/esbuild@0.27.4/package.json +49 -0
  833. package/third-party/npm/fflate@0.8.3/LICENSE +21 -0
  834. package/third-party/npm/fflate@0.8.3/package.json +128 -0
  835. package/third-party/npm/get-nonce@1.0.1/LICENSE +21 -0
  836. package/third-party/npm/get-nonce@1.0.1/package.json +68 -0
  837. package/third-party/npm/mediabunny@1.52.2/LICENSE +373 -0
  838. package/third-party/npm/mediabunny@1.52.2/package.json +136 -0
  839. package/third-party/npm/mediabunny@1.52.2/source/LICENSE +373 -0
  840. package/third-party/npm/mediabunny@1.52.2/source/package.json +136 -0
  841. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-demuxer.ts +400 -0
  842. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-muxer.ts +124 -0
  843. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-reader.ts +85 -0
  844. package/third-party/npm/mediabunny@1.52.2/source/src/aes.ts +307 -0
  845. package/third-party/npm/mediabunny@1.52.2/source/src/codec-data.ts +3178 -0
  846. package/third-party/npm/mediabunny@1.52.2/source/src/codec.ts +1154 -0
  847. package/third-party/npm/mediabunny@1.52.2/source/src/conversion.ts +2042 -0
  848. package/third-party/npm/mediabunny@1.52.2/source/src/custom-coder.ts +212 -0
  849. package/third-party/npm/mediabunny@1.52.2/source/src/decode.ts +263 -0
  850. package/third-party/npm/mediabunny@1.52.2/source/src/demuxer.ts +43 -0
  851. package/third-party/npm/mediabunny@1.52.2/source/src/encode.ts +1412 -0
  852. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-demuxer.ts +813 -0
  853. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-misc.ts +165 -0
  854. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-muxer.ts +350 -0
  855. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-demuxer.ts +995 -0
  856. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-misc.ts +81 -0
  857. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-muxer.ts +1529 -0
  858. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-segmented-input.ts +772 -0
  859. package/third-party/npm/mediabunny@1.52.2/source/src/id3.ts +972 -0
  860. package/third-party/npm/mediabunny@1.52.2/source/src/index.ts +319 -0
  861. package/third-party/npm/mediabunny@1.52.2/source/src/input-format.ts +819 -0
  862. package/third-party/npm/mediabunny@1.52.2/source/src/input-track.ts +1141 -0
  863. package/third-party/npm/mediabunny@1.52.2/source/src/input.ts +571 -0
  864. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-boxes.ts +1911 -0
  865. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-demuxer.ts +3953 -0
  866. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-misc.ts +90 -0
  867. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-muxer.ts +1595 -0
  868. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-reader.ts +91 -0
  869. package/third-party/npm/mediabunny@1.52.2/source/src/logging.ts +120 -0
  870. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/ebml.ts +770 -0
  871. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-demuxer.ts +2598 -0
  872. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-misc.ts +29 -0
  873. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-muxer.ts +1360 -0
  874. package/third-party/npm/mediabunny@1.52.2/source/src/media-sink.ts +2589 -0
  875. package/third-party/npm/mediabunny@1.52.2/source/src/media-source.ts +3041 -0
  876. package/third-party/npm/mediabunny@1.52.2/source/src/metadata.ts +335 -0
  877. package/third-party/npm/mediabunny@1.52.2/source/src/misc.ts +1336 -0
  878. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-demuxer.ts +469 -0
  879. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-muxer.ts +169 -0
  880. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-reader.ts +61 -0
  881. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-writer.ts +121 -0
  882. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-demuxer.ts +2519 -0
  883. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-misc.ts +32 -0
  884. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-muxer.ts +842 -0
  885. package/third-party/npm/mediabunny@1.52.2/source/src/muxer.ts +80 -0
  886. package/third-party/npm/mediabunny@1.52.2/source/src/node.ts +11 -0
  887. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-demuxer.ts +1087 -0
  888. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-misc.ts +116 -0
  889. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-muxer.ts +527 -0
  890. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-reader.ts +93 -0
  891. package/third-party/npm/mediabunny@1.52.2/source/src/output-format.ts +1425 -0
  892. package/third-party/npm/mediabunny@1.52.2/source/src/output.ts +940 -0
  893. package/third-party/npm/mediabunny@1.52.2/source/src/packet.ts +287 -0
  894. package/third-party/npm/mediabunny@1.52.2/source/src/pcm.ts +112 -0
  895. package/third-party/npm/mediabunny@1.52.2/source/src/reader.ts +391 -0
  896. package/third-party/npm/mediabunny@1.52.2/source/src/resample.ts +287 -0
  897. package/third-party/npm/mediabunny@1.52.2/source/src/sample.ts +3231 -0
  898. package/third-party/npm/mediabunny@1.52.2/source/src/segmented-input.ts +575 -0
  899. package/third-party/npm/mediabunny@1.52.2/source/src/source.ts +2588 -0
  900. package/third-party/npm/mediabunny@1.52.2/source/src/subtitles.ts +131 -0
  901. package/third-party/npm/mediabunny@1.52.2/source/src/target.ts +871 -0
  902. package/third-party/npm/mediabunny@1.52.2/source/src/tsconfig.json +16 -0
  903. package/third-party/npm/mediabunny@1.52.2/source/src/wave/riff-writer.ts +36 -0
  904. package/third-party/npm/mediabunny@1.52.2/source/src/wave/wave-demuxer.ts +583 -0
  905. package/third-party/npm/mediabunny@1.52.2/source/src/wave/wave-muxer.ts +375 -0
  906. package/third-party/npm/mediabunny@1.52.2/source/src/writer.ts +128 -0
  907. package/third-party/npm/react-dom@19.3.0/LICENSE +21 -0
  908. package/third-party/npm/react-dom@19.3.0/package.json +117 -0
  909. package/third-party/npm/react-remove-scroll-bar@2.3.8/package.json +85 -0
  910. package/third-party/npm/react-remove-scroll-bar@2.3.8/react-remove-scroll-bar-LICENSE +21 -0
  911. package/third-party/npm/react-remove-scroll@2.7.2/LICENSE +21 -0
  912. package/third-party/npm/react-remove-scroll@2.7.2/package.json +98 -0
  913. package/third-party/npm/react-style-singleton@2.2.3/LICENSE +21 -0
  914. package/third-party/npm/react-style-singleton@2.2.3/package.json +90 -0
  915. package/third-party/npm/react@19.3.0/LICENSE +21 -0
  916. package/third-party/npm/react@19.3.0/package.json +51 -0
  917. package/third-party/npm/scheduler@0.28.0/LICENSE +21 -0
  918. package/third-party/npm/scheduler@0.28.0/package.json +27 -0
  919. package/third-party/npm/tslib@2.8.1/LICENSE.txt +12 -0
  920. package/third-party/npm/tslib@2.8.1/package.json +47 -0
  921. package/third-party/npm/typescript@5.9.3/LICENSE.txt +55 -0
  922. package/third-party/npm/typescript@5.9.3/ThirdPartyNoticeText.txt +193 -0
  923. package/third-party/npm/typescript@5.9.3/package.json +120 -0
  924. package/third-party/npm/use-callback-ref@1.3.3/LICENSE +21 -0
  925. package/third-party/npm/use-callback-ref@1.3.3/package.json +85 -0
  926. package/third-party/npm/use-sidecar@1.1.3/LICENSE +21 -0
  927. package/third-party/npm/use-sidecar@1.1.3/package.json +93 -0
  928. package/third-party/packages/render-engine/assets/OFL.txt +93 -0
  929. package/third-party/packages/studio/public/fonts/OFL.txt +93 -0
  930. package/third-party/packages/studio/vendor/osmo-icons/LICENSE +21 -0
  931. package/third-party/packages/studio/vendor/shadcn/LICENSE +21 -0
  932. package/third-party/repository-notices.md +41 -0
  933. package/third-party/rust-standard-library/COPYRIGHT-library.html +5556 -0
  934. package/third-party/rust-standard-library/licenses/Apache-2.0.txt +73 -0
  935. package/third-party/rust-standard-library/licenses/BSD-2-Clause.txt +9 -0
  936. package/third-party/rust-standard-library/licenses/CC-BY-SA-4.0.txt +427 -0
  937. package/third-party/rust-standard-library/licenses/GCC-exception-3.1.txt +30 -0
  938. package/third-party/rust-standard-library/licenses/GPL-2.0-only.txt +133 -0
  939. package/third-party/rust-standard-library/licenses/GPL-3.0-or-later.txt +202 -0
  940. package/third-party/rust-standard-library/licenses/ISC.txt +7 -0
  941. package/third-party/rust-standard-library/licenses/LLVM-exception.txt +15 -0
  942. package/third-party/rust-standard-library/licenses/MIT.txt +9 -0
  943. package/third-party/rust-standard-library/licenses/NCSA.txt +29 -0
  944. package/third-party/rust-standard-library/licenses/OFL-1.1.txt +43 -0
  945. package/third-party/rust-standard-library/licenses/Unicode-3.0.txt +39 -0
  946. package/third-party/rust-standard-library/version.txt +1 -0
  947. package/vendor/osmo-lite +0 -0
  948. package/vendor/osmo-scene-0.1.0.tgz +0 -0
  949. package/vendor/platform.json +1 -0
@@ -0,0 +1,2042 @@
1
+ /*!
2
+ * Copyright (c) 2026-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ import {
10
+ AUDIO_CODECS,
11
+ AudioCodec,
12
+ MediaCodec,
13
+ NON_PCM_AUDIO_CODECS,
14
+ VIDEO_CODECS,
15
+ VideoCodec,
16
+ } from './codec';
17
+ import {
18
+ AudioEncodingConfig,
19
+ getEncodableAudioCodecs,
20
+ getFirstEncodableVideoCodec,
21
+ Quality,
22
+ resolveQuality,
23
+ VideoEncodingConfig,
24
+ } from './encode';
25
+ import { Input } from './input';
26
+ import { InputAudioTrack, InputTrack, InputVideoTrack } from './input-track';
27
+ import { Logging } from './logging';
28
+ import {
29
+ AudioSampleSink,
30
+ EncodedPacketSink,
31
+ VideoSampleSink,
32
+ } from './media-sink';
33
+ import {
34
+ AudioSource,
35
+ EncodedVideoPacketSource,
36
+ EncodedAudioPacketSource,
37
+ VideoSource,
38
+ VideoSampleSource,
39
+ AudioSampleSource,
40
+ } from './media-source';
41
+ import {
42
+ assert,
43
+ assertNever,
44
+ ceilToMultipleOfTwo,
45
+ clamp,
46
+ isIso639Dash2LanguageCode,
47
+ MaybePromise,
48
+ normalizeRotation,
49
+ promiseWithResolvers,
50
+ Rotation,
51
+ } from './misc';
52
+ import { Output, OutputTrackGroup } from './output';
53
+ import { Mp4OutputFormat } from './output-format';
54
+ import {
55
+ AudioSample,
56
+ clampCropRectangle,
57
+ CropRectangle,
58
+ getBytesPerSample,
59
+ validateCropRectangle,
60
+ VideoSample,
61
+ VideoSampleResource,
62
+ } from './sample';
63
+ import { MetadataTags, validateMetadataTags } from './metadata';
64
+ import { NullTarget } from './target';
65
+
66
+ /**
67
+ * The options for media file conversion.
68
+ * @group Conversion
69
+ * @public
70
+ */
71
+ export type ConversionOptions = {
72
+ /** The input file. */
73
+ input: Input;
74
+ /** The output file. */
75
+ output: Output;
76
+
77
+ /**
78
+ * Defines which input tracks are used for conversion. Defaults to `'all'` unless the input is an HLS input, in
79
+ * which case it defaults to `'primary'`.
80
+ *
81
+ * - `'all'`: All input tracks are eligible for conversion.
82
+ * - `'primary'`: Only the primary video and audio track from the input are eligible for conversion.
83
+ */
84
+ tracks?: 'all' | 'primary';
85
+
86
+ /**
87
+ * Video-specific options. When passing an object, the same options are applied to all video tracks. When passing a
88
+ * function, it will be invoked for each video track and is expected to return or resolve to the options
89
+ * for that specific track. The function is passed an instance of {@link InputVideoTrack} as well as a number `n`,
90
+ * which is the 1-based index of the track in the list of all video tracks. Using `n` is deprecated, prefer the
91
+ * identical `track.number` instead.
92
+ *
93
+ * When passing an array of a function that returns an array, one output track per array element will be created,
94
+ * allowing for "fan-out". Useful for creating multiple variants from a single track, for example with different
95
+ * resolutions.
96
+ */
97
+ video?: ConversionVideoOptions
98
+ | ConversionVideoOptions[]
99
+ | ((track: InputVideoTrack, n: number) => MaybePromise<
100
+ ConversionVideoOptions | ConversionVideoOptions[] | undefined
101
+ >);
102
+
103
+ /**
104
+ * Audio-specific options. When passing an object, the same options are applied to all audio tracks. When passing a
105
+ * function, it will be invoked for each audio track and is expected to return or resolve to the options
106
+ * for that specific track. The function is passed an instance of {@link InputAudioTrack} as well as a number `n`,
107
+ * which is the 1-based index of the track in the list of all audio tracks. Using `n` is deprecated, prefer the
108
+ * identical `track.number` instead.
109
+ *
110
+ * When passing an array of a function that returns an array, one output track per array element will be created,
111
+ * allowing for "fan-out". Useful for creating multiple variants from a single track, for example with different
112
+ * bitrates.
113
+ */
114
+ audio?: ConversionAudioOptions
115
+ | ConversionAudioOptions[]
116
+ | ((track: InputAudioTrack, n: number) => MaybePromise<
117
+ ConversionAudioOptions | ConversionAudioOptions[] | undefined
118
+ >);
119
+
120
+ /** Options to trim the input file. */
121
+ trim?: {
122
+ /**
123
+ * The time in the input file in seconds at which the output file should start. Must be less than `end`.
124
+ * When omitted, defaults to the earliest start timestamp of the non-discarded tracks, or to 0, whichever
125
+ * is higher.
126
+ */
127
+ start?: number;
128
+ /**
129
+ * The time in the input file in seconds at which the output file should end. Must be greater than `start`.
130
+ * Defaults to the duration of the input when omitted.
131
+ */
132
+ end?: number;
133
+ };
134
+
135
+ /**
136
+ * An object or a callback that returns or resolves to an object containing the descriptive metadata tags that
137
+ * should be written to the output file. If a function is passed, it will be passed the tags of the input file as
138
+ * its first argument, allowing you to modify, augment or extend them.
139
+ *
140
+ * If no function is set, the input's metadata tags will be copied to the output.
141
+ */
142
+ tags?: MetadataTags | ((inputTags: MetadataTags) => MaybePromise<MetadataTags>);
143
+
144
+ /**
145
+ * Whether to show potential console warnings about discarded tracks after calling `Conversion.init()`, defaults to
146
+ * `true`. Set this to `false` if you're properly handling the `discardedTracks` and `isValid` fields already and
147
+ * want to keep the console output clean.
148
+ */
149
+ showWarnings?: boolean;
150
+
151
+ /**
152
+ * Whether this conversion is composable, defaults to `false`. A non-composable conversion takes full ownership of
153
+ * the output: it requires a fresh output and controls its entire lifecycle, meaning it starts it, writes its
154
+ * metadata tags, and finalizes it.
155
+ *
156
+ * A composable conversion only adds tracks to the output and drives their media data; starting and finalizing
157
+ * the output is an outside responsibility. This is useful when only some output tracks should be driven by a
158
+ * conversion, and other are to be driven manually. Additionally, it can be used to have multiple conversions target
159
+ * the same output.
160
+ */
161
+ composable?: boolean;
162
+ };
163
+
164
+ /**
165
+ * Video-specific options.
166
+ * @group Conversion
167
+ * @public
168
+ */
169
+ export type ConversionVideoOptions = {
170
+ /** If `true`, all video tracks will be discarded and will not be present in the output. */
171
+ discard?: boolean;
172
+ /**
173
+ * The desired width of the output video in pixels, defaulting to the video's natural display width. If height
174
+ * is not set, it will be deduced automatically based on aspect ratio.
175
+ */
176
+ width?: number;
177
+ /**
178
+ * The desired height of the output video in pixels, defaulting to the video's natural display height. If width
179
+ * is not set, it will be deduced automatically based on aspect ratio.
180
+ */
181
+ height?: number;
182
+ /**
183
+ * The fitting algorithm in case both width and height are set, or if the input video changes its size over time.
184
+ *
185
+ * - `'fill'` will stretch the image to fill the entire box, potentially altering aspect ratio.
186
+ * - `'contain'` will contain the entire image within the box while preserving aspect ratio. This may lead to
187
+ * letterboxing.
188
+ * - `'cover'` will scale the image until the entire box is filled, while preserving aspect ratio.
189
+ */
190
+ fit?: 'fill' | 'contain' | 'cover';
191
+ /**
192
+ * The angle in degrees to rotate the input video by, clockwise. Rotation is applied before cropping and resizing.
193
+ * This rotation is _in addition to_ the natural rotation of the input video as specified in input file's metadata.
194
+ */
195
+ rotate?: Rotation;
196
+ /**
197
+ * Defaults to `true`. When enabled, Mediabunny will use the rotation metadata in the output file to perform video
198
+ * rotation whenever possible. Set this field to `false` if you want to ensure the output file does not make use of
199
+ * rotation metadata and that any rotation is baked into the video frames directly.
200
+ */
201
+ allowRotationMetadata?: boolean;
202
+ /**
203
+ * Specifies the rectangular region of the input video to crop to. The crop region will automatically be clamped to
204
+ * the dimensions of the input video track. Cropping is performed after rotation but before resizing.
205
+ */
206
+ crop?: CropRectangle;
207
+ /**
208
+ * The desired frame rate of the output video, in hertz. If not specified, the original input frame rate will
209
+ * be used (which may be variable).
210
+ */
211
+ frameRate?: number;
212
+ /** The desired output video codec. */
213
+ codec?: VideoCodec;
214
+ /** The desired quality of the output video. */
215
+ quality?: Quality;
216
+ /**
217
+ * The desired bitrate of the output video.
218
+ * @deprecated Use `quality` instead.
219
+ */
220
+ bitrate?: number | Quality;
221
+ /**
222
+ * Whether to discard or keep the transparency information of the input video. The default is `'discard'`. Note that
223
+ * for `'keep'` to produce a transparent video, you must use an output config that supports it, such as WebM with
224
+ * VP9.
225
+ */
226
+ alpha?: 'discard' | 'keep';
227
+ /**
228
+ * The interval, in seconds, of how often frames are encoded as a key frame. The default is 5 seconds. Frequent key
229
+ * frames improve seeking behavior but increase file size. When using multiple video tracks, you should give them
230
+ * all the same key frame interval.
231
+ *
232
+ * Setting this fields forces a transcode.
233
+ */
234
+ keyFrameInterval?: number;
235
+ /**
236
+ * A hint that configures the hardware acceleration method used when transcoding. This is best left on
237
+ * `'no-preference'`, the default.
238
+ */
239
+ hardwareAcceleration?: 'no-preference' | 'prefer-hardware' | 'prefer-software';
240
+ /** When `true`, video will always be re-encoded instead of directly copying over the encoded samples. */
241
+ forceTranscode?: boolean;
242
+ /**
243
+ * Allows for custom user-defined processing of video frames, e.g. for applying overlays, color transformations, or
244
+ * timestamp modifications. Will be called for each input video sample after transformations and frame rate
245
+ * corrections.
246
+ *
247
+ * Must return a {@link VideoSample}, a {@link VideoSampleResource} or a `CanvasImageSource`, an array of them, or
248
+ * `null` for dropping the frame. When non-timestamped data is returned, the timestamp and duration from the source
249
+ * sample will be used. Rotation metadata of the returned sample will be ignored.
250
+ *
251
+ * This function can also be used to manually resize frames. When doing so, you should signal the post-process
252
+ * dimensions using the `processedWidth` and `processedHeight` fields, which enables the encoder to better know what
253
+ * to expect. If these fields aren't set, Mediabunny will assume you won't perform any resizing.
254
+ */
255
+ process?: (sample: VideoSample) => MaybePromise<
256
+ CanvasImageSource | VideoSample | VideoSampleResource
257
+ | (CanvasImageSource | VideoSample | VideoSampleResource)[] | null
258
+ >;
259
+ /**
260
+ * An optional hint specifying the width of video samples returned by the `process` function, for better
261
+ * encoder configuration.
262
+ */
263
+ processedWidth?: number;
264
+ /**
265
+ * An optional hint specifying the height of video samples returned by the `process` function, for better
266
+ * encoder configuration.
267
+ */
268
+ processedHeight?: number;
269
+ /**
270
+ * Defines the group(s) the output track is a part of. For more, see {@link BaseTrackMetadata.group}.
271
+ *
272
+ * If left blank, tracks will internally be assigned to groups such that the output track pairability graph exactly
273
+ * matches the input track pairability graph.
274
+ */
275
+ group?: OutputTrackGroup | OutputTrackGroup[];
276
+ };
277
+
278
+ /**
279
+ * Audio-specific options.
280
+ * @group Conversion
281
+ * @public
282
+ */
283
+ export type ConversionAudioOptions = {
284
+ /** If `true`, all audio tracks will be discarded and will not be present in the output. */
285
+ discard?: boolean;
286
+ /** The desired channel count of the output audio. */
287
+ numberOfChannels?: number;
288
+ /** The desired sample rate of the output audio, in hertz. */
289
+ sampleRate?: number;
290
+ /**
291
+ * The desired sample format (and therefore bit depth) of the audio samples before they are passed to the encoder.
292
+ * Can be used to control bit depth with certain output codecs such as FLAC.
293
+ *
294
+ * Setting this field forces audio transcoding.
295
+ */
296
+ sampleFormat?: 'u8' | 's16' | 's32' | 'f32';
297
+ /** The desired output audio codec. */
298
+ codec?: AudioCodec;
299
+ /** The desired quality of the output audio. */
300
+ quality?: Quality;
301
+ /**
302
+ * The desired bitrate of the output audio.
303
+ * @deprecated Use `quality` instead.
304
+ */
305
+ bitrate?: number | Quality;
306
+ /** When `true`, audio will always be re-encoded instead of directly copying over the encoded samples. */
307
+ forceTranscode?: boolean;
308
+ /**
309
+ * Allows for custom user-defined processing of audio samples, e.g. for applying audio effects, transformations, or
310
+ * timestamp modifications. Will be called for each input audio sample after remixing and resampling.
311
+ *
312
+ * Must return an {@link AudioSample}, an array of them, or `null` for dropping the sample.
313
+ *
314
+ * This function can also be used to manually perform remixing or resampling. When doing so, you should signal the
315
+ * post-process parameters using the `processedNumberOfChannels` and `processedSampleRate` fields, which enables the
316
+ * encoder to better know what to expect. If these fields aren't set, Mediabunny will assume you won't perform
317
+ * remixing or resampling.
318
+ */
319
+ process?: (sample: AudioSample) => MaybePromise<
320
+ AudioSample | AudioSample[] | null
321
+ >;
322
+ /**
323
+ * An optional hint specifying the channel count of audio samples returned by the `process` function, for better
324
+ * encoder configuration.
325
+ */
326
+ processedNumberOfChannels?: number;
327
+ /**
328
+ * An optional hint specifying the sample rate of audio samples returned by the `process` function, for better
329
+ * encoder configuration.
330
+ */
331
+ processedSampleRate?: number;
332
+ /**
333
+ * Defines the group(s) the output track is a part of. For more, see {@link BaseTrackMetadata.group}.
334
+ *
335
+ * If left blank, tracks will internally be assigned to groups such that the output track pairability graph exactly
336
+ * matches the input track pairability graph.
337
+ */
338
+ group?: OutputTrackGroup | OutputTrackGroup[];
339
+ };
340
+
341
+ const validateVideoOptions = (videoOptions: ConversionVideoOptions) => {
342
+ if (!videoOptions || typeof videoOptions !== 'object') {
343
+ throw new TypeError('options.video, when provided, must be an object.');
344
+ }
345
+ if (videoOptions?.discard !== undefined && typeof videoOptions.discard !== 'boolean') {
346
+ throw new TypeError('options.video.discard, when provided, must be a boolean.');
347
+ }
348
+ if (videoOptions?.forceTranscode !== undefined && typeof videoOptions.forceTranscode !== 'boolean') {
349
+ throw new TypeError('options.video.forceTranscode, when provided, must be a boolean.');
350
+ }
351
+ if (videoOptions?.codec !== undefined && !VIDEO_CODECS.includes(videoOptions.codec)) {
352
+ throw new TypeError(
353
+ `options.video.codec, when provided, must be one of: ${VIDEO_CODECS.join(', ')}.`,
354
+ );
355
+ }
356
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
357
+ const bitrate = videoOptions?.bitrate;
358
+ if (videoOptions?.quality !== undefined && !(videoOptions.quality instanceof Quality)) {
359
+ throw new TypeError('options.video.quality, when provided, must be a Quality.');
360
+ }
361
+ if (videoOptions?.quality !== undefined && bitrate !== undefined) {
362
+ throw new TypeError('options.video.quality and options.video.bitrate cannot both be provided.');
363
+ }
364
+ if (bitrate !== undefined && !(bitrate instanceof Quality) && (!Number.isInteger(bitrate) || bitrate <= 0)) {
365
+ throw new TypeError('options.video.bitrate, when provided, must be a positive integer or a quality.');
366
+ }
367
+ if (
368
+ videoOptions?.width !== undefined
369
+ && (!Number.isInteger(videoOptions.width) || videoOptions.width <= 0)
370
+ ) {
371
+ throw new TypeError('options.video.width, when provided, must be a positive integer.');
372
+ }
373
+ if (
374
+ videoOptions?.height !== undefined
375
+ && (!Number.isInteger(videoOptions.height) || videoOptions.height <= 0)
376
+ ) {
377
+ throw new TypeError('options.video.height, when provided, must be a positive integer.');
378
+ }
379
+ if (videoOptions?.fit !== undefined && !['fill', 'contain', 'cover'].includes(videoOptions.fit)) {
380
+ throw new TypeError('options.video.fit, when provided, must be one of \'fill\', \'contain\', or \'cover\'.');
381
+ }
382
+ if (
383
+ videoOptions?.width !== undefined
384
+ && videoOptions.height !== undefined
385
+ && videoOptions.fit === undefined
386
+ ) {
387
+ throw new TypeError(
388
+ 'When both options.video.width and options.video.height are provided, options.video.fit must also be'
389
+ + ' provided.',
390
+ );
391
+ }
392
+ if (videoOptions?.rotate !== undefined && ![0, 90, 180, 270].includes(videoOptions.rotate)) {
393
+ throw new TypeError('options.video.rotate, when provided, must be 0, 90, 180 or 270.');
394
+ }
395
+ if (videoOptions?.allowRotationMetadata !== undefined && typeof videoOptions.allowRotationMetadata !== 'boolean') {
396
+ throw new TypeError('options.video.allowRotationMetadata, when provided, must be a boolean.');
397
+ }
398
+ if (videoOptions?.crop !== undefined) {
399
+ validateCropRectangle(videoOptions.crop, 'options.video.');
400
+ }
401
+ if (
402
+ videoOptions?.frameRate !== undefined
403
+ && (!Number.isFinite(videoOptions.frameRate) || videoOptions.frameRate <= 0)
404
+ ) {
405
+ throw new TypeError('options.video.frameRate, when provided, must be a finite positive number.');
406
+ }
407
+ if (videoOptions?.alpha !== undefined && !['discard', 'keep'].includes(videoOptions.alpha)) {
408
+ throw new TypeError('options.video.alpha, when provided, must be either \'discard\' or \'keep\'.');
409
+ }
410
+ if (
411
+ videoOptions?.keyFrameInterval !== undefined
412
+ && (!Number.isFinite(videoOptions.keyFrameInterval) || videoOptions.keyFrameInterval < 0)
413
+ ) {
414
+ throw new TypeError('options.video.keyFrameInterval, when provided, must be a non-negative number.');
415
+ }
416
+ if (videoOptions?.process !== undefined && typeof videoOptions.process !== 'function') {
417
+ throw new TypeError('options.video.process, when provided, must be a function.');
418
+ }
419
+ if (
420
+ videoOptions?.processedWidth !== undefined
421
+ && (!Number.isInteger(videoOptions.processedWidth) || videoOptions.processedWidth <= 0)
422
+ ) {
423
+ throw new TypeError('options.video.processedWidth, when provided, must be a positive integer.');
424
+ }
425
+ if (
426
+ videoOptions?.processedHeight !== undefined
427
+ && (!Number.isInteger(videoOptions.processedHeight) || videoOptions.processedHeight <= 0)
428
+ ) {
429
+ throw new TypeError('options.video.processedHeight, when provided, must be a positive integer.');
430
+ }
431
+ if (
432
+ videoOptions?.hardwareAcceleration !== undefined
433
+ && !['no-preference', 'prefer-hardware', 'prefer-software'].includes(videoOptions.hardwareAcceleration)
434
+ ) {
435
+ throw new TypeError(
436
+ 'options.video.hardwareAcceleration, when provided, must be \'no-preference\', \'prefer-hardware\' or'
437
+ + ' \'prefer-software\'.',
438
+ );
439
+ }
440
+ if (
441
+ videoOptions?.group !== undefined
442
+ && !(
443
+ videoOptions.group instanceof OutputTrackGroup
444
+ || (Array.isArray(videoOptions.group) && videoOptions.group.every(x => x instanceof OutputTrackGroup))
445
+ )
446
+ ) {
447
+ throw new TypeError(
448
+ 'options.video.group, when provided, must be an OutputTrackGroup or an array of OutputTrackGroups.',
449
+ );
450
+ }
451
+ };
452
+
453
+ const validateAudioOptions = (audioOptions: ConversionAudioOptions) => {
454
+ if (!audioOptions || typeof audioOptions !== 'object') {
455
+ throw new TypeError('options.audio, when provided, must be an object.');
456
+ }
457
+ if (audioOptions?.discard !== undefined && typeof audioOptions.discard !== 'boolean') {
458
+ throw new TypeError('options.audio.discard, when provided, must be a boolean.');
459
+ }
460
+ if (audioOptions?.forceTranscode !== undefined && typeof audioOptions.forceTranscode !== 'boolean') {
461
+ throw new TypeError('options.audio.forceTranscode, when provided, must be a boolean.');
462
+ }
463
+ if (audioOptions?.codec !== undefined && !AUDIO_CODECS.includes(audioOptions.codec)) {
464
+ throw new TypeError(
465
+ `options.audio.codec, when provided, must be one of: ${AUDIO_CODECS.join(', ')}.`,
466
+ );
467
+ }
468
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
469
+ const bitrate = audioOptions?.bitrate;
470
+ if (audioOptions?.quality !== undefined && !(audioOptions.quality instanceof Quality)) {
471
+ throw new TypeError('options.audio.quality, when provided, must be a Quality.');
472
+ }
473
+ if (audioOptions?.quality !== undefined && bitrate !== undefined) {
474
+ throw new TypeError('options.audio.quality and options.audio.bitrate cannot both be provided.');
475
+ }
476
+ if (bitrate !== undefined && !(bitrate instanceof Quality) && (!Number.isInteger(bitrate) || bitrate <= 0)) {
477
+ throw new TypeError('options.audio.bitrate, when provided, must be a positive integer or a quality.');
478
+ }
479
+ if (
480
+ audioOptions?.numberOfChannels !== undefined
481
+ && (!Number.isInteger(audioOptions.numberOfChannels) || audioOptions.numberOfChannels <= 0)
482
+ ) {
483
+ throw new TypeError('options.audio.numberOfChannels, when provided, must be a positive integer.');
484
+ }
485
+ if (
486
+ audioOptions?.sampleRate !== undefined
487
+ && (!Number.isInteger(audioOptions.sampleRate) || audioOptions.sampleRate <= 0)
488
+ ) {
489
+ throw new TypeError('options.audio.sampleRate, when provided, must be a positive integer.');
490
+ }
491
+ if (
492
+ audioOptions?.sampleFormat !== undefined
493
+ && !['u8', 's16', 's32', 'f32'].includes(audioOptions.sampleFormat)
494
+ ) {
495
+ throw new TypeError('options.audio.sampleFormat, when provided, must be one of: u8, s16, s32, f32.');
496
+ }
497
+ if (audioOptions?.process !== undefined && typeof audioOptions.process !== 'function') {
498
+ throw new TypeError('options.audio.process, when provided, must be a function.');
499
+ }
500
+ if (
501
+ audioOptions?.processedNumberOfChannels !== undefined
502
+ && (!Number.isInteger(audioOptions.processedNumberOfChannels) || audioOptions.processedNumberOfChannels <= 0)
503
+ ) {
504
+ throw new TypeError('options.audio.processedNumberOfChannels, when provided, must be a positive integer.');
505
+ }
506
+ if (
507
+ audioOptions?.processedSampleRate !== undefined
508
+ && (!Number.isInteger(audioOptions.processedSampleRate) || audioOptions.processedSampleRate <= 0)
509
+ ) {
510
+ throw new TypeError('options.audio.processedSampleRate, when provided, must be a positive integer.');
511
+ }
512
+ if (
513
+ audioOptions?.group !== undefined
514
+ && !(
515
+ audioOptions.group instanceof OutputTrackGroup
516
+ || (Array.isArray(audioOptions.group) && audioOptions.group.every(x => x instanceof OutputTrackGroup))
517
+ )
518
+ ) {
519
+ throw new TypeError(
520
+ 'options.audio.group, when provided, must be an OutputTrackGroup or an array of OutputTrackGroups.',
521
+ );
522
+ }
523
+ };
524
+
525
+ const FALLBACK_NUMBER_OF_CHANNELS = 2;
526
+ const FALLBACK_SAMPLE_RATE = 48000;
527
+
528
+ /**
529
+ * An input track that was discarded (excluded) from a {@link Conversion} alongside the discard reason.
530
+ * @group Conversion
531
+ * @public
532
+ */
533
+ export type DiscardedTrack = {
534
+ /** The track that was discarded. */
535
+ track: InputTrack;
536
+ /**
537
+ * The reason for discarding the track.
538
+ *
539
+ * - `'discarded_by_user'`: You discarded this track by setting `discard: true`.
540
+ * - `'max_track_count_reached'`: The output had no more room for another track.
541
+ * - `'max_track_count_of_type_reached'`: The output had no more room for another track of this type, or the output
542
+ * doesn't support this track type at all.
543
+ * - `'unknown_source_codec'`: We don't know the codec of the input track and therefore don't know what to do
544
+ * with it.
545
+ * - `'undecodable_source_codec'`: The input track's codec is known, but we are unable to decode it.
546
+ * - `'no_encodable_target_codec'`: We can't find a codec that we are able to encode and that can be contained
547
+ * within the output format. This reason can be hit if the environment doesn't support the necessary encoders, or if
548
+ * you requested a codec that cannot be contained within the output format.
549
+ */
550
+ reason:
551
+ | 'discarded_by_user'
552
+ | 'max_track_count_reached'
553
+ | 'max_track_count_of_type_reached'
554
+ | 'unknown_source_codec'
555
+ | 'undecodable_source_codec'
556
+ | 'no_encodable_target_codec';
557
+ /** The options that were provided for this track, or `{}` if none were provided. */
558
+ trackOptions: ConversionVideoOptions | ConversionAudioOptions;
559
+ };
560
+
561
+ /**
562
+ * Options for controlling a single call to {@link Conversion.execute}.
563
+ * @group Conversion
564
+ * @public
565
+ */
566
+ export type ConversionExecuteOptions = {
567
+ /**
568
+ * The timestamp in seconds, in the output's timescale, until which the conversion should advance. Defaults to
569
+ * `Infinity`, meaning the conversion runs until the end.
570
+ *
571
+ * This field is especially useful for composable conversions, as it allows you to advance the conversion in
572
+ * lockstep with other media data sources.
573
+ */
574
+ until?: number;
575
+ /**
576
+ * A signal that, when triggered, pauses the conversion as soon as possible.
577
+ */
578
+ pauseSignal?: AbortSignal;
579
+ };
580
+
581
+ type TrackPump = {
582
+ done: boolean;
583
+ resolvers: ReturnType<typeof promiseWithResolvers<void>>;
584
+ wake: (() => void) | null;
585
+ start: () => void;
586
+ };
587
+
588
+ /**
589
+ * Represents a media file conversion process, used to convert one media file into another. In addition to conversion,
590
+ * this class can be used to resize and rotate video, resample audio, drop tracks, or trim to a specific time range.
591
+ * @group Conversion
592
+ * @public
593
+ */
594
+ export class Conversion {
595
+ /** The input file. */
596
+ readonly input: Input;
597
+ /** The output file. */
598
+ readonly output: Output;
599
+
600
+ /**
601
+ * The current state of the conversion.
602
+ *
603
+ * - `'idle'`: The conversion is not currently executing and isn't done; `execute` can be called.
604
+ * - `'executing'`: A call to `execute` is currently running.
605
+ * - `'canceled'`: The conversion has been canceled and can no longer be executed.
606
+ * - `'done'`: The conversion has run to completion. Subsequent calls to `execute` do nothing.
607
+ */
608
+ state: 'idle' | 'executing' | 'canceled' | 'done' = 'idle';
609
+
610
+ /** @internal */
611
+ _options: ConversionOptions;
612
+ /** @internal */
613
+ _startTimestamp!: number;
614
+ /** @internal */
615
+ _endTimestamp!: number;
616
+
617
+ /** @internal */
618
+ _nextOutputTrackId = 0;
619
+ /** @internal */
620
+ _outputTrackIds: number[] = [];
621
+ /** @internal */
622
+ _outputOwnTrackGroups: (OutputTrackGroup | null)[] = [];
623
+
624
+ /** @internal */
625
+ _trackPumps: TrackPump[] = [];
626
+ /** @internal */
627
+ _composable = false;
628
+
629
+ /** @internal */
630
+ _executed = false;
631
+ /** @internal */
632
+ _executionUntil = Infinity;
633
+ /** @internal */
634
+ _pauseRequested = false;
635
+
636
+ /** @internal */
637
+ _synchronizer = new TrackSynchronizer(this);
638
+
639
+ /** @internal */
640
+ _totalDuration: number | null = null;
641
+ /** @internal */
642
+ _maxTimestamps = new Map<number, number>(); // Track ID -> timestamp
643
+
644
+ /**
645
+ * A callback that is fired whenever the conversion progresses. Gets passed as first argument a number between
646
+ * 0 and 1, indicating the completion of the conversion. Note that a progress of 1 doesn't necessarily mean the
647
+ * conversion is complete; the conversion is complete once `execute()` resolves.
648
+ *
649
+ * As second argument, this callback receives the input time in seconds that has been processed.
650
+ *
651
+ * In order for progress to be computed, this property must be set before `execute` is called.
652
+ */
653
+ onProgress?: (progress: number, processedTime: number) => unknown = undefined;
654
+ /** @internal */
655
+ _computeProgress = false;
656
+ /** @internal */
657
+ _lastProgress = 0;
658
+
659
+ /**
660
+ * Whether this conversion, as it has been configured, is valid and can be executed. If this field is `false`, check
661
+ * the `discardedTracks` field for reasons. Composable conversions are always valid, even if they utilize
662
+ * zero tracks.
663
+ *
664
+ * Note: a conversion having discarded tracks does not automatically mean it is invalid; if the remaining, utilized
665
+ * tracks make for a valid output file, the conversion is still allowed.
666
+ */
667
+ isValid = false;
668
+ /**
669
+ * The list of tracks that are included in the output file. When fan-out is used, the same track appears in this
670
+ * array multiple times.
671
+ */
672
+ readonly utilizedTracks: InputTrack[] = [];
673
+ /** The list of tracks from the input file that have been discarded, alongside the discard reason. */
674
+ readonly discardedTracks: DiscardedTrack[] = [];
675
+
676
+ /** Initializes a new conversion process without starting the conversion. */
677
+ static async init(options: ConversionOptions) {
678
+ const conversion = new Conversion(options);
679
+ await conversion._init();
680
+
681
+ return conversion;
682
+ }
683
+
684
+ /** Creates a new Conversion instance (duh). */
685
+ private constructor(options: ConversionOptions) {
686
+ if (!options || typeof options !== 'object') {
687
+ throw new TypeError('options must be an object.');
688
+ }
689
+ if (!(options.input instanceof Input)) {
690
+ throw new TypeError('options.input must be an Input.');
691
+ }
692
+ if (!(options.output instanceof Output)) {
693
+ throw new TypeError('options.output must be an Output.');
694
+ }
695
+ if (
696
+ options.tracks !== undefined
697
+ && options.tracks !== 'all'
698
+ && options.tracks !== 'primary'
699
+ ) {
700
+ throw new TypeError(
701
+ 'options.tracks, when provided, must be either \'all\' or \'primary\'.',
702
+ );
703
+ }
704
+ if (options.composable !== undefined && typeof options.composable !== 'boolean') {
705
+ throw new TypeError('options.composable, when provided, must be a boolean.');
706
+ }
707
+
708
+ const composable = options.composable ?? false;
709
+ if (!composable) {
710
+ if (
711
+ options.output.tracks.length > 0
712
+ || Object.keys(options.output._metadataTags).length > 0
713
+ || options.output.state !== 'pending'
714
+ ) {
715
+ throw new TypeError('options.output must be fresh: no tracks or metadata tags added and not started.');
716
+ }
717
+ } else {
718
+ if (options.tags !== undefined) {
719
+ throw new TypeError(
720
+ 'options.tags cannot be set by a composable conversion; set metadata directly on the output'
721
+ + ' instead.',
722
+ );
723
+ }
724
+
725
+ if (options.output.state !== 'pending') {
726
+ throw new TypeError('options.output must not have been started yet.');
727
+ }
728
+ }
729
+
730
+ if (options.video !== undefined && typeof options.video !== 'function') {
731
+ if (Array.isArray(options.video)) {
732
+ for (const obj of options.video) {
733
+ validateVideoOptions(obj);
734
+ }
735
+ } else {
736
+ validateVideoOptions(options.video);
737
+ }
738
+ } else {
739
+ // We'll validate the return value later
740
+ }
741
+
742
+ if (options.audio !== undefined && typeof options.audio !== 'function') {
743
+ if (Array.isArray(options.audio)) {
744
+ for (const obj of options.audio) {
745
+ validateAudioOptions(obj);
746
+ }
747
+ } else {
748
+ validateAudioOptions(options.audio);
749
+ }
750
+ } else {
751
+ // We'll validate the return value later
752
+ }
753
+
754
+ if (options.trim !== undefined && (!options.trim || typeof options.trim !== 'object')) {
755
+ throw new TypeError('options.trim, when provided, must be an object.');
756
+ }
757
+ if (options.trim?.start !== undefined && (!Number.isFinite(options.trim.start))) {
758
+ throw new TypeError('options.trim.start, when provided, must be a finite number.');
759
+ }
760
+ if (options.trim?.end !== undefined && (!Number.isFinite(options.trim.end))) {
761
+ throw new TypeError('options.trim.end, when provided, must be a finite number.');
762
+ }
763
+ if (
764
+ options.trim?.start !== undefined
765
+ && options.trim.end !== undefined
766
+ && options.trim.start >= options.trim.end) {
767
+ throw new TypeError('options.trim.start must be less than options.trim.end.');
768
+ }
769
+ if (
770
+ options.tags !== undefined
771
+ && (typeof options.tags !== 'object' || !options.tags)
772
+ && typeof options.tags !== 'function'
773
+ ) {
774
+ throw new TypeError('options.tags, when provided, must be an object or a function.');
775
+ }
776
+ if (typeof options.tags === 'object') {
777
+ validateMetadataTags(options.tags);
778
+ }
779
+ if (options.showWarnings !== undefined && typeof options.showWarnings !== 'boolean') {
780
+ throw new TypeError('options.showWarnings, when provided, must be a boolean.');
781
+ }
782
+
783
+ this._options = options;
784
+ this._composable = composable;
785
+ this.input = options.input;
786
+ this.output = options.output;
787
+ }
788
+
789
+ /** @internal */
790
+ async _init() {
791
+ const inputFormat = await this.input.getFormat();
792
+
793
+ let tracks: InputTrack[];
794
+
795
+ let trackMode = this._options.tracks;
796
+ if (trackMode === undefined) {
797
+ // HACK to keep bundle size low, temp for now
798
+ const defaultTrackMode = inputFormat.name.includes('(HLS)')
799
+ ? 'primary'
800
+ : 'all';
801
+
802
+ trackMode = defaultTrackMode;
803
+ }
804
+
805
+ if (trackMode === 'all') {
806
+ tracks = await this.input.getTracks();
807
+ } else if (trackMode === 'primary') {
808
+ const primaryVideoTrack = await this.input.getPrimaryVideoTrack();
809
+ const primaryAudioTrack = await this.input.getPrimaryAudioTrack();
810
+
811
+ tracks = [primaryVideoTrack, primaryAudioTrack].filter(x => x !== null);
812
+ } else {
813
+ assertNever(trackMode);
814
+ assert(false);
815
+ }
816
+
817
+ const outputTrackCounts = this.output.format.getSupportedTrackCounts();
818
+
819
+ // Input track counters
820
+ let nVideo = 1;
821
+ let nAudio = 1;
822
+
823
+ // All tracks that aren't discarded by the user
824
+ const filteredTracks: InputTrack[] = [];
825
+ const filteredTrackOptions: (ConversionVideoOptions | ConversionAudioOptions)[][] = [];
826
+
827
+ for (const track of tracks) {
828
+ let trackOptions: (ConversionVideoOptions | ConversionAudioOptions)[];
829
+
830
+ if (track.isVideoTrack()) {
831
+ if (this._options.video) {
832
+ if (typeof this._options.video === 'function') {
833
+ const returnedTrackOptions = await this._options.video(track, nVideo) ?? {};
834
+ if (Array.isArray(returnedTrackOptions)) {
835
+ for (const obj of returnedTrackOptions) {
836
+ validateVideoOptions(obj);
837
+ }
838
+ } else {
839
+ validateVideoOptions(returnedTrackOptions);
840
+ }
841
+
842
+ trackOptions = Array.isArray(returnedTrackOptions)
843
+ ? returnedTrackOptions
844
+ : [returnedTrackOptions];
845
+
846
+ nVideo++;
847
+ } else {
848
+ // Already validated
849
+ trackOptions = Array.isArray(this._options.video)
850
+ ? this._options.video
851
+ : [this._options.video];
852
+ }
853
+ } else {
854
+ trackOptions = [{}];
855
+ }
856
+ } else if (track.isAudioTrack()) {
857
+ if (this._options.audio) {
858
+ if (typeof this._options.audio === 'function') {
859
+ const returnedTrackOptions = await this._options.audio(track, nAudio) ?? {};
860
+ if (Array.isArray(returnedTrackOptions)) {
861
+ for (const obj of returnedTrackOptions) {
862
+ validateAudioOptions(obj);
863
+ }
864
+ } else {
865
+ validateAudioOptions(returnedTrackOptions);
866
+ }
867
+
868
+ trackOptions = Array.isArray(returnedTrackOptions)
869
+ ? returnedTrackOptions
870
+ : [returnedTrackOptions];
871
+
872
+ nAudio++;
873
+ } else {
874
+ // Already validated
875
+ trackOptions = Array.isArray(this._options.audio)
876
+ ? this._options.audio
877
+ : [this._options.audio];
878
+ }
879
+ } else {
880
+ trackOptions = [{}];
881
+ }
882
+ } else {
883
+ assert(false);
884
+ }
885
+
886
+ const discardOptions = trackOptions.filter(x => x.discard);
887
+ for (const discardOption of discardOptions) {
888
+ this.discardedTracks.push({
889
+ track,
890
+ reason: 'discarded_by_user',
891
+ trackOptions: discardOption,
892
+ });
893
+ }
894
+
895
+ if (trackOptions.length === discardOptions.length) {
896
+ if (trackOptions.length === 0) {
897
+ this.discardedTracks.push({
898
+ track,
899
+ reason: 'discarded_by_user',
900
+ trackOptions: {},
901
+ });
902
+ }
903
+
904
+ continue;
905
+ }
906
+
907
+ const nonDiscardOptions = trackOptions.filter(x => !x.discard);
908
+ filteredTracks.push(track);
909
+ filteredTrackOptions.push(nonDiscardOptions);
910
+ }
911
+
912
+ if (this._options.trim?.start !== undefined) {
913
+ this._startTimestamp = this._options.trim.start;
914
+ } else {
915
+ // Compute the start timestamp from the set of filtered tracks. Technically these can still be narrowed
916
+ // down later due to discarded tracks, but we need to fix the start timestamp now due to track processing
917
+ // depending on it.
918
+ this._startTimestamp = Math.max(
919
+ await this.input.getFirstTimestamp(filteredTracks),
920
+ // Samples can also have negative timestamps, but the meaning typically is "don't present me", so let's
921
+ // cut those out by default.
922
+ 0,
923
+ );
924
+ }
925
+
926
+ this._endTimestamp = Math.max(this._options.trim?.end ?? Infinity, this._startTimestamp);
927
+
928
+ // Run these sequentially so that output tracks have a deterministic order
929
+ for (let i = 0; i < filteredTracks.length; i++) {
930
+ const track = filteredTracks[i]!;
931
+ const options = filteredTrackOptions[i]!;
932
+
933
+ for (const option of options) {
934
+ if (this.output.tracks.length === outputTrackCounts.total.max) {
935
+ this.discardedTracks.push({
936
+ track,
937
+ reason: 'max_track_count_reached',
938
+ trackOptions: option,
939
+ });
940
+ continue;
941
+ }
942
+
943
+ const addedCountOfType = this.output.tracks.reduce(
944
+ (count, t) => count + (t.type === track.type ? 1 : 0),
945
+ 0,
946
+ );
947
+
948
+ if (addedCountOfType === outputTrackCounts[track.type].max) {
949
+ this.discardedTracks.push({
950
+ track,
951
+ reason: 'max_track_count_of_type_reached',
952
+ trackOptions: option,
953
+ });
954
+ continue;
955
+ }
956
+
957
+ const outputTrackId = this._nextOutputTrackId++;
958
+
959
+ if (track.isVideoTrack()) {
960
+ await this._processVideoTrack(track, option as ConversionVideoOptions, outputTrackId);
961
+ } else if (track.isAudioTrack()) {
962
+ await this._processAudioTrack(track, option as ConversionAudioOptions, outputTrackId);
963
+ } else {
964
+ assert(false);
965
+ }
966
+ }
967
+ }
968
+
969
+ // When no track groups are set by the user, then the output track pairability should be *identical* to the
970
+ // input's. We do the naive algorithm to achieve this: assign each track to its own group, and pair groups with
971
+ // each other based on input track pairability.
972
+ for (let i = 0; i < this.utilizedTracks.length - 1; i++) {
973
+ for (let j = i + 1; j < this.utilizedTracks.length; j++) {
974
+ const trackA = this.utilizedTracks[i]!;
975
+ const trackB = this.utilizedTracks[j]!;
976
+ const ownGroupA = this._outputOwnTrackGroups[i];
977
+ const ownGroupB = this._outputOwnTrackGroups[j];
978
+
979
+ assert(ownGroupA !== undefined);
980
+ assert(ownGroupB !== undefined);
981
+
982
+ if (ownGroupA && ownGroupB && trackA.canBePairedWith(trackB)) {
983
+ ownGroupA.pairWith(ownGroupB);
984
+ }
985
+ }
986
+ }
987
+
988
+ // Now, let's deal with metadata tags. A composable conversion does not touch the output's metadata tags; that
989
+ // remains the responsibility of whoever owns the output.
990
+
991
+ if (!this._composable) {
992
+ const inputTags = await this.input.getMetadataTags();
993
+ let outputTags: MetadataTags;
994
+
995
+ if (this._options.tags) {
996
+ const result = typeof this._options.tags === 'function'
997
+ ? await this._options.tags(inputTags)
998
+ : this._options.tags;
999
+ validateMetadataTags(result);
1000
+
1001
+ outputTags = result;
1002
+ } else {
1003
+ outputTags = inputTags;
1004
+ }
1005
+
1006
+ // Somewhat dirty but pragmatic
1007
+ const inputAndOutputFormatMatch = inputFormat.mimeType === this.output.format.mimeType;
1008
+ const rawTagsAreUnchanged = inputTags.raw === outputTags.raw;
1009
+
1010
+ if (inputTags.raw && rawTagsAreUnchanged && !inputAndOutputFormatMatch) {
1011
+ // If the input and output formats aren't the same, copying over raw metadata tags makes no sense and
1012
+ // only results in junk tags, so let's cut them out.
1013
+ delete outputTags.raw;
1014
+ }
1015
+
1016
+ this.output.setMetadataTags(outputTags);
1017
+ }
1018
+
1019
+ // Let's check if the conversion can actually be executed
1020
+ if (!this._composable) {
1021
+ this.isValid = this.output.hasEnoughTracks();
1022
+ } else {
1023
+ // Checking Output start validity is not up to us. We consider even zero-track conversions to be valid
1024
+ this.isValid = true;
1025
+ }
1026
+
1027
+ if (this._options.showWarnings ?? true) {
1028
+ const warnElements: unknown[] = [];
1029
+
1030
+ const unintentionallyDiscardedTracks = this.discardedTracks.filter(x => x.reason !== 'discarded_by_user');
1031
+ if (unintentionallyDiscardedTracks.length > 0) {
1032
+ // Let's give the user a notice/warning about discarded tracks so they aren't confused
1033
+ warnElements.push(
1034
+ 'Some tracks had to be discarded from the conversion:', unintentionallyDiscardedTracks,
1035
+ );
1036
+ }
1037
+
1038
+ if (!this.isValid) {
1039
+ if (warnElements.length > 0) {
1040
+ warnElements.push('\n\n');
1041
+ }
1042
+
1043
+ warnElements.push(this._getInvalidityExplanation().join(''));
1044
+ }
1045
+
1046
+ if (warnElements.length > 0) {
1047
+ Logging._warn(...warnElements);
1048
+ }
1049
+ }
1050
+ }
1051
+
1052
+ /** @internal */
1053
+ _getInvalidityExplanation() {
1054
+ const elements: string[] = [];
1055
+
1056
+ if (this.discardedTracks.length === 0) {
1057
+ elements.push(
1058
+ 'Due to missing tracks, this conversion cannot be executed.',
1059
+ );
1060
+ } else {
1061
+ const encodabilityIsTheProblem = this.discardedTracks.every(x =>
1062
+ x.reason === 'discarded_by_user' || x.reason === 'no_encodable_target_codec',
1063
+ ) && this.discardedTracks.some(x => x.reason === 'no_encodable_target_codec');
1064
+
1065
+ elements.push(
1066
+ 'Due to discarded tracks, this conversion cannot be executed.',
1067
+ );
1068
+
1069
+ if (encodabilityIsTheProblem) {
1070
+ const codecs = this.discardedTracks.flatMap((x) => {
1071
+ if (x.reason === 'discarded_by_user') return [];
1072
+
1073
+ let supportedCodecs: MediaCodec[];
1074
+ if (x.track.type === 'video') {
1075
+ supportedCodecs = this.output.format.getSupportedVideoCodecs();
1076
+ } else if (x.track.type === 'audio') {
1077
+ supportedCodecs = this.output.format.getSupportedAudioCodecs();
1078
+ } else {
1079
+ supportedCodecs = this.output.format.getSupportedSubtitleCodecs();
1080
+ }
1081
+
1082
+ // If the user requested a specific codec, only that codec was ever attempted
1083
+ return supportedCodecs.filter(codec => !x.trackOptions.codec || codec === x.trackOptions.codec);
1084
+ });
1085
+
1086
+ const uniqueCodecs = [...new Set(codecs)];
1087
+
1088
+ if (uniqueCodecs.length === 1) {
1089
+ elements.push(
1090
+ `\nTracks were discarded because your environment is not able to encode '${uniqueCodecs[0]}'`
1091
+ + ' with the provided parameters.',
1092
+ );
1093
+ } else {
1094
+ elements.push(
1095
+ '\nTracks were discarded because your environment is not able to encode any of the codecs'
1096
+ + ` ${uniqueCodecs.map(x => `'${x}'`).join(', ')} with the provided parameters.`,
1097
+ );
1098
+ }
1099
+
1100
+ if (uniqueCodecs.includes('mp3')) {
1101
+ elements.push(
1102
+ `\nThe @mediabunny/mp3-encoder extension package provides support for encoding MP3.`,
1103
+ );
1104
+ }
1105
+
1106
+ if (uniqueCodecs.includes('aac')) {
1107
+ elements.push(
1108
+ '\nThe @mediabunny/aac-encoder extension package provides support for encoding AAC.',
1109
+ );
1110
+ }
1111
+
1112
+ if (uniqueCodecs.includes('ac3') || uniqueCodecs.includes('eac3')) {
1113
+ elements.push(
1114
+ '\nThe @mediabunny/ac3 extension package provides support'
1115
+ + ' for encoding and decoding AC-3/E-AC-3.',
1116
+ );
1117
+ }
1118
+
1119
+ if (uniqueCodecs.includes('flac')) {
1120
+ elements.push(
1121
+ '\nThe @mediabunny/flac-encoder extension package provides support for encoding FLAC.',
1122
+ );
1123
+ }
1124
+ } else {
1125
+ elements.push('\nCheck the discardedTracks field for more info.');
1126
+ }
1127
+ }
1128
+
1129
+ return elements;
1130
+ }
1131
+
1132
+ /**
1133
+ * Executes the conversion process and resolves when the conversion is complete. When
1134
+ * {@link ConversionExecuteOptions.until} is provided, the conversion will be suspended once that output timestamp
1135
+ * is reached and can be resumed with another call to `execute`. An ongoing execution may also be suspended via
1136
+ * {@link ConversionExecuteOptions.pauseSignal}.
1137
+ *
1138
+ * Execution will throw if `isValid` is `false`.
1139
+ */
1140
+ async execute(options: ConversionExecuteOptions = {}) {
1141
+ if (!options || typeof options !== 'object') {
1142
+ throw new TypeError('options must be an object.');
1143
+ }
1144
+ if (options.until !== undefined && (typeof options.until !== 'number' || Number.isNaN(options.until))) {
1145
+ throw new TypeError('options.until, when provided, must be a number.');
1146
+ }
1147
+ if (options.pauseSignal !== undefined && !(options.pauseSignal instanceof AbortSignal)) {
1148
+ throw new TypeError('options.pauseSignal, when provided, must be an AbortSignal.');
1149
+ }
1150
+
1151
+ if (!this.isValid) {
1152
+ throw new Error(
1153
+ 'Cannot execute this conversion because its output configuration is invalid. Make sure to always check'
1154
+ + ' the isValid field before executing a conversion.\n'
1155
+ + this._getInvalidityExplanation().join(''),
1156
+ );
1157
+ }
1158
+
1159
+ if (this.state === 'executing') {
1160
+ throw new Error('Cannot call execute() while a previous call to execute() is still running.');
1161
+ }
1162
+
1163
+ if (this.state === 'canceled') {
1164
+ throw new ConversionCanceledError();
1165
+ }
1166
+
1167
+ if (this.state === 'done') {
1168
+ // The conversion already ran to completion, nothing left to do
1169
+ return;
1170
+ }
1171
+
1172
+ if (this._composable && this.output.state === 'pending') {
1173
+ throw new Error(
1174
+ 'A composable conversion requires the output to be started. Call start() on the output before executing'
1175
+ + ' the conversion.',
1176
+ );
1177
+ }
1178
+
1179
+ this.state = 'executing';
1180
+ this._executionUntil = options.until ?? Infinity;
1181
+ this._pauseRequested = options.pauseSignal?.aborted ?? false;
1182
+
1183
+ const onPause = () => {
1184
+ if (this.state !== 'executing') {
1185
+ return;
1186
+ }
1187
+
1188
+ this._pauseRequested = true;
1189
+
1190
+ // Release any pumps stuck in the synchronizer so they can reach their next checkpoint and suspend
1191
+ this._synchronizer.resolveAll();
1192
+ };
1193
+ options.pauseSignal?.addEventListener('abort', onPause);
1194
+
1195
+ for (const pump of this._trackPumps) {
1196
+ if (!pump.done) {
1197
+ pump.resolvers = promiseWithResolvers();
1198
+ }
1199
+ }
1200
+
1201
+ if (!this._executed) {
1202
+ this._executed = true;
1203
+
1204
+ for (const id of this._outputTrackIds) {
1205
+ this._synchronizer.declareTrack(id);
1206
+ }
1207
+
1208
+ if (this.onProgress) {
1209
+ // Compute duration using only the utilized tracks
1210
+ const uniqueUtilizedTracks = new Set(this.utilizedTracks);
1211
+ const durationPromises = [...uniqueUtilizedTracks].map(async (track) => {
1212
+ if (await track.isLive()) {
1213
+ return Infinity; // Upper bound (assuming no universe heat death)
1214
+ }
1215
+
1216
+ return (await track.getDurationFromMetadata()) ?? (await track.computeDuration());
1217
+ });
1218
+ const duration = Math.max(0, ...await Promise.all(durationPromises));
1219
+
1220
+ this._computeProgress = true;
1221
+ this._totalDuration = Math.min(
1222
+ duration - this._startTimestamp,
1223
+ this._endTimestamp - this._startTimestamp,
1224
+ );
1225
+
1226
+ for (const id of this._outputTrackIds) {
1227
+ this._maxTimestamps.set(id, 0);
1228
+ }
1229
+
1230
+ this.onProgress?.(0, 0);
1231
+ }
1232
+
1233
+ if (!this._composable) {
1234
+ await this.output.start();
1235
+ }
1236
+
1237
+ for (const pump of this._trackPumps) {
1238
+ pump.start();
1239
+ }
1240
+ } else {
1241
+ // Wake all suspended track pumps
1242
+ for (const pump of this._trackPumps) {
1243
+ pump.wake?.();
1244
+ }
1245
+ }
1246
+
1247
+ try {
1248
+ await Promise.all(this._trackPumps.map(x => x.resolvers.promise));
1249
+ } catch (error) {
1250
+ if ((this.state as Conversion['state']) !== 'canceled') {
1251
+ // Make sure to cancel to stop other encoding processes and clean up resources
1252
+ void this.cancel();
1253
+ }
1254
+
1255
+ throw error;
1256
+ } finally {
1257
+ options.pauseSignal?.removeEventListener('abort', onPause);
1258
+ }
1259
+
1260
+ if ((this.state as Conversion['state']) === 'canceled') {
1261
+ throw new ConversionCanceledError();
1262
+ }
1263
+
1264
+ const isDone = this._trackPumps.every(x => x.done);
1265
+ this.state = isDone ? 'done' : 'idle';
1266
+
1267
+ if (isDone) {
1268
+ if (!this._composable) {
1269
+ await this.output.finalize();
1270
+ }
1271
+
1272
+ if (this._computeProgress) {
1273
+ const minTimestamp = Math.min(...this._maxTimestamps.values());
1274
+ this.onProgress?.(1, minTimestamp);
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ /**
1280
+ * Cancels the conversion process, causing any ongoing `execute` call to throw a `ConversionCanceledError`.
1281
+ * Does nothing if the conversion is already complete.
1282
+ */
1283
+ async cancel() {
1284
+ if (this.state === 'done') {
1285
+ return;
1286
+ }
1287
+
1288
+ if (this.state === 'canceled') {
1289
+ Logging._warn('Conversion already canceled.');
1290
+ return;
1291
+ }
1292
+
1293
+ this.state = 'canceled';
1294
+
1295
+ // Wake all suspended track pumps so they can wind down
1296
+ for (const pump of this._trackPumps) {
1297
+ pump.wake?.();
1298
+ }
1299
+
1300
+ this._synchronizer.resolveAll();
1301
+
1302
+ if (!this._composable) {
1303
+ await this.output.cancel();
1304
+ }
1305
+ }
1306
+
1307
+ /** @internal */
1308
+ async _processVideoTrack(track: InputVideoTrack, trackOptions: ConversionVideoOptions, outputTrackId: number) {
1309
+ const sourceCodec = await track.getCodec();
1310
+ if (!sourceCodec) {
1311
+ this.discardedTracks.push({
1312
+ track,
1313
+ reason: 'unknown_source_codec',
1314
+ trackOptions,
1315
+ });
1316
+ return;
1317
+ }
1318
+
1319
+ let videoSource: VideoSource;
1320
+
1321
+ const innateRotation = await track.getRotation();
1322
+ const totalRotation = normalizeRotation(innateRotation + (trackOptions.rotate ?? 0));
1323
+ let outputTrackRotation = totalRotation;
1324
+ const canUseRotationMetadata = this.output.format.supportsVideoRotationMetadata
1325
+ && (trackOptions.allowRotationMetadata ?? true);
1326
+
1327
+ const squarePixelWidth = await track.getSquarePixelWidth();
1328
+ const squarePixelHeight = await track.getSquarePixelHeight();
1329
+ const [rotatedWidth, rotatedHeight] = totalRotation % 180 === 0
1330
+ ? [squarePixelWidth, squarePixelHeight]
1331
+ : [squarePixelHeight, squarePixelWidth];
1332
+
1333
+ let crop = trackOptions.crop;
1334
+ if (crop) {
1335
+ crop = clampCropRectangle(crop, rotatedWidth, rotatedHeight);
1336
+ }
1337
+
1338
+ const [originalWidth, originalHeight] = crop
1339
+ ? [crop.width, crop.height]
1340
+ : [rotatedWidth, rotatedHeight];
1341
+
1342
+ let width = originalWidth;
1343
+ let height = originalHeight;
1344
+ const aspectRatio = width / height;
1345
+
1346
+ // A lot of video encoders require that the dimensions be multiples of 2
1347
+ if (trackOptions.width !== undefined && trackOptions.height === undefined) {
1348
+ width = ceilToMultipleOfTwo(trackOptions.width);
1349
+ height = ceilToMultipleOfTwo(Math.round(width / aspectRatio));
1350
+ } else if (trackOptions.width === undefined && trackOptions.height !== undefined) {
1351
+ height = ceilToMultipleOfTwo(trackOptions.height);
1352
+ width = ceilToMultipleOfTwo(Math.round(height * aspectRatio));
1353
+ } else if (trackOptions.width !== undefined && trackOptions.height !== undefined) {
1354
+ width = ceilToMultipleOfTwo(trackOptions.width);
1355
+ height = ceilToMultipleOfTwo(trackOptions.height);
1356
+ }
1357
+
1358
+ const firstTimestamp = await track.getFirstTimestamp();
1359
+ let videoCodecs = this.output.format.getSupportedVideoCodecs();
1360
+
1361
+ const needsTranscode = !!trackOptions.forceTranscode
1362
+ || firstTimestamp < this._startTimestamp
1363
+ || !!trackOptions.frameRate
1364
+ || trackOptions.keyFrameInterval !== undefined
1365
+ || trackOptions.process !== undefined
1366
+ || trackOptions.quality !== undefined
1367
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
1368
+ || trackOptions.bitrate !== undefined
1369
+ || !videoCodecs.includes(sourceCodec)
1370
+ || (trackOptions.codec && trackOptions.codec !== sourceCodec)
1371
+ || width !== originalWidth
1372
+ || height !== originalHeight
1373
+ // TODO This is suboptimal: Forcing a rerender when both rotation and process are set is not
1374
+ // performance-optimal, but right now there's no other way because we can't change the track rotation
1375
+ // metadata after the output has already started. Should be possible with API changes in v2, though!
1376
+ || (totalRotation !== 0 && !canUseRotationMetadata)
1377
+ || !!crop;
1378
+
1379
+ const alpha = trackOptions.alpha ?? 'discard';
1380
+
1381
+ if (!needsTranscode) {
1382
+ // Fast path, we can simply copy over the encoded packets
1383
+
1384
+ const source = new EncodedVideoPacketSource(sourceCodec);
1385
+ videoSource = source;
1386
+
1387
+ this._registerTrackPump(async (pump) => {
1388
+ const sink = new EncodedPacketSink(track);
1389
+ const decoderConfig = await track.getDecoderConfig();
1390
+ const meta: EncodedVideoChunkMetadata = { decoderConfig: decoderConfig ?? undefined };
1391
+
1392
+ for await (const packet of sink.packets(undefined, undefined, { verifyKeyPackets: true })) {
1393
+ if (this.state === 'canceled') {
1394
+ break;
1395
+ }
1396
+
1397
+ if (packet.timestamp >= this._endTimestamp) {
1398
+ break;
1399
+ }
1400
+
1401
+ const modifiedPacket = packet.clone({
1402
+ timestamp: packet.timestamp - this._startTimestamp,
1403
+ sideData: alpha === 'discard'
1404
+ ? {} // Remove alpha side data
1405
+ : packet.sideData,
1406
+ });
1407
+ assert(modifiedPacket.timestamp >= 0);
1408
+
1409
+ this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
1410
+ await source.add(modifiedPacket, meta);
1411
+
1412
+ if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
1413
+ await this._synchronizer.wait(modifiedPacket.timestamp);
1414
+ }
1415
+
1416
+ await this._checkpoint(pump, modifiedPacket.timestamp);
1417
+ }
1418
+
1419
+ source.close();
1420
+ this._synchronizer.closeTrack(outputTrackId);
1421
+ });
1422
+ } else {
1423
+ // We need to decode & reencode the video
1424
+
1425
+ const canDecode = await track.canDecode();
1426
+ if (!canDecode) {
1427
+ this.discardedTracks.push({
1428
+ track,
1429
+ reason: 'undecodable_source_codec',
1430
+ trackOptions,
1431
+ });
1432
+ return;
1433
+ }
1434
+
1435
+ if (trackOptions.codec) {
1436
+ videoCodecs = videoCodecs.filter(codec => codec === trackOptions.codec);
1437
+ }
1438
+
1439
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
1440
+ const quality = resolveQuality(trackOptions.quality, trackOptions.bitrate)
1441
+ ?? new Quality('high');
1442
+
1443
+ const encodableCodec = await getFirstEncodableVideoCodec(videoCodecs, {
1444
+ width: trackOptions.process && trackOptions.processedWidth
1445
+ ? trackOptions.processedWidth
1446
+ : width,
1447
+ height: trackOptions.process && trackOptions.processedHeight
1448
+ ? trackOptions.processedHeight
1449
+ : height,
1450
+ quality,
1451
+ });
1452
+ if (!encodableCodec) {
1453
+ this.discardedTracks.push({
1454
+ track,
1455
+ reason: 'no_encodable_target_codec',
1456
+ trackOptions,
1457
+ });
1458
+ return;
1459
+ }
1460
+
1461
+ const encodingConfig: VideoEncodingConfig = {
1462
+ codec: encodableCodec,
1463
+ quality,
1464
+ keyFrameInterval: trackOptions.keyFrameInterval,
1465
+ sizeChangeBehavior: trackOptions.fit ?? 'passThrough',
1466
+ alpha,
1467
+ hardwareAcceleration: trackOptions.hardwareAcceleration,
1468
+ transform: {},
1469
+ };
1470
+ assert(encodingConfig.transform);
1471
+
1472
+ let needsRerender = width !== originalWidth
1473
+ || height !== originalHeight
1474
+ || (totalRotation !== 0 && (!canUseRotationMetadata || trackOptions.process !== undefined))
1475
+ || !!crop
1476
+ // Don't expect encoders to reliably handle non-square pixels:
1477
+ || squarePixelWidth !== await track.getCodedWidth()
1478
+ || squarePixelHeight !== await track.getCodedHeight();
1479
+
1480
+ if (!needsRerender) {
1481
+ // If we're directly passing decoded samples back to the encoder, sometimes the encoder may error due
1482
+ // to lack of support of certain video frame formats, like when HDR is at play. To check for this, we
1483
+ // first try to pass a single frame to the encoder to see how it behaves. If it throws, we then fall
1484
+ // back to the rerender path.
1485
+ //
1486
+ // Creating a new temporary Output is sort of hacky, but due to a lack of an isolated encoder API right
1487
+ // now, this is the simplest way. Will refactor in the future! TODO
1488
+
1489
+ const tempOutput = new Output({
1490
+ format: new Mp4OutputFormat(), // Supports all video codecs
1491
+ target: new NullTarget(),
1492
+ });
1493
+
1494
+ const tempSource = new VideoSampleSource(encodingConfig);
1495
+ tempOutput.addVideoTrack(tempSource);
1496
+
1497
+ await tempOutput.start();
1498
+
1499
+ const sink = new VideoSampleSink(track);
1500
+ using firstSample = await sink.getSample(firstTimestamp); // Let's just use the first sample
1501
+
1502
+ if (firstSample) {
1503
+ try {
1504
+ await tempSource.add(firstSample);
1505
+ firstSample.close();
1506
+ await tempOutput.finalize();
1507
+ } catch (error) {
1508
+ Logging._warn(
1509
+ 'An error occurred when probing encoder support. Falling back to rerender path.', error,
1510
+ );
1511
+ void tempOutput.cancel();
1512
+
1513
+ needsRerender = true;
1514
+ encodingConfig.transform.force = true;
1515
+ }
1516
+ } else {
1517
+ await tempOutput.cancel();
1518
+ }
1519
+ }
1520
+
1521
+ if (trackOptions.frameRate) {
1522
+ encodingConfig.transform.frameRate = trackOptions.frameRate;
1523
+ }
1524
+
1525
+ if (trackOptions.process) {
1526
+ encodingConfig.transform.process = trackOptions.process;
1527
+ }
1528
+
1529
+ if (needsRerender) {
1530
+ outputTrackRotation = 0; // Since the rotation is baked into the output
1531
+
1532
+ encodingConfig.transform.width = width;
1533
+ encodingConfig.transform.height = height;
1534
+ encodingConfig.transform.fit = trackOptions.fit ?? 'fill';
1535
+ encodingConfig.transform.rotate = normalizeRotation(totalRotation - innateRotation);
1536
+ encodingConfig.transform.crop = crop;
1537
+ encodingConfig.transform.alpha = alpha;
1538
+ }
1539
+
1540
+ // We need to do this because `process` can emit new timestamps
1541
+ let lastSampleTimestamp: number | null = null;
1542
+ encodingConfig.onEncodedSample = (sample) => {
1543
+ lastSampleTimestamp = sample.timestamp;
1544
+ };
1545
+
1546
+ const source = new VideoSampleSource(encodingConfig);
1547
+ videoSource = source;
1548
+
1549
+ this._registerTrackPump(async (pump) => {
1550
+ const sink = new VideoSampleSink(track);
1551
+
1552
+ for await (using sample of sink.samples(this._startTimestamp, this._endTimestamp)) {
1553
+ if (this.state === 'canceled') {
1554
+ break;
1555
+ }
1556
+
1557
+ const adjustedSampleTimestamp = Math.max(sample.timestamp - this._startTimestamp, 0);
1558
+ sample.setTimestamp(adjustedSampleTimestamp);
1559
+
1560
+ this._reportProgress(outputTrackId, sample.timestamp + sample.duration);
1561
+ await source.add(sample);
1562
+ sample.close();
1563
+
1564
+ if (lastSampleTimestamp !== null) {
1565
+ if (this._synchronizer.shouldWait(outputTrackId, lastSampleTimestamp)) {
1566
+ await this._synchronizer.wait(lastSampleTimestamp);
1567
+ }
1568
+
1569
+ await this._checkpoint(pump, lastSampleTimestamp);
1570
+ }
1571
+ }
1572
+
1573
+ source.close();
1574
+ this._synchronizer.closeTrack(outputTrackId);
1575
+ });
1576
+ }
1577
+
1578
+ let ownGroup: OutputTrackGroup | null = null;
1579
+ if (!trackOptions.group && !this._composable) {
1580
+ // Create per-track groups to replicate the input's pairability graph. Don't do this for composable
1581
+ // conversions.
1582
+ ownGroup = new OutputTrackGroup();
1583
+ }
1584
+
1585
+ const videoTrackLanguageCode = await track.getLanguageCode();
1586
+ this.output.addVideoTrack(videoSource, {
1587
+ frameRate: trackOptions.frameRate,
1588
+ // TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
1589
+ languageCode: isIso639Dash2LanguageCode(videoTrackLanguageCode) ? videoTrackLanguageCode : undefined,
1590
+ name: await track.getName() ?? undefined,
1591
+ disposition: await track.getDisposition(),
1592
+ rotation: outputTrackRotation,
1593
+ group: ownGroup ?? trackOptions.group,
1594
+ });
1595
+
1596
+ this.utilizedTracks.push(track);
1597
+ this._outputTrackIds.push(outputTrackId);
1598
+ this._outputOwnTrackGroups.push(ownGroup);
1599
+ }
1600
+
1601
+ /** @internal */
1602
+ async _processAudioTrack(track: InputAudioTrack, trackOptions: ConversionAudioOptions, outputTrackId: number) {
1603
+ const sourceCodec = await track.getCodec();
1604
+ if (!sourceCodec) {
1605
+ this.discardedTracks.push({
1606
+ track,
1607
+ reason: 'unknown_source_codec',
1608
+ trackOptions,
1609
+ });
1610
+ return;
1611
+ }
1612
+
1613
+ let audioSource: AudioSource;
1614
+
1615
+ const originalNumberOfChannels = await track.getNumberOfChannels();
1616
+ const originalSampleRate = await track.getSampleRate();
1617
+
1618
+ const firstTimestamp = await track.getFirstTimestamp();
1619
+
1620
+ let numberOfChannels = trackOptions.numberOfChannels ?? originalNumberOfChannels;
1621
+ let sampleRate = trackOptions.sampleRate ?? originalSampleRate;
1622
+
1623
+ const needsTrimming = firstTimestamp < this._startTimestamp;
1624
+ let needsPadding = firstTimestamp > this._startTimestamp && !this.output.format.supportsTimestampedMediaData;
1625
+
1626
+ let audioCodecs = this.output.format.getSupportedAudioCodecs();
1627
+ if (
1628
+ !trackOptions.forceTranscode
1629
+ && !trackOptions.quality
1630
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
1631
+ && !trackOptions.bitrate
1632
+ && numberOfChannels === originalNumberOfChannels
1633
+ && sampleRate === originalSampleRate
1634
+ && !needsTrimming
1635
+ && !needsPadding
1636
+ && audioCodecs.includes(sourceCodec)
1637
+ && (!trackOptions.codec || trackOptions.codec === sourceCodec)
1638
+ && !trackOptions.process
1639
+ && trackOptions.sampleFormat === undefined
1640
+ ) {
1641
+ // Fast path, we can simply copy over the encoded packets
1642
+
1643
+ const source = new EncodedAudioPacketSource(sourceCodec);
1644
+ audioSource = source;
1645
+
1646
+ this._registerTrackPump(async (pump) => {
1647
+ const sink = new EncodedPacketSink(track);
1648
+ const decoderConfig = await track.getDecoderConfig();
1649
+ const meta: EncodedAudioChunkMetadata = { decoderConfig: decoderConfig ?? undefined };
1650
+
1651
+ for await (const packet of sink.packets()) {
1652
+ if (this.state === 'canceled') {
1653
+ break;
1654
+ }
1655
+
1656
+ if (packet.timestamp >= this._endTimestamp) {
1657
+ break;
1658
+ }
1659
+
1660
+ const modifiedPacket = packet.clone({
1661
+ timestamp: packet.timestamp - this._startTimestamp,
1662
+ });
1663
+ assert(modifiedPacket.timestamp >= 0);
1664
+
1665
+ this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
1666
+ await source.add(modifiedPacket, meta);
1667
+
1668
+ if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
1669
+ await this._synchronizer.wait(modifiedPacket.timestamp);
1670
+ }
1671
+
1672
+ await this._checkpoint(pump, modifiedPacket.timestamp);
1673
+ }
1674
+
1675
+ source.close();
1676
+ this._synchronizer.closeTrack(outputTrackId);
1677
+ });
1678
+ } else {
1679
+ // We need to decode & reencode the audio
1680
+
1681
+ const canDecode = await track.canDecode();
1682
+ if (!canDecode) {
1683
+ this.discardedTracks.push({
1684
+ track,
1685
+ reason: 'undecodable_source_codec',
1686
+ trackOptions,
1687
+ });
1688
+ return;
1689
+ }
1690
+
1691
+ let codecOfChoice: AudioCodec | null = null;
1692
+
1693
+ if (trackOptions.codec) {
1694
+ audioCodecs = audioCodecs.filter(codec => codec === trackOptions.codec);
1695
+ }
1696
+
1697
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
1698
+ const quality = resolveQuality(trackOptions.quality, trackOptions.bitrate)
1699
+ ?? new Quality('high');
1700
+
1701
+ const encodableCodecs = await getEncodableAudioCodecs(audioCodecs, {
1702
+ numberOfChannels: trackOptions.process && trackOptions.processedNumberOfChannels
1703
+ ? trackOptions.processedNumberOfChannels
1704
+ : numberOfChannels,
1705
+ sampleRate: trackOptions.process && trackOptions.processedSampleRate
1706
+ ? trackOptions.processedSampleRate
1707
+ : sampleRate,
1708
+ quality,
1709
+ });
1710
+
1711
+ if (
1712
+ !encodableCodecs.some(codec => (NON_PCM_AUDIO_CODECS as readonly string[]).includes(codec))
1713
+ && audioCodecs.some(codec => (NON_PCM_AUDIO_CODECS as readonly string[]).includes(codec))
1714
+ && (numberOfChannels !== FALLBACK_NUMBER_OF_CHANNELS || sampleRate !== FALLBACK_SAMPLE_RATE)
1715
+ ) {
1716
+ // We could not find a compatible non-PCM codec despite the container supporting them. This can be
1717
+ // caused by strange channel count or sample rate configurations. Therefore, let's try again but with
1718
+ // fallback parameters.
1719
+
1720
+ const encodableCodecsWithDefaultParams = await getEncodableAudioCodecs(audioCodecs, {
1721
+ numberOfChannels: FALLBACK_NUMBER_OF_CHANNELS,
1722
+ sampleRate: FALLBACK_SAMPLE_RATE,
1723
+ quality,
1724
+ });
1725
+
1726
+ const nonPcmCodec = encodableCodecsWithDefaultParams
1727
+ .find(codec => (NON_PCM_AUDIO_CODECS as readonly string[]).includes(codec));
1728
+ if (nonPcmCodec) {
1729
+ // We are able to encode using a non-PCM codec, but it'll require resampling
1730
+ codecOfChoice = nonPcmCodec;
1731
+ numberOfChannels = FALLBACK_NUMBER_OF_CHANNELS;
1732
+ sampleRate = FALLBACK_SAMPLE_RATE;
1733
+ }
1734
+ } else {
1735
+ codecOfChoice = encodableCodecs[0] ?? null;
1736
+ }
1737
+
1738
+ if (codecOfChoice === null) {
1739
+ this.discardedTracks.push({
1740
+ track,
1741
+ reason: 'no_encodable_target_codec',
1742
+ trackOptions,
1743
+ });
1744
+ return;
1745
+ }
1746
+
1747
+ const encodingConfig: AudioEncodingConfig = {
1748
+ codec: codecOfChoice,
1749
+ quality,
1750
+ transform: {
1751
+ sampleFormat: trackOptions.sampleFormat,
1752
+ process: trackOptions.process,
1753
+ },
1754
+ };
1755
+ assert(encodingConfig.transform);
1756
+
1757
+ if (numberOfChannels !== originalNumberOfChannels) {
1758
+ encodingConfig.transform.numberOfChannels = numberOfChannels;
1759
+ }
1760
+ if (sampleRate !== originalSampleRate) {
1761
+ encodingConfig.transform.sampleRate = sampleRate;
1762
+ }
1763
+
1764
+ let lastSampleTimestamp: number | null = null;
1765
+ encodingConfig.onEncodedSample = (sample) => {
1766
+ lastSampleTimestamp = sample.timestamp;
1767
+ };
1768
+
1769
+ const source = new AudioSampleSource(encodingConfig);
1770
+ audioSource = source;
1771
+
1772
+ this._registerTrackPump(async (pump) => {
1773
+ const sink = new AudioSampleSink(track);
1774
+ for await (using sample of sink.samples(this._startTimestamp, this._endTimestamp)) {
1775
+ if (this.state === 'canceled') {
1776
+ break;
1777
+ }
1778
+
1779
+ if (needsPadding) {
1780
+ // Add one padding sample at the beginning
1781
+ const paddingLength = firstTimestamp - this._startTimestamp;
1782
+ const paddingLengthSamples = Math.round(paddingLength * originalSampleRate);
1783
+
1784
+ const bytesPerSample = getBytesPerSample(sample.format);
1785
+ const data = new Uint8Array(bytesPerSample * paddingLengthSamples * originalNumberOfChannels);
1786
+ if (sample.format === 'u8' || sample.format === 'u8-planar') {
1787
+ data.fill(2 ** 7); // Fill it with the silent value
1788
+ }
1789
+
1790
+ using silentSample = new AudioSample({
1791
+ data,
1792
+ // Use the same format the decoder is spitting out. This avoids feeding changing sample
1793
+ // formats to the audio encoder.
1794
+ format: sample.format,
1795
+ numberOfChannels: originalNumberOfChannels,
1796
+ sampleRate: originalSampleRate,
1797
+ timestamp: 0,
1798
+ });
1799
+ await this._registerAudioSample(
1800
+ pump, silentSample, source, outputTrackId, () => lastSampleTimestamp,
1801
+ );
1802
+
1803
+ needsPadding = false;
1804
+ }
1805
+
1806
+ let startFrame = 0;
1807
+ let endFrame = sample.numberOfFrames;
1808
+
1809
+ if (sample.timestamp < this._startTimestamp) {
1810
+ startFrame = Math.round((this._startTimestamp - sample.timestamp) * sample.sampleRate);
1811
+ }
1812
+ if (sample.timestamp + sample.duration > this._endTimestamp) {
1813
+ endFrame = Math.round((this._endTimestamp - sample.timestamp) * sample.sampleRate);
1814
+ }
1815
+
1816
+ // Can't assign to "using" identifiers so we gotta do this
1817
+ let finalSampleLet: AudioSample;
1818
+ if (startFrame > 0 || endFrame < sample.numberOfFrames) {
1819
+ // Trim the sample if it sticks out of the trim region on either end
1820
+ const trimmedSample = sample.trim(startFrame, endFrame);
1821
+ sample.close();
1822
+ finalSampleLet = trimmedSample;
1823
+
1824
+ if (trimmedSample.numberOfFrames === 0) {
1825
+ trimmedSample.close();
1826
+ continue;
1827
+ }
1828
+ } else {
1829
+ finalSampleLet = sample;
1830
+ }
1831
+
1832
+ using finalSample = finalSampleLet;
1833
+
1834
+ // Offset the timestamp as needed
1835
+ finalSample.setTimestamp(finalSample.timestamp - this._startTimestamp);
1836
+
1837
+ await this._registerAudioSample(
1838
+ pump, finalSample, source, outputTrackId, () => lastSampleTimestamp,
1839
+ );
1840
+ }
1841
+
1842
+ source.close();
1843
+ this._synchronizer.closeTrack(outputTrackId);
1844
+ });
1845
+ }
1846
+
1847
+ let ownGroup: OutputTrackGroup | null = null;
1848
+ if (!trackOptions.group && !this._composable) {
1849
+ // Create per-track groups to replicate the input's pairability graph. Don't do this for composable
1850
+ // conversions.
1851
+ ownGroup = new OutputTrackGroup();
1852
+ }
1853
+
1854
+ const audioTrackLanguageCode = await track.getLanguageCode();
1855
+ this.output.addAudioTrack(audioSource, {
1856
+ // TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
1857
+ languageCode: isIso639Dash2LanguageCode(audioTrackLanguageCode) ? audioTrackLanguageCode : undefined,
1858
+ name: await track.getName() ?? undefined,
1859
+ disposition: await track.getDisposition(),
1860
+ group: ownGroup ?? trackOptions.group,
1861
+ });
1862
+
1863
+ this.utilizedTracks.push(track);
1864
+ this._outputTrackIds.push(outputTrackId);
1865
+ this._outputOwnTrackGroups.push(ownGroup);
1866
+ }
1867
+
1868
+ /** @internal */
1869
+ async _registerAudioSample(
1870
+ pump: TrackPump,
1871
+ sample: AudioSample,
1872
+ source: AudioSampleSource,
1873
+ outputTrackId: number,
1874
+ getLastSampleTimestamp: () => number | null,
1875
+ ) {
1876
+ this._reportProgress(outputTrackId, sample.timestamp + sample.duration);
1877
+
1878
+ await source.add(sample);
1879
+ sample.close();
1880
+
1881
+ const lastSampleTimestamp = getLastSampleTimestamp();
1882
+ if (lastSampleTimestamp !== null) {
1883
+ if (this._synchronizer.shouldWait(outputTrackId, lastSampleTimestamp)) {
1884
+ await this._synchronizer.wait(lastSampleTimestamp);
1885
+ }
1886
+
1887
+ await this._checkpoint(pump, lastSampleTimestamp);
1888
+ }
1889
+ }
1890
+
1891
+ /** @internal */
1892
+ _registerTrackPump(fn: (pump: TrackPump) => Promise<void>) {
1893
+ const pump: TrackPump = {
1894
+ done: false,
1895
+ resolvers: promiseWithResolvers(),
1896
+ wake: null,
1897
+ start: () => {
1898
+ void fn(pump).then(() => {
1899
+ pump.done = true;
1900
+ pump.resolvers.resolve();
1901
+ }, (error) => {
1902
+ pump.resolvers.reject(error);
1903
+ });
1904
+ },
1905
+ };
1906
+
1907
+ this._trackPumps.push(pump);
1908
+ }
1909
+
1910
+ /** @internal */
1911
+ async _checkpoint(pump: TrackPump, timestamp: number) {
1912
+ while (this.state !== 'canceled' && (timestamp >= this._executionUntil || this._pauseRequested)) {
1913
+ // We've reached the target; signal it and suspend until the next execution wakes us up
1914
+ pump.resolvers.resolve();
1915
+
1916
+ const { promise, resolve } = promiseWithResolvers();
1917
+ pump.wake = resolve;
1918
+ await promise;
1919
+ }
1920
+ }
1921
+
1922
+ /** @internal */
1923
+ _reportProgress(trackId: number, endTimestamp: number) {
1924
+ if (!this._computeProgress) {
1925
+ return;
1926
+ }
1927
+ assert(this._totalDuration !== null);
1928
+
1929
+ this._maxTimestamps.set(
1930
+ trackId,
1931
+ Math.max(endTimestamp, this._maxTimestamps.get(trackId)!),
1932
+ );
1933
+
1934
+ const minTimestamp = Math.min(...this._maxTimestamps.values());
1935
+ const newProgress = clamp(minTimestamp / this._totalDuration, 0, 1);
1936
+
1937
+ if (newProgress !== this._lastProgress) {
1938
+ this._lastProgress = newProgress;
1939
+ this.onProgress?.(newProgress, minTimestamp);
1940
+ }
1941
+ }
1942
+ }
1943
+
1944
+ /**
1945
+ * Thrown when a conversion couldn't complete due to being canceled.
1946
+ * @group Conversion
1947
+ * @public
1948
+ */
1949
+ export class ConversionCanceledError extends Error {
1950
+ /** Creates a new {@link ConversionCanceledError}. */
1951
+ constructor(message = 'Conversion has been canceled.') {
1952
+ super(message);
1953
+ this.name = 'ConversionCanceledError';
1954
+ }
1955
+ }
1956
+
1957
+ const MAX_TIMESTAMP_GAP = 1; // in seconds
1958
+
1959
+ /**
1960
+ * Utility class for synchronizing multiple track packet consumers with one another. We don't want one consumer to get
1961
+ * too out-of-sync with the others, as that may lead to a large number of packets that need to be internally buffered
1962
+ * before they can be written. Therefore, we use this class to slow down a consumer if it is too far ahead of the
1963
+ * slowest consumer.
1964
+ */
1965
+ class TrackSynchronizer {
1966
+ conversion: Conversion;
1967
+ maxTimestamps = new Map<number, number>(); // Track ID -> timestamp
1968
+ resolvers: {
1969
+ timestamp: number;
1970
+ resolve: () => void;
1971
+ }[] = [];
1972
+
1973
+ constructor(conversion: Conversion) {
1974
+ this.conversion = conversion;
1975
+ }
1976
+
1977
+ declareTrack(trackId: number) {
1978
+ this.maxTimestamps.set(trackId, 0);
1979
+ }
1980
+
1981
+ shouldWait(trackId: number, timestamp: number) {
1982
+ const currentValue = this.maxTimestamps.get(trackId);
1983
+ assert(currentValue !== undefined);
1984
+
1985
+ this.maxTimestamps.set(trackId, Math.max(timestamp, currentValue));
1986
+
1987
+ const newMin = this.computeMinAndMaybeResolve();
1988
+ if (
1989
+ this.conversion.state === 'canceled'
1990
+ || this.conversion._pauseRequested
1991
+ || timestamp >= this.conversion._executionUntil
1992
+ ) {
1993
+ // No point in throttling consumers that are about to suspend or wind down anyway
1994
+ return false;
1995
+ }
1996
+
1997
+ return timestamp - newMin > MAX_TIMESTAMP_GAP; // Should wait if it is too far ahead of the slowest consumer
1998
+ }
1999
+
2000
+ wait(timestamp: number) {
2001
+ const { promise, resolve } = promiseWithResolvers();
2002
+
2003
+ this.resolvers.push({
2004
+ timestamp,
2005
+ resolve,
2006
+ });
2007
+
2008
+ return promise;
2009
+ }
2010
+
2011
+ closeTrack(trackId: number) {
2012
+ this.maxTimestamps.delete(trackId);
2013
+ this.computeMinAndMaybeResolve();
2014
+ }
2015
+
2016
+ resolveAll() {
2017
+ for (const entry of this.resolvers) {
2018
+ entry.resolve();
2019
+ }
2020
+ this.resolvers.length = 0;
2021
+ }
2022
+
2023
+ computeMinAndMaybeResolve() {
2024
+ let newMin = Infinity;
2025
+ for (const [, timestamp] of this.maxTimestamps) {
2026
+ newMin = Math.min(newMin, timestamp);
2027
+ }
2028
+
2029
+ for (let i = 0; i < this.resolvers.length; i++) {
2030
+ const entry = this.resolvers[i]!;
2031
+
2032
+ if (entry.timestamp - newMin < MAX_TIMESTAMP_GAP) {
2033
+ // The gap has gotten small enough again, the consumer can continue again
2034
+ entry.resolve();
2035
+ this.resolvers.splice(i, 1);
2036
+ i--;
2037
+ }
2038
+ }
2039
+
2040
+ return newMin;
2041
+ }
2042
+ }