avbridge 2.0.0 → 2.1.1

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 (40) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/NOTICE.md +82 -0
  3. package/THIRD_PARTY_LICENSES.md +121 -0
  4. package/dist/{avi-M5B4SHRM.cjs → avi-GNTV5ZOH.cjs} +4 -4
  5. package/dist/{avi-M5B4SHRM.cjs.map → avi-GNTV5ZOH.cjs.map} +1 -1
  6. package/dist/{avi-POCGZ4JX.js → avi-V6HYQVR2.js} +3 -3
  7. package/dist/{avi-POCGZ4JX.js.map → avi-V6HYQVR2.js.map} +1 -1
  8. package/dist/{chunk-HZF5JDOO.js → chunk-CUQD23WO.js} +4 -4
  9. package/dist/{chunk-HZF5JDOO.js.map → chunk-CUQD23WO.js.map} +1 -1
  10. package/dist/{chunk-5ISVAODK.js → chunk-EJH67FXG.js} +30 -6
  11. package/dist/chunk-EJH67FXG.js.map +1 -0
  12. package/dist/{chunk-Z2FJ5TJC.cjs → chunk-JQH6D4OE.cjs} +31 -6
  13. package/dist/chunk-JQH6D4OE.cjs.map +1 -0
  14. package/dist/{chunk-TTV56KDB.cjs → chunk-O34444ID.cjs} +6 -6
  15. package/dist/{chunk-TTV56KDB.cjs.map → chunk-O34444ID.cjs.map} +1 -1
  16. package/dist/element-browser.js +34550 -0
  17. package/dist/element-browser.js.map +1 -0
  18. package/dist/element.cjs +3 -3
  19. package/dist/element.js +2 -2
  20. package/dist/index.cjs +16 -16
  21. package/dist/index.js +4 -4
  22. package/dist/libav-loader-6APXVNIV.cjs +12 -0
  23. package/dist/{libav-loader-ZHOERPHW.cjs.map → libav-loader-6APXVNIV.cjs.map} +1 -1
  24. package/dist/libav-loader-XKH2TKUW.js +3 -0
  25. package/dist/{libav-loader-KA2MAWLM.js.map → libav-loader-XKH2TKUW.js.map} +1 -1
  26. package/package.json +19 -7
  27. package/src/strategies/fallback/libav-loader.ts +49 -7
  28. package/src/stubs/node-fs-promises.ts +29 -0
  29. package/vendor/libav/README.md +139 -0
  30. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +688 -0
  31. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
  32. package/vendor/libav/avbridge/libav-avbridge.mjs +1 -0
  33. package/vendor/libav/webcodecs/libav-6.8.8.0-webcodecs.wasm.mjs +747 -0
  34. package/vendor/libav/webcodecs/libav-6.8.8.0-webcodecs.wasm.wasm +0 -0
  35. package/vendor/libav/webcodecs/libav-webcodecs.mjs +1 -0
  36. package/vendor/libav/webcodecs/libav.types.d.ts +5222 -0
  37. package/dist/chunk-5ISVAODK.js.map +0 -1
  38. package/dist/chunk-Z2FJ5TJC.cjs.map +0 -1
  39. package/dist/libav-loader-KA2MAWLM.js +0 -3
  40. package/dist/libav-loader-ZHOERPHW.cjs +0 -12
package/CHANGELOG.md CHANGED
@@ -4,7 +4,71 @@ All notable changes to **avbridge** are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
5
5
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [2.0.0]
7
+ ## [2.1.1]
8
+
9
+ ### Fixed
10
+
11
+ - **`dist/element-browser.js` no longer has a bare `libavjs-webcodecs-bridge`
12
+ import.** 2.1.0 inlined mediabunny into the browser bundle but left
13
+ `libavjs-webcodecs-bridge` external, so direct
14
+ `<script type="module">` consumers hit
15
+ `Failed to resolve module specifier "libavjs-webcodecs-bridge"` on load.
16
+ The browser entry now inlines it via `noExternal`. Only the actual
17
+ libav.js WASM variants stay external, and those are loaded via URL
18
+ dynamic imports relative to `import.meta.url`, not bare specifiers.
19
+
20
+ ## [2.1.0]
21
+
22
+ ### Added
23
+
24
+ - **Bundled libav.js binaries.** `npm install avbridge` now ships both
25
+ the `webcodecs` and the custom `avbridge` libav variants under
26
+ `vendor/libav/<variant>/`. Consumers no longer need to install
27
+ `@libav.js/variant-webcodecs` separately, and there's no more "run
28
+ `./scripts/build-libav.sh` for AVI support" friction — both variants
29
+ are in the tarball. Packed tarball: **4.0 MB**, unpacked: **15 MB**.
30
+ Unused asm.js fallbacks and threaded builds are pruned at build time
31
+ to keep the size manageable.
32
+
33
+ - **Pre-bundled browser entry: `avbridge/element-browser`.** A new
34
+ single-file output (`dist/element-browser.js`) intended for direct
35
+ `<script type="module">` consumption without a bundler. mediabunny is
36
+ inlined into the bundle; mediabunny's `node:fs/promises` Node branch
37
+ is aliased to a stub at build time. libav.js stays external and
38
+ lazy-loads from `../vendor/libav/` relative to the module's own URL
39
+ via `import.meta.url`. The usual `dist/index.js` and `dist/element.js`
40
+ entries are unchanged for bundler consumers.
41
+
42
+ - **`THIRD_PARTY_LICENSES.md` and `NOTICE.md`** — full LGPL-2.1
43
+ compliance paperwork for the bundled libav.js binaries. Attribution,
44
+ upstream pointers, replaceability hook documentation, and source
45
+ availability via the reproducible `scripts/build-libav.sh`.
46
+
47
+ ### Changed
48
+
49
+ - **`libavBaseUrl()` now resolves relative to `import.meta.url`** by
50
+ default. When avbridge is installed under `node_modules/avbridge/`,
51
+ the loader automatically finds libav at
52
+ `node_modules/avbridge/vendor/libav/<variant>/` with zero
53
+ configuration. The `AVBRIDGE_LIBAV_BASE` override is still the
54
+ documented escape hatch (and also the LGPL replaceability hook).
55
+
56
+ - **`libav-loader` now preflights variant URLs** with a `bytes=0-0`
57
+ Range request before invoking dynamic import. A missing file now
58
+ throws a clear "libav.js \"<variant>\" variant not reachable at
59
+ <url>" error in <100 ms instead of hanging inside WASM
60
+ instantiation.
61
+
62
+ - **`@libav.js/variant-webcodecs` and `libavjs-webcodecs-bridge`
63
+ promoted from `optionalDependencies` to `dependencies`.** Consumers
64
+ no longer need a separate install step. Only `@libav.js/types` stays
65
+ optional (it's types-only, no runtime code).
66
+
67
+ ### Removed
68
+
69
+ - Nothing. The new browser entry is additive; the classic entries are
70
+ byte-for-byte identical to 2.0.0 except for the loader's default
71
+ path resolution.
8
72
 
9
73
  ### Breaking changes
10
74
 
package/NOTICE.md ADDED
@@ -0,0 +1,82 @@
1
+ # Third-party notices
2
+
3
+ avbridge is distributed under the MIT License (see [LICENSE](./LICENSE)).
4
+
5
+ This package **bundles binary builds** of third-party libraries. Each
6
+ bundled library retains its original license, which you must honor if you
7
+ redistribute avbridge or works that include it.
8
+
9
+ See [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md) for the full
10
+ license texts. This file is a short index.
11
+
12
+ ## Bundled components
13
+
14
+ ### libav.js — LGPL-2.1-or-later
15
+
16
+ `vendor/libav/avbridge/` and `vendor/libav/webcodecs/` contain prebuilt
17
+ libav.js binaries (WebAssembly + JavaScript glue). libav.js is a compilation
18
+ of FFmpeg for the browser.
19
+
20
+ - Upstream: https://github.com/Yahweasel/libav.js
21
+ - License: LGPL-2.1-or-later (FFmpeg's libraries are LGPL; see
22
+ https://ffmpeg.org/legal.html)
23
+ - Bundled variants:
24
+ - `webcodecs` — vendored unmodified from
25
+ [`@libav.js/variant-webcodecs`](https://www.npmjs.com/package/@libav.js/variant-webcodecs)
26
+ at the version pinned in `package.json`.
27
+ - `avbridge` — a custom build produced by `scripts/build-libav.sh`. The
28
+ fragment list, compile flags, and the exact libav.js source commit used
29
+ are documented in [`vendor/libav/README.md`](./vendor/libav/README.md).
30
+ The build script is reproducible: running `./scripts/build-libav.sh`
31
+ downloads the exact upstream sources and reproduces the binary.
32
+
33
+ **LGPL replaceability.** avbridge's libav loader (`libavBaseUrl()` in
34
+ `src/strategies/fallback/libav-loader.ts`) resolves the libav load path at
35
+ runtime and can be overridden by setting `globalThis.AVBRIDGE_LIBAV_BASE`
36
+ to any other URL before the first playback. Consumers who want to replace
37
+ the bundled libav build with their own are therefore not obstructed — the
38
+ bundled binaries are a default, not a lock-in.
39
+
40
+ **Source availability.** avbridge satisfies LGPL-2.1 §6 ("Works that use
41
+ the Library") by:
42
+
43
+ 1. Pointing at the exact upstream project
44
+ ([Yahweasel/libav.js](https://github.com/Yahweasel/libav.js)) and the
45
+ version pinned in `package.json`.
46
+ 2. Shipping the reproducible build script (`scripts/build-libav.sh`) that
47
+ produced the `avbridge` variant, and documenting its inputs in
48
+ `vendor/libav/README.md`.
49
+ 3. Providing the replaceability hook described above, which lets end users
50
+ use a modified version of libav.js in their own applications without
51
+ relinking avbridge.
52
+
53
+ If you need a literal source tarball rather than a build script, please
54
+ open an issue at https://github.com/keishi/avbridge/issues and it will be
55
+ provided.
56
+
57
+ ### mediabunny — MPL-2.0
58
+
59
+ `dist/element-browser.js` (the pre-bundled browser entry) contains
60
+ mediabunny inlined into the bundle. The classic `dist/index.js` and
61
+ `dist/element.js` entries do **not** inline mediabunny; they keep it as an
62
+ external import for bundler consumers.
63
+
64
+ - Upstream: https://github.com/Vanilagy/mediabunny
65
+ - License: MPL-2.0 (https://www.mozilla.org/MPL/2.0/)
66
+ - Inlined version: see `mediabunny` in [`package.json`](./package.json)
67
+
68
+ MPL-2.0 is a file-level copyleft: modifications to MPL-licensed files must
69
+ be released under MPL-2.0, but combining MPL code with differently-licensed
70
+ code (as avbridge does) is fine as long as the MPL-licensed portions remain
71
+ identifiable and their source is available. mediabunny's source is
72
+ available at the upstream repository above; the inlined copy in
73
+ `dist/element-browser.js` is unmodified.
74
+
75
+ ### libavjs-webcodecs-bridge — MIT
76
+
77
+ - Upstream: https://github.com/Yahweasel/libavjs-webcodecs-bridge
78
+ - License: MIT
79
+
80
+ ---
81
+
82
+ For the full license texts, see [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md).
@@ -0,0 +1,121 @@
1
+ # Third-party license texts
2
+
3
+ This document contains the full license text of every third-party
4
+ component bundled with avbridge. The short overview lives in
5
+ [NOTICE.md](./NOTICE.md); this file is what you need if you redistribute
6
+ avbridge and have to comply with the underlying licenses.
7
+
8
+ ---
9
+
10
+ ## libav.js (LGPL-2.1-or-later)
11
+
12
+ avbridge bundles prebuilt binaries of libav.js — a compilation of FFmpeg's
13
+ libraries (libavformat, libavcodec, libavfilter, libavutil, libswresample,
14
+ libswscale) for WebAssembly. These binaries live in
15
+ `vendor/libav/avbridge/` and `vendor/libav/webcodecs/`.
16
+
17
+ - Upstream project: https://github.com/Yahweasel/libav.js
18
+ - FFmpeg legal notice: https://ffmpeg.org/legal.html
19
+ - License: **GNU Lesser General Public License version 2.1 or later**
20
+
21
+ The full LGPL-2.1 license text is available at
22
+ https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html and is
23
+ incorporated by reference. avbridge ships this text as a hyperlink rather
24
+ than a copy to keep the tarball size reasonable; the text is short, stable,
25
+ and universally accessible.
26
+
27
+ ### Your obligations if you redistribute avbridge
28
+
29
+ LGPL-2.1 §6 ("Works that use the Library") allows combined works that link
30
+ the library if the recipient can replace the library with a modified
31
+ version. avbridge satisfies this requirement in three ways:
32
+
33
+ 1. **The libav binaries are separate files.** They are not inlined into
34
+ `dist/index.js` or any other JavaScript bundle. They live under
35
+ `vendor/libav/<variant>/` and are loaded at runtime via a dynamic
36
+ import of `libav-<variant>.mjs`. You can replace the `.mjs` and
37
+ `.wasm` files with a different build and the rest of avbridge keeps
38
+ working unchanged.
39
+
40
+ 2. **The load path is user-overridable.** Set
41
+ `globalThis.AVBRIDGE_LIBAV_BASE = "/my/path"` before the first
42
+ playback and avbridge will load libav from your path instead of the
43
+ bundled default. This is the documented replaceability hook.
44
+
45
+ 3. **The build is reproducible.** `scripts/build-libav.sh` in the
46
+ avbridge repository builds the exact `avbridge` variant bundled in
47
+ this package. It downloads the pinned libav.js source, applies the
48
+ fragment list documented in `vendor/libav/README.md`, and writes the
49
+ output to `vendor/libav/avbridge/`. Running it gives you the same
50
+ bytes that ship in the npm tarball.
51
+
52
+ If you need the upstream libav.js / FFmpeg source code that corresponds
53
+ to the bundled binaries, either run `./scripts/build-libav.sh` (which
54
+ downloads it) or obtain it directly from
55
+ https://github.com/Yahweasel/libav.js and https://ffmpeg.org/download.html.
56
+ You may also open an issue at
57
+ https://github.com/keishi/avbridge/issues and a source archive matching
58
+ the shipped binaries will be provided.
59
+
60
+ ---
61
+
62
+ ## mediabunny (MPL-2.0)
63
+
64
+ mediabunny is inlined into `dist/element-browser.js` and kept as an external
65
+ dependency in `dist/index.js` and `dist/element.js`.
66
+
67
+ - Upstream project: https://github.com/Vanilagy/mediabunny
68
+ - License: **Mozilla Public License, version 2.0**
69
+ - License text: https://www.mozilla.org/MPL/2.0/
70
+
71
+ MPL-2.0 is a file-scoped copyleft. You may combine mediabunny with code
72
+ under a different license (as avbridge does), provided:
73
+
74
+ 1. The mediabunny source code remains available to recipients of the
75
+ combined work. avbridge satisfies this by pointing at the unmodified
76
+ upstream repository above; the version bundled is pinned in
77
+ `package.json`.
78
+ 2. Any modifications to mediabunny's own files are released under
79
+ MPL-2.0. avbridge does **not** modify mediabunny — the inlined copy
80
+ in `dist/element-browser.js` is a direct bundle of the unmodified
81
+ upstream source.
82
+
83
+ ---
84
+
85
+ ## libavjs-webcodecs-bridge (MIT)
86
+
87
+ - Upstream project: https://github.com/Yahweasel/libavjs-webcodecs-bridge
88
+ - License: **MIT**
89
+ - Version: as pinned in `package.json`
90
+
91
+ MIT License text (applies to libavjs-webcodecs-bridge):
92
+
93
+ ```
94
+ Copyright (c) Yahweasel and contributors
95
+
96
+ Permission is hereby granted, free of charge, to any person obtaining a
97
+ copy of this software and associated documentation files (the "Software"),
98
+ to deal in the Software without restriction, including without limitation
99
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
100
+ and/or sell copies of the Software, and to permit persons to whom the
101
+ Software is furnished to do so, subject to the following conditions:
102
+
103
+ The above copyright notice and this permission notice shall be included in
104
+ all copies or substantial portions of the Software.
105
+
106
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
107
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
108
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
109
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
110
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
111
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
112
+ OTHER DEALINGS IN THE SOFTWARE.
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Questions
118
+
119
+ If anything here is unclear, or you need a specific form of compliance
120
+ material (source tarballs, signed attestations, build reproducibility
121
+ evidence), open an issue at https://github.com/keishi/avbridge/issues.
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkL4NPOJ36_cjs = require('./chunk-L4NPOJ36.cjs');
4
- var chunkZ2FJ5TJC_cjs = require('./chunk-Z2FJ5TJC.cjs');
4
+ var chunkJQH6D4OE_cjs = require('./chunk-JQH6D4OE.cjs');
5
5
 
6
6
  // src/probe/avi.ts
7
7
  async function probeWithLibav(source, sniffed) {
8
- const libav = await chunkZ2FJ5TJC_cjs.loadLibav("avbridge");
8
+ const libav = await chunkJQH6D4OE_cjs.loadLibav("avbridge");
9
9
  const filename = source.name ?? `input.${sniffed === "unknown" ? "bin" : sniffed}`;
10
10
  const handle = await chunkL4NPOJ36_cjs.prepareLibavInput(libav, filename, source);
11
11
  let fmt_ctx;
@@ -160,5 +160,5 @@ function ffmpegToAvbridgeAudio(name) {
160
160
  }
161
161
 
162
162
  exports.probeWithLibav = probeWithLibav;
163
- //# sourceMappingURL=avi-M5B4SHRM.cjs.map
164
- //# sourceMappingURL=avi-M5B4SHRM.cjs.map
163
+ //# sourceMappingURL=avi-GNTV5ZOH.cjs.map
164
+ //# sourceMappingURL=avi-GNTV5ZOH.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/probe/avi.ts"],"names":["loadLibav","prepareLibavInput"],"mappings":";;;;;;AAuBA,eAAsB,cAAA,CACpB,QACA,OAAA,EACuB;AAKvB,EAAA,MAAM,KAAA,GAAS,MAAMA,2BAAA,CAAU,UAAU,CAAA;AAEzC,EAAA,MAAM,WAAW,MAAA,CAAO,IAAA,IAAQ,SAAS,OAAA,KAAY,SAAA,GAAY,QAAQ,OAAO,CAAA,CAAA;AAIhF,EAAA,MAAM,MAAA,GAA2B,MAAMC,mCAAA,CAAkB,KAAA,EAA6D,UAAU,MAAM,CAAA;AAEtI,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,UAAyB,EAAC;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,oBAAA,CAAqB,QAAQ,CAAA;AACxD,IAAA,OAAA,GAAU,OAAO,CAAC,CAAA;AAClB,IAAA,OAAA,GAAU,OAAO,CAAC,CAAA;AAAA,EACpB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,MAAA,CAAO,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAKpC,IAAA,MAAM,KAAA,GACJ,GAAA,YAAe,KAAA,GACX,GAAA,CAAI,UACJ,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,OACjC,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA,GAClB,OAAO,GAAG,CAAA;AAElB,IAAA,OAAA,CAAQ,KAAA,CAAM,8CAA8C,GAAG,CAAA;AAC/D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,yBAAA,EAA4B,QAAQ,CAAA,8HAAA,EAAiI,KAAA,IAAS,6CAAwC,CAAA,CAAA;AAAA,KACxN;AAAA,EACF;AAEA,EAAA,MAAM,cAAgC,EAAC;AACvC,EAAA,MAAM,cAAgC,EAAC;AAEvC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,SAAA,GAAa,MAAM,IAAA,CAAK,MAAM,KAAA,CAAM,gBAAA,CAAiB,MAAA,CAAO,QAAQ,CAAC,CAAA,IAAM,CAAA,QAAA,EAAW,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAA;AAG3G,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAM,MAAM,mBAAA,CAAoB,MAAA,CAAO,QAAQ,CAAC,CAAA;AAE5E,IAAA,IAAI,MAAA,CAAO,UAAA,KAAe,KAAA,CAAM,kBAAA,EAAoB;AAClD,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAI,MAAA,CAAO,KAAA;AAAA,QACX,KAAA,EAAO,sBAAsB,SAAS,CAAA;AAAA,QACtC,KAAA,EAAO,UAAU,KAAA,IAAS,CAAA;AAAA,QAC1B,MAAA,EAAQ,UAAU,MAAA,IAAU,CAAA;AAAA,QAC5B,GAAA,EAAK,UAAU,MAAM;AAAA,OACtB,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,MAAA,CAAO,UAAA,KAAe,KAAA,CAAM,kBAAA,EAAoB;AACzD,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAI,MAAA,CAAO,KAAA;AAAA,QACX,KAAA,EAAO,sBAAsB,SAAS,CAAA;AAAA,QACtC,QAAA,EAAU,QAAA,EAAU,QAAA,IAAY,QAAA,EAAU,qBAAA,IAAyB,CAAA;AAAA,QACnE,UAAA,EAAY,UAAU,WAAA,IAAe;AAAA,OACtC,CAAA;AAAA,IACH;AAAA,EACF;AAIA,EAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,KAAA,EAAO,OAAQ,CAAA;AAInD,EAAA,MAAM,KAAA,CAAM,uBAAA,CAAwB,OAAQ,CAAA,CAAE,MAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAC5D,EAAA,MAAM,MAAA,CAAO,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAEpC,EAAA,OAAO;AAAA,IACL,QAAQ,MAAA,CAAO,QAAA;AAAA,IACf,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,SAAA,EAAW,OAAA,KAAY,SAAA,GAAY,SAAA,GAAY,OAAA;AAAA,IAC/C,WAAA;AAAA,IACA,WAAA;AAAA,IACA,gBAAgB,EAAC;AAAA,IACjB,QAAA,EAAU,OAAA;AAAA,IACV;AAAA,GACF;AACF;AAEA,SAAS,UAAU,MAAA,EAAyC;AAC1D,EAAA,IAAI,OAAO,MAAA,CAAO,kBAAA,KAAuB,QAAA,IAAY,OAAO,kBAAA,EAAoB;AAC9E,IAAA,OAAO,MAAA,CAAO,qBAAqB,MAAA,CAAO,kBAAA;AAAA,EAC5C;AACA,EAAA,IAAI,MAAA,CAAO,cAAA,IAAkB,OAAO,MAAA,CAAO,mBAAmB,QAAA,EAAU;AACtE,IAAA,IAAI,MAAA,CAAO,cAAA,CAAe,GAAA,KAAQ,CAAA,EAAG,OAAO,MAAA;AAC5C,IAAA,OAAO,MAAA,CAAO,cAAA,CAAe,GAAA,GAAM,MAAA,CAAO,cAAA,CAAe,GAAA;AAAA,EAC3D;AACA,EAAA,OAAO,MAAA;AACT;AAEA,eAAe,YAAA,CAAa,OAAsB,OAAA,EAA8C;AAC9F,EAAA,IAAI;AAQF,IAAA,MAAM,EAAA,GAAK,MAAM,KAAA,CAAM,wBAAA,GAA2B,OAAO,CAAA;AACzD,IAAA,MAAM,EAAA,GAAK,MAAM,KAAA,CAAM,0BAAA,GAA6B,OAAO,CAAA;AAC3D,IAAA,IAAI,OAAO,EAAA,KAAO,QAAA,IAAY,OAAO,EAAA,KAAO,UAAU,OAAO,KAAA,CAAA;AAG7D,IAAA,IAAI,EAAA,KAAO,CAAA,UAAA,IAAe,EAAA,KAAO,CAAA,EAAG,OAAO,KAAA,CAAA;AAI3C,IAAA,MAAM,EAAA,GACJ,OAAO,KAAA,CAAM,QAAA,KAAa,aACtB,KAAA,CAAM,QAAA,CAAS,EAAA,EAAI,EAAE,IACrB,EAAA,GAAK,UAAA,GAAc,EAAA,IAAM,EAAA,GAAK,IAAI,UAAA,GAAc,CAAA,CAAA;AAEtD,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA,IAAM,GAAG,OAAO,KAAA,CAAA;AAC5C,IAAA,OAAO,EAAA,GAAK,GAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,eAAe,KAAQ,EAAA,EAAkD;AACvE,EAAA,IAAI;AAAE,IAAA,OAAO,MAAM,EAAA,EAAG;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,MAAA;AAAA,EAAW;AACvD;AAGA,SAAS,sBAAsB,IAAA,EAA0B;AACvD,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,OAAA;AAAU,MAAA,OAAO,OAAA;AAAA;AAAA,IACtB,KAAK,WAAA;AAAA,IACL,KAAK,WAAA;AAAA,IACL,KAAK,WAAA;AACH,MAAA,OAAO,OAAA;AAAA,IACT,KAAK,MAAA;AAAA,IACL,KAAK,MAAA;AAAA,IACL,KAAK,MAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,YAAA;AAAc,MAAA,OAAO,OAAA;AAAA,IAC1B,KAAK,YAAA;AAAc,MAAA,OAAO,OAAA;AAAA,IAC1B,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB,KAAK,MAAA;AAAA,IACL,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB;AAAe,MAAA,OAAO,IAAA;AAAA;AAE1B;AAEA,SAAS,sBAAsB,IAAA,EAA0B;AACvD,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,KAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AAAU,MAAA,OAAO,OAAA;AAAA,IACtB,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB;AAAe,MAAA,OAAO,IAAA;AAAA;AAE1B","file":"avi-M5B4SHRM.cjs","sourcesContent":["import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport { loadLibav } from \"../strategies/fallback/libav-loader.js\";\n\n/**\n * Probe AVI/ASF/FLV (and any other format mediabunny doesn't speak) via\n * libav.js. This module is `import()`-ed only when sniffing identifies one of\n * those containers.\n *\n * Critical: codec identification goes through `libav.avcodec_get_name(id)`\n * which returns the FFmpeg codec name as a string (e.g. \"h264\", \"mpeg4\",\n * \"wmv3\"). The numeric AV_CODEC_ID_* enum is *not* exposed on the libav\n * instance (only AVMEDIA_TYPE_*, AV_PIX_FMT_*, AV_SAMPLE_FMT_* and a handful\n * of others are), so comparing codec_ids against constants does not work.\n */\nexport async function probeWithLibav(\n source: NormalizedSource,\n sniffed: ContainerKind,\n): Promise<MediaContext> {\n // AVI/ASF/FLV demuxers are not in any libav.js npm variant — they live in\n // the custom \"avbridge\" build produced by `scripts/build-libav.sh`. The loader\n // emits an actionable error if the build hasn't been run yet. Threading\n // is OFF by default in `loadLibav` (see the comment there for why).\n const libav = (await loadLibav(\"avbridge\")) as unknown as LibavInstance;\n\n const filename = source.name ?? `input.${sniffed === \"unknown\" ? \"bin\" : sniffed}`;\n // For Blob/File sources we use libav's in-memory readahead file. For URL\n // sources we attach an HTTP block reader so libav demuxes via Range\n // requests instead of buffering the whole file.\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, source);\n\n let fmt_ctx: number | undefined;\n let streams: LibavStream[] = [];\n try {\n const result = await libav.ff_init_demuxer_file(filename);\n fmt_ctx = result[0];\n streams = result[1];\n } catch (err) {\n await handle.detach().catch(() => {});\n // Errors thrown across the libav.js worker/pthread boundary aren't\n // always Error instances — they can be plain objects, numbers (errno\n // codes), or strings. Stringify defensively so the user-facing message\n // never has `(undefined)` in it.\n const inner =\n err instanceof Error\n ? err.message\n : typeof err === \"object\" && err !== null\n ? JSON.stringify(err)\n : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] ff_init_demuxer_file raw error:\", err);\n throw new Error(\n `libav.js could not demux ${filename}. The current libav variant likely lacks the required demuxer (e.g. AVI). See vendor/libav/README.md for build instructions. (${inner || \"no message — see console for raw error\"})`,\n );\n }\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const stream of streams) {\n const codecName = (await safe(() => libav.avcodec_get_name(stream.codec_id))) ?? `unknown(${stream.codec_id})`;\n // codecpar holds width/height/channels/sample_rate/profile/level/extradata\n // for the actual stream. We have to copy it out of WASM memory.\n const codecpar = await safe(() => libav.ff_copyout_codecpar(stream.codecpar));\n\n if (stream.codec_type === libav.AVMEDIA_TYPE_VIDEO) {\n videoTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeVideo(codecName),\n width: codecpar?.width ?? 0,\n height: codecpar?.height ?? 0,\n fps: framerate(stream),\n });\n } else if (stream.codec_type === libav.AVMEDIA_TYPE_AUDIO) {\n audioTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeAudio(codecName),\n channels: codecpar?.channels ?? codecpar?.ch_layout_nb_channels ?? 0,\n sampleRate: codecpar?.sample_rate ?? 0,\n });\n }\n }\n\n // We need this duration but cannot reliably get it from the streams alone\n // for AVI; libav.js exposes it via the AVFormatContext duration helper.\n const duration = await safeDuration(libav, fmt_ctx!);\n\n // Close the demuxer; the strategy will reopen it later if it ends up being\n // chosen. Probing should not pin native resources.\n await libav.avformat_close_input_js(fmt_ctx!).catch(() => {});\n await handle.detach().catch(() => {});\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container: sniffed === \"unknown\" ? \"unknown\" : sniffed,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"libav\",\n duration,\n };\n}\n\nfunction framerate(stream: LibavStream): number | undefined {\n if (typeof stream.avg_frame_rate_num === \"number\" && stream.avg_frame_rate_den) {\n return stream.avg_frame_rate_num / stream.avg_frame_rate_den;\n }\n if (stream.avg_frame_rate && typeof stream.avg_frame_rate === \"object\") {\n if (stream.avg_frame_rate.den === 0) return undefined;\n return stream.avg_frame_rate.num / stream.avg_frame_rate.den;\n }\n return undefined;\n}\n\nasync function safeDuration(libav: LibavInstance, fmt_ctx: number): Promise<number | undefined> {\n try {\n // `AVFormatContext.duration` is an int64 in microseconds (AV_TIME_BASE).\n // libav.js exposes it as a split lo/hi pair the same way it does for\n // packet pts — `AVFormatContext_duration(ctx)` returns the low 32 bits,\n // `AVFormatContext_durationhi(ctx)` returns the high 32 bits. Reading\n // only the low half (the previous bug) gave garbage for any file whose\n // duration > ~35 minutes, and zero for shorter files where the value\n // happened to live in the high half.\n const lo = await libav.AVFormatContext_duration?.(fmt_ctx);\n const hi = await libav.AVFormatContext_durationhi?.(fmt_ctx);\n if (typeof lo !== \"number\" || typeof hi !== \"number\") return undefined;\n\n // AV_NOPTS_VALUE = -2^63 → ptshi = -2147483648, pts = 0. Means \"unknown\".\n if (hi === -2147483648 && lo === 0) return undefined;\n\n // Reconstruct the 64-bit value. Prefer libav's helper when available\n // because it correctly handles signed 32-bit two's complement.\n const us =\n typeof libav.i64tof64 === \"function\"\n ? libav.i64tof64(lo, hi)\n : hi * 0x100000000 + lo + (lo < 0 ? 0x100000000 : 0);\n\n if (!Number.isFinite(us) || us <= 0) return undefined;\n return us / 1_000_000;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n\n/** Map FFmpeg codec names to avbridge video codec identifiers. */\nfunction ffmpegToAvbridgeVideo(name: string): VideoCodec {\n switch (name) {\n case \"h264\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n case \"mpeg4\": return \"mpeg4\"; // MPEG-4 Part 2 / DivX / Xvid\n case \"msmpeg4v1\":\n case \"msmpeg4v2\":\n case \"msmpeg4v3\": // a.k.a. DIV3\n return \"mpeg4\";\n case \"wmv1\":\n case \"wmv2\":\n case \"wmv3\":\n return \"wmv3\";\n case \"vc1\": return \"vc1\";\n case \"mpeg2video\": return \"mpeg2\";\n case \"mpeg1video\": return \"mpeg1\";\n case \"theora\": return \"theora\";\n case \"rv30\":\n case \"rv40\": return \"rv40\";\n default: return name as VideoCodec;\n }\n}\n\nfunction ffmpegToAvbridgeAudio(name: string): AudioCodec {\n switch (name) {\n case \"aac\": return \"aac\";\n case \"mp3\":\n case \"mp3float\":\n return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n case \"wmav1\":\n case \"wmav2\": return \"wmav2\";\n case \"wmapro\": return \"wmapro\";\n case \"alac\": return \"alac\";\n default: return name as AudioCodec;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Minimal structural types for the slice of libav.js we touch.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n avg_frame_rate?: { num: number; den: number };\n avg_frame_rate_num?: number;\n avg_frame_rate_den?: number;\n}\n\ninterface LibavCodecpar {\n width?: number;\n height?: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n profile?: number;\n level?: number;\n}\n\ninterface LibavInstance {\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_copyout_codecpar(codecpar: number): Promise<LibavCodecpar>;\n avcodec_get_name(codec_id: number): Promise<string>;\n avformat_close_input_js(ctx: number): Promise<void>;\n AVFormatContext_duration?(ctx: number): Promise<number>;\n AVFormatContext_durationhi?(ctx: number): Promise<number>;\n i64tof64?(lo: number, hi: number): number;\n\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n}\n"]}
1
+ {"version":3,"sources":["../src/probe/avi.ts"],"names":["loadLibav","prepareLibavInput"],"mappings":"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","file":"avi-GNTV5ZOH.cjs","sourcesContent":["import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport { loadLibav } from \"../strategies/fallback/libav-loader.js\";\n\n/**\n * Probe AVI/ASF/FLV (and any other format mediabunny doesn't speak) via\n * libav.js. This module is `import()`-ed only when sniffing identifies one of\n * those containers.\n *\n * Critical: codec identification goes through `libav.avcodec_get_name(id)`\n * which returns the FFmpeg codec name as a string (e.g. \"h264\", \"mpeg4\",\n * \"wmv3\"). The numeric AV_CODEC_ID_* enum is *not* exposed on the libav\n * instance (only AVMEDIA_TYPE_*, AV_PIX_FMT_*, AV_SAMPLE_FMT_* and a handful\n * of others are), so comparing codec_ids against constants does not work.\n */\nexport async function probeWithLibav(\n source: NormalizedSource,\n sniffed: ContainerKind,\n): Promise<MediaContext> {\n // AVI/ASF/FLV demuxers are not in any libav.js npm variant — they live in\n // the custom \"avbridge\" build produced by `scripts/build-libav.sh`. The loader\n // emits an actionable error if the build hasn't been run yet. Threading\n // is OFF by default in `loadLibav` (see the comment there for why).\n const libav = (await loadLibav(\"avbridge\")) as unknown as LibavInstance;\n\n const filename = source.name ?? `input.${sniffed === \"unknown\" ? \"bin\" : sniffed}`;\n // For Blob/File sources we use libav's in-memory readahead file. For URL\n // sources we attach an HTTP block reader so libav demuxes via Range\n // requests instead of buffering the whole file.\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, source);\n\n let fmt_ctx: number | undefined;\n let streams: LibavStream[] = [];\n try {\n const result = await libav.ff_init_demuxer_file(filename);\n fmt_ctx = result[0];\n streams = result[1];\n } catch (err) {\n await handle.detach().catch(() => {});\n // Errors thrown across the libav.js worker/pthread boundary aren't\n // always Error instances — they can be plain objects, numbers (errno\n // codes), or strings. Stringify defensively so the user-facing message\n // never has `(undefined)` in it.\n const inner =\n err instanceof Error\n ? err.message\n : typeof err === \"object\" && err !== null\n ? JSON.stringify(err)\n : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] ff_init_demuxer_file raw error:\", err);\n throw new Error(\n `libav.js could not demux ${filename}. The current libav variant likely lacks the required demuxer (e.g. AVI). See vendor/libav/README.md for build instructions. (${inner || \"no message — see console for raw error\"})`,\n );\n }\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const stream of streams) {\n const codecName = (await safe(() => libav.avcodec_get_name(stream.codec_id))) ?? `unknown(${stream.codec_id})`;\n // codecpar holds width/height/channels/sample_rate/profile/level/extradata\n // for the actual stream. We have to copy it out of WASM memory.\n const codecpar = await safe(() => libav.ff_copyout_codecpar(stream.codecpar));\n\n if (stream.codec_type === libav.AVMEDIA_TYPE_VIDEO) {\n videoTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeVideo(codecName),\n width: codecpar?.width ?? 0,\n height: codecpar?.height ?? 0,\n fps: framerate(stream),\n });\n } else if (stream.codec_type === libav.AVMEDIA_TYPE_AUDIO) {\n audioTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeAudio(codecName),\n channels: codecpar?.channels ?? codecpar?.ch_layout_nb_channels ?? 0,\n sampleRate: codecpar?.sample_rate ?? 0,\n });\n }\n }\n\n // We need this duration but cannot reliably get it from the streams alone\n // for AVI; libav.js exposes it via the AVFormatContext duration helper.\n const duration = await safeDuration(libav, fmt_ctx!);\n\n // Close the demuxer; the strategy will reopen it later if it ends up being\n // chosen. Probing should not pin native resources.\n await libav.avformat_close_input_js(fmt_ctx!).catch(() => {});\n await handle.detach().catch(() => {});\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container: sniffed === \"unknown\" ? \"unknown\" : sniffed,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"libav\",\n duration,\n };\n}\n\nfunction framerate(stream: LibavStream): number | undefined {\n if (typeof stream.avg_frame_rate_num === \"number\" && stream.avg_frame_rate_den) {\n return stream.avg_frame_rate_num / stream.avg_frame_rate_den;\n }\n if (stream.avg_frame_rate && typeof stream.avg_frame_rate === \"object\") {\n if (stream.avg_frame_rate.den === 0) return undefined;\n return stream.avg_frame_rate.num / stream.avg_frame_rate.den;\n }\n return undefined;\n}\n\nasync function safeDuration(libav: LibavInstance, fmt_ctx: number): Promise<number | undefined> {\n try {\n // `AVFormatContext.duration` is an int64 in microseconds (AV_TIME_BASE).\n // libav.js exposes it as a split lo/hi pair the same way it does for\n // packet pts — `AVFormatContext_duration(ctx)` returns the low 32 bits,\n // `AVFormatContext_durationhi(ctx)` returns the high 32 bits. Reading\n // only the low half (the previous bug) gave garbage for any file whose\n // duration > ~35 minutes, and zero for shorter files where the value\n // happened to live in the high half.\n const lo = await libav.AVFormatContext_duration?.(fmt_ctx);\n const hi = await libav.AVFormatContext_durationhi?.(fmt_ctx);\n if (typeof lo !== \"number\" || typeof hi !== \"number\") return undefined;\n\n // AV_NOPTS_VALUE = -2^63 → ptshi = -2147483648, pts = 0. Means \"unknown\".\n if (hi === -2147483648 && lo === 0) return undefined;\n\n // Reconstruct the 64-bit value. Prefer libav's helper when available\n // because it correctly handles signed 32-bit two's complement.\n const us =\n typeof libav.i64tof64 === \"function\"\n ? libav.i64tof64(lo, hi)\n : hi * 0x100000000 + lo + (lo < 0 ? 0x100000000 : 0);\n\n if (!Number.isFinite(us) || us <= 0) return undefined;\n return us / 1_000_000;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n\n/** Map FFmpeg codec names to avbridge video codec identifiers. */\nfunction ffmpegToAvbridgeVideo(name: string): VideoCodec {\n switch (name) {\n case \"h264\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n case \"mpeg4\": return \"mpeg4\"; // MPEG-4 Part 2 / DivX / Xvid\n case \"msmpeg4v1\":\n case \"msmpeg4v2\":\n case \"msmpeg4v3\": // a.k.a. DIV3\n return \"mpeg4\";\n case \"wmv1\":\n case \"wmv2\":\n case \"wmv3\":\n return \"wmv3\";\n case \"vc1\": return \"vc1\";\n case \"mpeg2video\": return \"mpeg2\";\n case \"mpeg1video\": return \"mpeg1\";\n case \"theora\": return \"theora\";\n case \"rv30\":\n case \"rv40\": return \"rv40\";\n default: return name as VideoCodec;\n }\n}\n\nfunction ffmpegToAvbridgeAudio(name: string): AudioCodec {\n switch (name) {\n case \"aac\": return \"aac\";\n case \"mp3\":\n case \"mp3float\":\n return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n case \"wmav1\":\n case \"wmav2\": return \"wmav2\";\n case \"wmapro\": return \"wmapro\";\n case \"alac\": return \"alac\";\n default: return name as AudioCodec;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Minimal structural types for the slice of libav.js we touch.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n avg_frame_rate?: { num: number; den: number };\n avg_frame_rate_num?: number;\n avg_frame_rate_den?: number;\n}\n\ninterface LibavCodecpar {\n width?: number;\n height?: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n profile?: number;\n level?: number;\n}\n\ninterface LibavInstance {\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_copyout_codecpar(codecpar: number): Promise<LibavCodecpar>;\n avcodec_get_name(codec_id: number): Promise<string>;\n avformat_close_input_js(ctx: number): Promise<void>;\n AVFormatContext_duration?(ctx: number): Promise<number>;\n AVFormatContext_durationhi?(ctx: number): Promise<number>;\n i64tof64?(lo: number, hi: number): number;\n\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { prepareLibavInput } from './chunk-WD2ZNQA7.js';
2
- import { loadLibav } from './chunk-5ISVAODK.js';
2
+ import { loadLibav } from './chunk-EJH67FXG.js';
3
3
 
4
4
  // src/probe/avi.ts
5
5
  async function probeWithLibav(source, sniffed) {
@@ -158,5 +158,5 @@ function ffmpegToAvbridgeAudio(name) {
158
158
  }
159
159
 
160
160
  export { probeWithLibav };
161
- //# sourceMappingURL=avi-POCGZ4JX.js.map
162
- //# sourceMappingURL=avi-POCGZ4JX.js.map
161
+ //# sourceMappingURL=avi-V6HYQVR2.js.map
162
+ //# sourceMappingURL=avi-V6HYQVR2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/probe/avi.ts"],"names":[],"mappings":"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","file":"avi-POCGZ4JX.js","sourcesContent":["import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport { loadLibav } from \"../strategies/fallback/libav-loader.js\";\n\n/**\n * Probe AVI/ASF/FLV (and any other format mediabunny doesn't speak) via\n * libav.js. This module is `import()`-ed only when sniffing identifies one of\n * those containers.\n *\n * Critical: codec identification goes through `libav.avcodec_get_name(id)`\n * which returns the FFmpeg codec name as a string (e.g. \"h264\", \"mpeg4\",\n * \"wmv3\"). The numeric AV_CODEC_ID_* enum is *not* exposed on the libav\n * instance (only AVMEDIA_TYPE_*, AV_PIX_FMT_*, AV_SAMPLE_FMT_* and a handful\n * of others are), so comparing codec_ids against constants does not work.\n */\nexport async function probeWithLibav(\n source: NormalizedSource,\n sniffed: ContainerKind,\n): Promise<MediaContext> {\n // AVI/ASF/FLV demuxers are not in any libav.js npm variant — they live in\n // the custom \"avbridge\" build produced by `scripts/build-libav.sh`. The loader\n // emits an actionable error if the build hasn't been run yet. Threading\n // is OFF by default in `loadLibav` (see the comment there for why).\n const libav = (await loadLibav(\"avbridge\")) as unknown as LibavInstance;\n\n const filename = source.name ?? `input.${sniffed === \"unknown\" ? \"bin\" : sniffed}`;\n // For Blob/File sources we use libav's in-memory readahead file. For URL\n // sources we attach an HTTP block reader so libav demuxes via Range\n // requests instead of buffering the whole file.\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, source);\n\n let fmt_ctx: number | undefined;\n let streams: LibavStream[] = [];\n try {\n const result = await libav.ff_init_demuxer_file(filename);\n fmt_ctx = result[0];\n streams = result[1];\n } catch (err) {\n await handle.detach().catch(() => {});\n // Errors thrown across the libav.js worker/pthread boundary aren't\n // always Error instances — they can be plain objects, numbers (errno\n // codes), or strings. Stringify defensively so the user-facing message\n // never has `(undefined)` in it.\n const inner =\n err instanceof Error\n ? err.message\n : typeof err === \"object\" && err !== null\n ? JSON.stringify(err)\n : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] ff_init_demuxer_file raw error:\", err);\n throw new Error(\n `libav.js could not demux ${filename}. The current libav variant likely lacks the required demuxer (e.g. AVI). See vendor/libav/README.md for build instructions. (${inner || \"no message — see console for raw error\"})`,\n );\n }\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const stream of streams) {\n const codecName = (await safe(() => libav.avcodec_get_name(stream.codec_id))) ?? `unknown(${stream.codec_id})`;\n // codecpar holds width/height/channels/sample_rate/profile/level/extradata\n // for the actual stream. We have to copy it out of WASM memory.\n const codecpar = await safe(() => libav.ff_copyout_codecpar(stream.codecpar));\n\n if (stream.codec_type === libav.AVMEDIA_TYPE_VIDEO) {\n videoTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeVideo(codecName),\n width: codecpar?.width ?? 0,\n height: codecpar?.height ?? 0,\n fps: framerate(stream),\n });\n } else if (stream.codec_type === libav.AVMEDIA_TYPE_AUDIO) {\n audioTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeAudio(codecName),\n channels: codecpar?.channels ?? codecpar?.ch_layout_nb_channels ?? 0,\n sampleRate: codecpar?.sample_rate ?? 0,\n });\n }\n }\n\n // We need this duration but cannot reliably get it from the streams alone\n // for AVI; libav.js exposes it via the AVFormatContext duration helper.\n const duration = await safeDuration(libav, fmt_ctx!);\n\n // Close the demuxer; the strategy will reopen it later if it ends up being\n // chosen. Probing should not pin native resources.\n await libav.avformat_close_input_js(fmt_ctx!).catch(() => {});\n await handle.detach().catch(() => {});\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container: sniffed === \"unknown\" ? \"unknown\" : sniffed,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"libav\",\n duration,\n };\n}\n\nfunction framerate(stream: LibavStream): number | undefined {\n if (typeof stream.avg_frame_rate_num === \"number\" && stream.avg_frame_rate_den) {\n return stream.avg_frame_rate_num / stream.avg_frame_rate_den;\n }\n if (stream.avg_frame_rate && typeof stream.avg_frame_rate === \"object\") {\n if (stream.avg_frame_rate.den === 0) return undefined;\n return stream.avg_frame_rate.num / stream.avg_frame_rate.den;\n }\n return undefined;\n}\n\nasync function safeDuration(libav: LibavInstance, fmt_ctx: number): Promise<number | undefined> {\n try {\n // `AVFormatContext.duration` is an int64 in microseconds (AV_TIME_BASE).\n // libav.js exposes it as a split lo/hi pair the same way it does for\n // packet pts — `AVFormatContext_duration(ctx)` returns the low 32 bits,\n // `AVFormatContext_durationhi(ctx)` returns the high 32 bits. Reading\n // only the low half (the previous bug) gave garbage for any file whose\n // duration > ~35 minutes, and zero for shorter files where the value\n // happened to live in the high half.\n const lo = await libav.AVFormatContext_duration?.(fmt_ctx);\n const hi = await libav.AVFormatContext_durationhi?.(fmt_ctx);\n if (typeof lo !== \"number\" || typeof hi !== \"number\") return undefined;\n\n // AV_NOPTS_VALUE = -2^63 → ptshi = -2147483648, pts = 0. Means \"unknown\".\n if (hi === -2147483648 && lo === 0) return undefined;\n\n // Reconstruct the 64-bit value. Prefer libav's helper when available\n // because it correctly handles signed 32-bit two's complement.\n const us =\n typeof libav.i64tof64 === \"function\"\n ? libav.i64tof64(lo, hi)\n : hi * 0x100000000 + lo + (lo < 0 ? 0x100000000 : 0);\n\n if (!Number.isFinite(us) || us <= 0) return undefined;\n return us / 1_000_000;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n\n/** Map FFmpeg codec names to avbridge video codec identifiers. */\nfunction ffmpegToAvbridgeVideo(name: string): VideoCodec {\n switch (name) {\n case \"h264\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n case \"mpeg4\": return \"mpeg4\"; // MPEG-4 Part 2 / DivX / Xvid\n case \"msmpeg4v1\":\n case \"msmpeg4v2\":\n case \"msmpeg4v3\": // a.k.a. DIV3\n return \"mpeg4\";\n case \"wmv1\":\n case \"wmv2\":\n case \"wmv3\":\n return \"wmv3\";\n case \"vc1\": return \"vc1\";\n case \"mpeg2video\": return \"mpeg2\";\n case \"mpeg1video\": return \"mpeg1\";\n case \"theora\": return \"theora\";\n case \"rv30\":\n case \"rv40\": return \"rv40\";\n default: return name as VideoCodec;\n }\n}\n\nfunction ffmpegToAvbridgeAudio(name: string): AudioCodec {\n switch (name) {\n case \"aac\": return \"aac\";\n case \"mp3\":\n case \"mp3float\":\n return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n case \"wmav1\":\n case \"wmav2\": return \"wmav2\";\n case \"wmapro\": return \"wmapro\";\n case \"alac\": return \"alac\";\n default: return name as AudioCodec;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Minimal structural types for the slice of libav.js we touch.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n avg_frame_rate?: { num: number; den: number };\n avg_frame_rate_num?: number;\n avg_frame_rate_den?: number;\n}\n\ninterface LibavCodecpar {\n width?: number;\n height?: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n profile?: number;\n level?: number;\n}\n\ninterface LibavInstance {\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_copyout_codecpar(codecpar: number): Promise<LibavCodecpar>;\n avcodec_get_name(codec_id: number): Promise<string>;\n avformat_close_input_js(ctx: number): Promise<void>;\n AVFormatContext_duration?(ctx: number): Promise<number>;\n AVFormatContext_durationhi?(ctx: number): Promise<number>;\n i64tof64?(lo: number, hi: number): number;\n\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n}\n"]}
1
+ {"version":3,"sources":["../src/probe/avi.ts"],"names":[],"mappings":"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","file":"avi-V6HYQVR2.js","sourcesContent":["import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport { loadLibav } from \"../strategies/fallback/libav-loader.js\";\n\n/**\n * Probe AVI/ASF/FLV (and any other format mediabunny doesn't speak) via\n * libav.js. This module is `import()`-ed only when sniffing identifies one of\n * those containers.\n *\n * Critical: codec identification goes through `libav.avcodec_get_name(id)`\n * which returns the FFmpeg codec name as a string (e.g. \"h264\", \"mpeg4\",\n * \"wmv3\"). The numeric AV_CODEC_ID_* enum is *not* exposed on the libav\n * instance (only AVMEDIA_TYPE_*, AV_PIX_FMT_*, AV_SAMPLE_FMT_* and a handful\n * of others are), so comparing codec_ids against constants does not work.\n */\nexport async function probeWithLibav(\n source: NormalizedSource,\n sniffed: ContainerKind,\n): Promise<MediaContext> {\n // AVI/ASF/FLV demuxers are not in any libav.js npm variant — they live in\n // the custom \"avbridge\" build produced by `scripts/build-libav.sh`. The loader\n // emits an actionable error if the build hasn't been run yet. Threading\n // is OFF by default in `loadLibav` (see the comment there for why).\n const libav = (await loadLibav(\"avbridge\")) as unknown as LibavInstance;\n\n const filename = source.name ?? `input.${sniffed === \"unknown\" ? \"bin\" : sniffed}`;\n // For Blob/File sources we use libav's in-memory readahead file. For URL\n // sources we attach an HTTP block reader so libav demuxes via Range\n // requests instead of buffering the whole file.\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, source);\n\n let fmt_ctx: number | undefined;\n let streams: LibavStream[] = [];\n try {\n const result = await libav.ff_init_demuxer_file(filename);\n fmt_ctx = result[0];\n streams = result[1];\n } catch (err) {\n await handle.detach().catch(() => {});\n // Errors thrown across the libav.js worker/pthread boundary aren't\n // always Error instances — they can be plain objects, numbers (errno\n // codes), or strings. Stringify defensively so the user-facing message\n // never has `(undefined)` in it.\n const inner =\n err instanceof Error\n ? err.message\n : typeof err === \"object\" && err !== null\n ? JSON.stringify(err)\n : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] ff_init_demuxer_file raw error:\", err);\n throw new Error(\n `libav.js could not demux ${filename}. The current libav variant likely lacks the required demuxer (e.g. AVI). See vendor/libav/README.md for build instructions. (${inner || \"no message — see console for raw error\"})`,\n );\n }\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const stream of streams) {\n const codecName = (await safe(() => libav.avcodec_get_name(stream.codec_id))) ?? `unknown(${stream.codec_id})`;\n // codecpar holds width/height/channels/sample_rate/profile/level/extradata\n // for the actual stream. We have to copy it out of WASM memory.\n const codecpar = await safe(() => libav.ff_copyout_codecpar(stream.codecpar));\n\n if (stream.codec_type === libav.AVMEDIA_TYPE_VIDEO) {\n videoTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeVideo(codecName),\n width: codecpar?.width ?? 0,\n height: codecpar?.height ?? 0,\n fps: framerate(stream),\n });\n } else if (stream.codec_type === libav.AVMEDIA_TYPE_AUDIO) {\n audioTracks.push({\n id: stream.index,\n codec: ffmpegToAvbridgeAudio(codecName),\n channels: codecpar?.channels ?? codecpar?.ch_layout_nb_channels ?? 0,\n sampleRate: codecpar?.sample_rate ?? 0,\n });\n }\n }\n\n // We need this duration but cannot reliably get it from the streams alone\n // for AVI; libav.js exposes it via the AVFormatContext duration helper.\n const duration = await safeDuration(libav, fmt_ctx!);\n\n // Close the demuxer; the strategy will reopen it later if it ends up being\n // chosen. Probing should not pin native resources.\n await libav.avformat_close_input_js(fmt_ctx!).catch(() => {});\n await handle.detach().catch(() => {});\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container: sniffed === \"unknown\" ? \"unknown\" : sniffed,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"libav\",\n duration,\n };\n}\n\nfunction framerate(stream: LibavStream): number | undefined {\n if (typeof stream.avg_frame_rate_num === \"number\" && stream.avg_frame_rate_den) {\n return stream.avg_frame_rate_num / stream.avg_frame_rate_den;\n }\n if (stream.avg_frame_rate && typeof stream.avg_frame_rate === \"object\") {\n if (stream.avg_frame_rate.den === 0) return undefined;\n return stream.avg_frame_rate.num / stream.avg_frame_rate.den;\n }\n return undefined;\n}\n\nasync function safeDuration(libav: LibavInstance, fmt_ctx: number): Promise<number | undefined> {\n try {\n // `AVFormatContext.duration` is an int64 in microseconds (AV_TIME_BASE).\n // libav.js exposes it as a split lo/hi pair the same way it does for\n // packet pts — `AVFormatContext_duration(ctx)` returns the low 32 bits,\n // `AVFormatContext_durationhi(ctx)` returns the high 32 bits. Reading\n // only the low half (the previous bug) gave garbage for any file whose\n // duration > ~35 minutes, and zero for shorter files where the value\n // happened to live in the high half.\n const lo = await libav.AVFormatContext_duration?.(fmt_ctx);\n const hi = await libav.AVFormatContext_durationhi?.(fmt_ctx);\n if (typeof lo !== \"number\" || typeof hi !== \"number\") return undefined;\n\n // AV_NOPTS_VALUE = -2^63 → ptshi = -2147483648, pts = 0. Means \"unknown\".\n if (hi === -2147483648 && lo === 0) return undefined;\n\n // Reconstruct the 64-bit value. Prefer libav's helper when available\n // because it correctly handles signed 32-bit two's complement.\n const us =\n typeof libav.i64tof64 === \"function\"\n ? libav.i64tof64(lo, hi)\n : hi * 0x100000000 + lo + (lo < 0 ? 0x100000000 : 0);\n\n if (!Number.isFinite(us) || us <= 0) return undefined;\n return us / 1_000_000;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n\n/** Map FFmpeg codec names to avbridge video codec identifiers. */\nfunction ffmpegToAvbridgeVideo(name: string): VideoCodec {\n switch (name) {\n case \"h264\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n case \"mpeg4\": return \"mpeg4\"; // MPEG-4 Part 2 / DivX / Xvid\n case \"msmpeg4v1\":\n case \"msmpeg4v2\":\n case \"msmpeg4v3\": // a.k.a. DIV3\n return \"mpeg4\";\n case \"wmv1\":\n case \"wmv2\":\n case \"wmv3\":\n return \"wmv3\";\n case \"vc1\": return \"vc1\";\n case \"mpeg2video\": return \"mpeg2\";\n case \"mpeg1video\": return \"mpeg1\";\n case \"theora\": return \"theora\";\n case \"rv30\":\n case \"rv40\": return \"rv40\";\n default: return name as VideoCodec;\n }\n}\n\nfunction ffmpegToAvbridgeAudio(name: string): AudioCodec {\n switch (name) {\n case \"aac\": return \"aac\";\n case \"mp3\":\n case \"mp3float\":\n return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n case \"wmav1\":\n case \"wmav2\": return \"wmav2\";\n case \"wmapro\": return \"wmapro\";\n case \"alac\": return \"alac\";\n default: return name as AudioCodec;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Minimal structural types for the slice of libav.js we touch.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n avg_frame_rate?: { num: number; den: number };\n avg_frame_rate_num?: number;\n avg_frame_rate_den?: number;\n}\n\ninterface LibavCodecpar {\n width?: number;\n height?: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n profile?: number;\n level?: number;\n}\n\ninterface LibavInstance {\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_copyout_codecpar(codecpar: number): Promise<LibavCodecpar>;\n avcodec_get_name(codec_id: number): Promise<string>;\n avformat_close_input_js(ctx: number): Promise<void>;\n AVFormatContext_duration?(ctx: number): Promise<number>;\n AVFormatContext_durationhi?(ctx: number): Promise<number>;\n i64tof64?(lo: number, hi: number): number;\n\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { normalizeSource, sniffNormalizedSource } from './chunk-PQTZS7OA.js';
2
- import { loadLibav } from './chunk-5ISVAODK.js';
2
+ import { loadLibav } from './chunk-EJH67FXG.js';
3
3
  import { pickLibavVariant } from './chunk-J5MCMN3S.js';
4
4
 
5
5
  // src/probe/mediabunny.ts
@@ -191,7 +191,7 @@ async function probe(source) {
191
191
  }
192
192
  }
193
193
  try {
194
- const { probeWithLibav } = await import('./avi-POCGZ4JX.js');
194
+ const { probeWithLibav } = await import('./avi-V6HYQVR2.js');
195
195
  return await probeWithLibav(normalized, sniffed);
196
196
  } catch (err) {
197
197
  const inner = err instanceof Error ? err.message : String(err);
@@ -3056,5 +3056,5 @@ function defaultFallbackChain(strategy) {
3056
3056
  }
3057
3057
 
3058
3058
  export { UnifiedPlayer, avbridgeAudioToMediabunny, avbridgeVideoToMediabunny, buildMediabunnySourceFromInput, classifyContext, createPlayer, probe, srtToVtt };
3059
- //# sourceMappingURL=chunk-HZF5JDOO.js.map
3060
- //# sourceMappingURL=chunk-HZF5JDOO.js.map
3059
+ //# sourceMappingURL=chunk-CUQD23WO.js.map
3060
+ //# sourceMappingURL=chunk-CUQD23WO.js.map