avbridge 2.2.1 → 2.5.0

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 (165) hide show
  1. package/CHANGELOG.md +153 -1
  2. package/NOTICE.md +2 -2
  3. package/README.md +2 -3
  4. package/THIRD_PARTY_LICENSES.md +2 -2
  5. package/dist/avi-2JPBSHGA.js +183 -0
  6. package/dist/avi-2JPBSHGA.js.map +1 -0
  7. package/dist/avi-F6WZJK5T.cjs +185 -0
  8. package/dist/avi-F6WZJK5T.cjs.map +1 -0
  9. package/dist/{avi-GCGM7OJI.js → avi-NJXAXUXK.js} +9 -3
  10. package/dist/avi-NJXAXUXK.js.map +1 -0
  11. package/dist/{avi-6SJLWIWW.cjs → avi-W6L3BTWU.cjs} +10 -4
  12. package/dist/avi-W6L3BTWU.cjs.map +1 -0
  13. package/dist/chunk-2IJ66NTD.cjs +212 -0
  14. package/dist/chunk-2IJ66NTD.cjs.map +1 -0
  15. package/dist/{chunk-ILKDNBSE.js → chunk-2XW2O3YI.cjs} +55 -10
  16. package/dist/chunk-2XW2O3YI.cjs.map +1 -0
  17. package/dist/chunk-5KVLE6YI.js +167 -0
  18. package/dist/chunk-5KVLE6YI.js.map +1 -0
  19. package/dist/chunk-5YAWWKA3.js +18 -0
  20. package/dist/chunk-5YAWWKA3.js.map +1 -0
  21. package/dist/chunk-CPJLFFCC.js +189 -0
  22. package/dist/chunk-CPJLFFCC.js.map +1 -0
  23. package/dist/chunk-CPZ7PXAM.cjs +240 -0
  24. package/dist/chunk-CPZ7PXAM.cjs.map +1 -0
  25. package/dist/{chunk-WD2ZNQA7.js → chunk-DCSOQH2N.js} +7 -4
  26. package/dist/chunk-DCSOQH2N.js.map +1 -0
  27. package/dist/{chunk-HZLQNKFN.cjs → chunk-E76AMWI4.js} +40 -15
  28. package/dist/chunk-E76AMWI4.js.map +1 -0
  29. package/dist/chunk-F3LQJKXK.cjs +20 -0
  30. package/dist/chunk-F3LQJKXK.cjs.map +1 -0
  31. package/dist/chunk-IAYKFGFG.js +200 -0
  32. package/dist/chunk-IAYKFGFG.js.map +1 -0
  33. package/dist/{chunk-DMWARSEF.js → chunk-KY2GPCT7.js} +788 -697
  34. package/dist/chunk-KY2GPCT7.js.map +1 -0
  35. package/dist/chunk-LUFA47FP.js +19 -0
  36. package/dist/chunk-LUFA47FP.js.map +1 -0
  37. package/dist/chunk-NNVOHKXJ.cjs +204 -0
  38. package/dist/chunk-NNVOHKXJ.cjs.map +1 -0
  39. package/dist/chunk-Q2VUO52Z.cjs +374 -0
  40. package/dist/chunk-Q2VUO52Z.cjs.map +1 -0
  41. package/dist/chunk-QDJLQR53.cjs +22 -0
  42. package/dist/chunk-QDJLQR53.cjs.map +1 -0
  43. package/dist/chunk-S4WAZC2T.cjs +173 -0
  44. package/dist/chunk-S4WAZC2T.cjs.map +1 -0
  45. package/dist/chunk-SMH6IOP2.js +368 -0
  46. package/dist/chunk-SMH6IOP2.js.map +1 -0
  47. package/dist/chunk-SR3MPV4D.js +237 -0
  48. package/dist/chunk-SR3MPV4D.js.map +1 -0
  49. package/dist/{chunk-UF2N5L63.cjs → chunk-TBW26OPP.cjs} +800 -710
  50. package/dist/chunk-TBW26OPP.cjs.map +1 -0
  51. package/dist/chunk-X2K3GIWE.js +235 -0
  52. package/dist/chunk-X2K3GIWE.js.map +1 -0
  53. package/dist/{chunk-L4NPOJ36.cjs → chunk-Z33SBWL5.cjs} +7 -4
  54. package/dist/chunk-Z33SBWL5.cjs.map +1 -0
  55. package/dist/chunk-ZCUXHW55.cjs +242 -0
  56. package/dist/chunk-ZCUXHW55.cjs.map +1 -0
  57. package/dist/element-browser.js +1282 -503
  58. package/dist/element-browser.js.map +1 -1
  59. package/dist/element.cjs +59 -5
  60. package/dist/element.cjs.map +1 -1
  61. package/dist/element.d.cts +39 -1
  62. package/dist/element.d.ts +39 -1
  63. package/dist/element.js +58 -4
  64. package/dist/element.js.map +1 -1
  65. package/dist/index.cjs +605 -327
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.d.cts +48 -4
  68. package/dist/index.d.ts +48 -4
  69. package/dist/index.js +528 -319
  70. package/dist/index.js.map +1 -1
  71. package/dist/libav-demux-H2GS46GH.cjs +27 -0
  72. package/dist/{libav-http-reader-NQJVY273.js.map → libav-demux-H2GS46GH.cjs.map} +1 -1
  73. package/dist/libav-demux-OWZ4T2YW.js +6 -0
  74. package/dist/{libav-http-reader-FPYDBMYK.cjs.map → libav-demux-OWZ4T2YW.js.map} +1 -1
  75. package/dist/libav-http-reader-AZLE7YFS.cjs +16 -0
  76. package/dist/libav-http-reader-AZLE7YFS.cjs.map +1 -0
  77. package/dist/libav-http-reader-WXG3Z7AI.js +3 -0
  78. package/dist/libav-http-reader-WXG3Z7AI.js.map +1 -0
  79. package/dist/{libav-import-GST2AMPL.cjs → libav-import-2ZVKV2E7.cjs} +2 -2
  80. package/dist/{libav-import-GST2AMPL.cjs.map → libav-import-2ZVKV2E7.cjs.map} +1 -1
  81. package/dist/{libav-import-2JURFHEW.js → libav-import-6MGLCXVQ.js} +2 -2
  82. package/dist/{libav-import-2JURFHEW.js.map → libav-import-6MGLCXVQ.js.map} +1 -1
  83. package/dist/{player-U2NPmFvA.d.cts → player-B6WB74RD.d.cts} +62 -3
  84. package/dist/{player-U2NPmFvA.d.ts → player-B6WB74RD.d.ts} +62 -3
  85. package/dist/player.cjs +5631 -0
  86. package/dist/player.cjs.map +1 -0
  87. package/dist/player.d.cts +699 -0
  88. package/dist/player.d.ts +699 -0
  89. package/dist/player.js +5629 -0
  90. package/dist/player.js.map +1 -0
  91. package/dist/remux-OBSMIENG.cjs +35 -0
  92. package/dist/remux-OBSMIENG.cjs.map +1 -0
  93. package/dist/remux-WBYIZBBX.js +10 -0
  94. package/dist/remux-WBYIZBBX.js.map +1 -0
  95. package/dist/source-4TZ6KMNV.js +4 -0
  96. package/dist/{source-FFZ7TW2B.js.map → source-4TZ6KMNV.js.map} +1 -1
  97. package/dist/source-7YLO6E7X.cjs +29 -0
  98. package/dist/{source-CN43EI7Z.cjs.map → source-7YLO6E7X.cjs.map} +1 -1
  99. package/dist/source-MTX5ELUZ.js +4 -0
  100. package/dist/source-MTX5ELUZ.js.map +1 -0
  101. package/dist/source-VFLXLOCN.cjs +29 -0
  102. package/dist/source-VFLXLOCN.cjs.map +1 -0
  103. package/dist/subtitles-4T74JRGT.js +4 -0
  104. package/dist/subtitles-4T74JRGT.js.map +1 -0
  105. package/dist/subtitles-QUH4LPI4.cjs +29 -0
  106. package/dist/subtitles-QUH4LPI4.cjs.map +1 -0
  107. package/dist/variant-routing-434STYAB.js +3 -0
  108. package/dist/{variant-routing-JOBWXYKD.js.map → variant-routing-434STYAB.js.map} +1 -1
  109. package/dist/variant-routing-HONNAA6R.cjs +12 -0
  110. package/dist/{variant-routing-GOHB2RZN.cjs.map → variant-routing-HONNAA6R.cjs.map} +1 -1
  111. package/package.json +9 -1
  112. package/src/classify/rules.ts +27 -5
  113. package/src/convert/remux.ts +9 -35
  114. package/src/convert/transcode-libav.ts +691 -0
  115. package/src/convert/transcode.ts +53 -12
  116. package/src/element/avbridge-player.ts +861 -0
  117. package/src/element/avbridge-video.ts +54 -0
  118. package/src/element/player-icons.ts +25 -0
  119. package/src/element/player-styles.ts +472 -0
  120. package/src/errors.ts +53 -0
  121. package/src/index.ts +23 -0
  122. package/src/player-element.ts +18 -0
  123. package/src/player.ts +118 -27
  124. package/src/plugins/builtin.ts +2 -2
  125. package/src/probe/avi.ts +4 -0
  126. package/src/probe/index.ts +40 -10
  127. package/src/strategies/fallback/audio-output.ts +31 -0
  128. package/src/strategies/fallback/decoder.ts +179 -175
  129. package/src/strategies/fallback/index.ts +48 -6
  130. package/src/strategies/fallback/libav-import.ts +9 -1
  131. package/src/strategies/fallback/variant-routing.ts +7 -13
  132. package/src/strategies/fallback/video-renderer.ts +231 -32
  133. package/src/strategies/hybrid/decoder.ts +219 -200
  134. package/src/strategies/hybrid/index.ts +48 -7
  135. package/src/strategies/native.ts +6 -3
  136. package/src/strategies/remux/index.ts +14 -2
  137. package/src/strategies/remux/mse.ts +12 -2
  138. package/src/strategies/remux/pipeline.ts +72 -12
  139. package/src/subtitles/index.ts +7 -3
  140. package/src/subtitles/render.ts +8 -0
  141. package/src/types.ts +53 -1
  142. package/src/util/libav-demux.ts +405 -0
  143. package/src/util/libav-http-reader.ts +5 -1
  144. package/src/util/source.ts +28 -8
  145. package/src/util/transport.ts +26 -0
  146. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +1 -1
  147. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
  148. package/dist/avi-6SJLWIWW.cjs.map +0 -1
  149. package/dist/avi-GCGM7OJI.js.map +0 -1
  150. package/dist/chunk-DMWARSEF.js.map +0 -1
  151. package/dist/chunk-HZLQNKFN.cjs.map +0 -1
  152. package/dist/chunk-ILKDNBSE.js.map +0 -1
  153. package/dist/chunk-J5MCMN3S.js +0 -27
  154. package/dist/chunk-J5MCMN3S.js.map +0 -1
  155. package/dist/chunk-L4NPOJ36.cjs.map +0 -1
  156. package/dist/chunk-NZU7W256.cjs +0 -29
  157. package/dist/chunk-NZU7W256.cjs.map +0 -1
  158. package/dist/chunk-UF2N5L63.cjs.map +0 -1
  159. package/dist/chunk-WD2ZNQA7.js.map +0 -1
  160. package/dist/libav-http-reader-FPYDBMYK.cjs +0 -16
  161. package/dist/libav-http-reader-NQJVY273.js +0 -3
  162. package/dist/source-CN43EI7Z.cjs +0 -28
  163. package/dist/source-FFZ7TW2B.js +0 -3
  164. package/dist/variant-routing-GOHB2RZN.cjs +0 -12
  165. package/dist/variant-routing-JOBWXYKD.js +0 -3
@@ -0,0 +1,200 @@
1
+ // src/util/debug.ts
2
+ function isDebugEnabled() {
3
+ if (typeof globalThis === "undefined") return false;
4
+ const g = globalThis;
5
+ if (g.AVBRIDGE_DEBUG === true) return true;
6
+ if (typeof location !== "undefined" && typeof URLSearchParams !== "undefined") {
7
+ try {
8
+ const p = new URLSearchParams(location.search);
9
+ if (p.has("avbridge_debug")) {
10
+ g.AVBRIDGE_DEBUG = true;
11
+ return true;
12
+ }
13
+ } catch {
14
+ }
15
+ }
16
+ return false;
17
+ }
18
+ function fmt(tag) {
19
+ return `[avbridge:${tag}]`;
20
+ }
21
+ var dbg = {
22
+ /** Verbose — only when debug is enabled. The hot-path normal case. */
23
+ info(tag, ...args) {
24
+ if (isDebugEnabled()) console.info(fmt(tag), ...args);
25
+ },
26
+ /** Warning — only when debug is enabled. Non-fatal oddities. */
27
+ warn(tag, ...args) {
28
+ if (isDebugEnabled()) console.warn(fmt(tag), ...args);
29
+ },
30
+ /**
31
+ * Self-diagnosis warning. **Always** emits regardless of debug flag.
32
+ * Use this only for conditions that mean something is actually wrong
33
+ * or degraded — not for routine chatter.
34
+ */
35
+ diag(tag, ...args) {
36
+ console.warn(fmt(tag), ...args);
37
+ },
38
+ /**
39
+ * Timing helper: wraps an async call and logs its elapsed time when
40
+ * debug is on. The callback runs whether debug is on or off — this is
41
+ * just for the `dbg.info` at the end.
42
+ *
43
+ * Also unconditionally fires `dbg.diag` if the elapsed time exceeds
44
+ * `slowMs`, so "the bootstrap took 8 seconds" shows up even without
45
+ * debug mode enabled.
46
+ */
47
+ async timed(tag, label, slowMs, fn) {
48
+ const start = performance.now();
49
+ try {
50
+ const result = await fn();
51
+ const elapsed = performance.now() - start;
52
+ if (isDebugEnabled()) {
53
+ console.info(fmt(tag), `${label} ${elapsed.toFixed(0)}ms`);
54
+ }
55
+ if (elapsed > slowMs) {
56
+ console.warn(
57
+ fmt(tag),
58
+ `${label} took ${elapsed.toFixed(0)}ms (>${slowMs}ms expected) \u2014 this is unusually slow; possible causes: ${hintForTag(tag)}`
59
+ );
60
+ }
61
+ return result;
62
+ } catch (err) {
63
+ const elapsed = performance.now() - start;
64
+ console.warn(
65
+ fmt(tag),
66
+ `${label} FAILED after ${elapsed.toFixed(0)}ms:`,
67
+ err
68
+ );
69
+ throw err;
70
+ }
71
+ }
72
+ };
73
+ function hintForTag(tag) {
74
+ switch (tag) {
75
+ case "probe":
76
+ return "slow network (range request), large sniff window, or libav cold-start";
77
+ case "libav-load":
78
+ return "large .wasm download, misconfigured AVBRIDGE_LIBAV_BASE, or server-side MIME type";
79
+ case "bootstrap":
80
+ return "probe+classify+strategy-init chain; enable AVBRIDGE_DEBUG for a phase breakdown";
81
+ case "cold-start":
82
+ return "decoder is producing output slower than realtime \u2014 check framesDecoded in getDiagnostics()";
83
+ default:
84
+ return "unknown stage \u2014 enable globalThis.AVBRIDGE_DEBUG for more detail";
85
+ }
86
+ }
87
+
88
+ // src/strategies/fallback/libav-loader.ts
89
+ var cache = /* @__PURE__ */ new Map();
90
+ function cacheKey(variant, threads) {
91
+ return `${variant}:${threads ? "thr" : "wasm"}`;
92
+ }
93
+ function loadLibav(variant = "webcodecs", opts = {}) {
94
+ const env = globalThis;
95
+ const wantThreads = opts.threads !== void 0 ? opts.threads : env.AVBRIDGE_LIBAV_THREADS === true;
96
+ const key = cacheKey(variant, wantThreads);
97
+ let entry = cache.get(key);
98
+ if (!entry) {
99
+ entry = loadVariant(variant, wantThreads);
100
+ cache.set(key, entry);
101
+ }
102
+ return entry;
103
+ }
104
+ async function loadVariant(variant, wantThreads) {
105
+ return dbg.timed(
106
+ "libav-load",
107
+ `load "${variant}" (threads=${wantThreads})`,
108
+ 5e3,
109
+ () => loadVariantInner(variant, wantThreads)
110
+ );
111
+ }
112
+ async function loadVariantInner(variant, wantThreads) {
113
+ const key = cacheKey(variant, wantThreads);
114
+ const base = `${libavBaseUrl()}/${variant}`;
115
+ const variantUrl = `${base}/libav-${variant}.mjs`;
116
+ dbg.info("libav-load", `fetching ${variantUrl}`);
117
+ if (typeof fetch === "function") {
118
+ try {
119
+ const head = await fetch(variantUrl, { method: "GET", headers: { Range: "bytes=0-0" } });
120
+ if (!head.ok && head.status !== 206) {
121
+ throw new Error(
122
+ `HTTP ${head.status} ${head.statusText} \u2014 check that libav files are served at ${base}/ (override via globalThis.AVBRIDGE_LIBAV_BASE)`
123
+ );
124
+ }
125
+ try {
126
+ await head.arrayBuffer();
127
+ } catch {
128
+ }
129
+ } catch (err) {
130
+ cache.delete(key);
131
+ throw chain(
132
+ `libav.js "${variant}" variant not reachable at ${variantUrl}`,
133
+ err
134
+ );
135
+ }
136
+ }
137
+ let mod;
138
+ try {
139
+ const imported = await import(
140
+ /* @vite-ignore */
141
+ variantUrl
142
+ );
143
+ if (!imported || typeof imported.LibAV !== "function") {
144
+ throw new Error(`module at ${variantUrl} did not export LibAV`);
145
+ }
146
+ mod = imported;
147
+ } catch (err) {
148
+ cache.delete(key);
149
+ const hint = variant === "avbridge" ? `The "avbridge" variant is a custom local build. Run \`./scripts/build-libav.sh\` to produce it (requires Emscripten; ~15-30 min the first time).` : `Make sure the variant files are present at ${base}/ (set globalThis.AVBRIDGE_LIBAV_BASE to override the default lookup path).`;
150
+ throw new Error(
151
+ `failed to load libav.js "${variant}" variant from ${variantUrl}. ${hint} Original error: ${err.message || String(err)}`
152
+ );
153
+ }
154
+ try {
155
+ const inst = await mod.LibAV(buildOpts(base, wantThreads));
156
+ await silenceLibavLogs(inst);
157
+ return inst;
158
+ } catch (err) {
159
+ cache.delete(key);
160
+ throw chain(`LibAV() factory failed for "${variant}" variant (threads=${wantThreads})`, err);
161
+ }
162
+ }
163
+ async function silenceLibavLogs(inst) {
164
+ try {
165
+ const setLevel = inst.av_log_set_level;
166
+ if (typeof setLevel === "function") {
167
+ const quiet = inst.AV_LOG_QUIET ?? -8;
168
+ await setLevel(quiet);
169
+ }
170
+ } catch {
171
+ }
172
+ }
173
+ function buildOpts(base, wantThreads) {
174
+ return {
175
+ base,
176
+ nothreads: !wantThreads,
177
+ yesthreads: wantThreads
178
+ };
179
+ }
180
+ function libavBaseUrl() {
181
+ const override = typeof globalThis !== "undefined" ? globalThis.AVBRIDGE_LIBAV_BASE : void 0;
182
+ if (override) return override;
183
+ try {
184
+ return new URL("../vendor/libav", import.meta.url).href;
185
+ } catch {
186
+ if (typeof location !== "undefined" && location.protocol.startsWith("http")) {
187
+ return `${location.origin}/libav`;
188
+ }
189
+ return "/libav";
190
+ }
191
+ }
192
+ function chain(message, err) {
193
+ const inner = err instanceof Error ? err.message : String(err);
194
+ console.error(`[avbridge] ${message}:`, err);
195
+ return new Error(`${message}: ${inner || "(no message \u2014 see browser console)"}`);
196
+ }
197
+
198
+ export { dbg, loadLibav };
199
+ //# sourceMappingURL=chunk-IAYKFGFG.js.map
200
+ //# sourceMappingURL=chunk-IAYKFGFG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/util/debug.ts","../src/strategies/fallback/libav-loader.ts"],"names":[],"mappings":"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","file":"chunk-IAYKFGFG.js","sourcesContent":["/**\n * Debug + self-diagnosis helper.\n *\n * avbridge has a lot of async stages (probe → classify → libav load →\n * strategy.execute → decoder pump → cold-start gate → first paint) and\n * when something's slow or wrong the symptom — \"it hangs\", \"it stutters\",\n * \"it plays audio without video\" — is usually nowhere near the actual\n * cause. This module gives us two things:\n *\n * 1. **Gated verbose logging.** `dbg.info(tag, ...)` etc. are no-ops\n * unless the consumer sets `globalThis.AVBRIDGE_DEBUG = true` (or\n * uses the matching `?avbridge_debug` URL search param at dev time).\n * When enabled, every log is prefixed with `[avbridge:<tag>]` so the\n * console is filterable.\n *\n * 2. **Unconditional self-diagnosis.** `dbg.warnIf(cond, tag, ...)`\n * always fires when a suspicious condition is detected, even with\n * debug off. These are the things we *know* mean something is\n * broken or degraded and the user would want to know about — e.g.\n * the cold-start gate timing out, the decoder running slower than\n * realtime, a libav variant taking longer to load than any network\n * should take, >20% of packets getting rejected.\n *\n * The guiding principle: **if a symptom caused more than 10 minutes of\n * human debugging once, add a targeted warning so the next instance\n * self-identifies in the console.** This module is where those\n * warnings live.\n */\n\n/** Read the debug flag fresh on every call so it's runtime-toggleable. */\nfunction isDebugEnabled(): boolean {\n if (typeof globalThis === \"undefined\") return false;\n const g = globalThis as { AVBRIDGE_DEBUG?: unknown };\n if (g.AVBRIDGE_DEBUG === true) return true;\n // Convenience: if running in a browser with a `?avbridge_debug` search\n // param, flip the flag on automatically. Useful for demos and quick\n // user reproduction without editing code.\n if (typeof location !== \"undefined\" && typeof URLSearchParams !== \"undefined\") {\n try {\n const p = new URLSearchParams(location.search);\n if (p.has(\"avbridge_debug\")) {\n g.AVBRIDGE_DEBUG = true;\n return true;\n }\n } catch { /* ignore */ }\n }\n return false;\n}\n\nfunction fmt(tag: string): string {\n return `[avbridge:${tag}]`;\n}\n\n/* eslint-disable no-console */\n\nexport const dbg = {\n /** Verbose — only when debug is enabled. The hot-path normal case. */\n info(tag: string, ...args: unknown[]): void {\n if (isDebugEnabled()) console.info(fmt(tag), ...args);\n },\n\n /** Warning — only when debug is enabled. Non-fatal oddities. */\n warn(tag: string, ...args: unknown[]): void {\n if (isDebugEnabled()) console.warn(fmt(tag), ...args);\n },\n\n /**\n * Self-diagnosis warning. **Always** emits regardless of debug flag.\n * Use this only for conditions that mean something is actually wrong\n * or degraded — not for routine chatter.\n */\n diag(tag: string, ...args: unknown[]): void {\n console.warn(fmt(tag), ...args);\n },\n\n /**\n * Timing helper: wraps an async call and logs its elapsed time when\n * debug is on. The callback runs whether debug is on or off — this is\n * just for the `dbg.info` at the end.\n *\n * Also unconditionally fires `dbg.diag` if the elapsed time exceeds\n * `slowMs`, so \"the bootstrap took 8 seconds\" shows up even without\n * debug mode enabled.\n */\n async timed<T>(\n tag: string,\n label: string,\n slowMs: number,\n fn: () => Promise<T>,\n ): Promise<T> {\n const start = performance.now();\n try {\n const result = await fn();\n const elapsed = performance.now() - start;\n if (isDebugEnabled()) {\n console.info(fmt(tag), `${label} ${elapsed.toFixed(0)}ms`);\n }\n if (elapsed > slowMs) {\n console.warn(\n fmt(tag),\n `${label} took ${elapsed.toFixed(0)}ms (>${slowMs}ms expected) — ` +\n `this is unusually slow; possible causes: ${hintForTag(tag)}`,\n );\n }\n return result;\n } catch (err) {\n const elapsed = performance.now() - start;\n console.warn(\n fmt(tag),\n `${label} FAILED after ${elapsed.toFixed(0)}ms:`,\n err,\n );\n throw err;\n }\n },\n};\n\nfunction hintForTag(tag: string): string {\n switch (tag) {\n case \"probe\":\n return \"slow network (range request), large sniff window, or libav cold-start\";\n case \"libav-load\":\n return \"large .wasm download, misconfigured AVBRIDGE_LIBAV_BASE, or server-side MIME type\";\n case \"bootstrap\":\n return \"probe+classify+strategy-init chain; enable AVBRIDGE_DEBUG for a phase breakdown\";\n case \"cold-start\":\n return \"decoder is producing output slower than realtime — check framesDecoded in getDiagnostics()\";\n default:\n return \"unknown stage — enable globalThis.AVBRIDGE_DEBUG for more detail\";\n }\n}\n","/**\n * Lazy libav.js loader supporting multiple variants.\n *\n * avbridge recognises three libav variants:\n *\n * - **webcodecs** — npm `@libav.js/variant-webcodecs`, ~5 MB. Modern formats\n * only (mp4/mkv/webm/ogg/wav/...) — designed to bridge to WebCodecs.\n *\n * - **default** — npm `@libav.js/variant-default`, ~12 MB. Audio-only build\n * (Opus, FLAC, WAV) despite the name. Useful for audio fallback.\n *\n * - **avbridge** — a custom build produced by `scripts/build-libav.sh` and\n * landing in `vendor/libav/`. Includes the AVI/ASF/FLV/MKV demuxers plus\n * the legacy decoders (WMV3, MPEG-4 Part 2, MS-MPEG4 v1/2/3, VC-1, MPEG-1/2,\n * AC-3/E-AC-3, WMAv1/v2/Pro). This is the only variant that can read AVI;\n * the npm variants are intentionally minimal and ship none of the legacy\n * demuxers.\n *\n * Variant resolution always goes through a runtime URL + `/* @vite-ignore *\\/`\n * dynamic import. Static imports trigger Vite's optimized-deps pipeline,\n * which rewrites `import.meta.url` away from the real `dist/` directory and\n * breaks libav's sibling-binary loading.\n */\n\nimport { dbg } from \"../../util/debug.js\";\n\nexport type LibavVariant = \"webcodecs\" | \"default\" | \"avbridge\";\n\nexport interface LoadLibavOptions {\n /**\n * Force threading on/off for this load. If unspecified, defaults to\n * \"true if `crossOriginIsolated`, otherwise false\". Some libav.js code\n * paths (notably the cross-thread reader-device protocol used during\n * `avformat_find_stream_info` for AVI) are unreliable in threaded mode,\n * so probing forces this to `false` while decode keeps it default.\n */\n threads?: boolean;\n}\n\n// Cache key includes both variant and threading mode so probe and decode\n// can run different libav instances of the same variant.\nconst cache: Map<string, Promise<LibavInstance>> = new Map();\n\nfunction cacheKey(variant: LibavVariant, threads: boolean): string {\n return `${variant}:${threads ? \"thr\" : \"wasm\"}`;\n}\n\n/**\n * Load (and cache) a libav.js variant. Pass `\"webcodecs\"` for the small\n * default; pass `\"default\"` for the audio fallback; pass `\"avbridge\"` for the\n * custom build that supports AVI/WMV/legacy codecs.\n */\nexport function loadLibav(\n variant: LibavVariant = \"webcodecs\",\n opts: LoadLibavOptions = {},\n): Promise<LibavInstance> {\n // Threading is OFF by default. The threaded libav.js variant is too\n // fragile in practice for our usage:\n // - Probe (`avformat_find_stream_info` for AVI) throws an `undefined`\n // exception out of `ff_init_demuxer_file`, apparently due to the\n // cross-thread reader-device protocol racing with the main thread.\n // - Decode hits a `TypeError: Cannot read properties of undefined\n // (reading 'apply')` inside libav.js's own worker message handler\n // within seconds of starting — a bug in libav.js's threaded message\n // dispatch that we can't fix from outside.\n //\n // Performance work for the fallback strategy needs to come from elsewhere\n // (WASM SIMD, OffscreenCanvas, larger decode batches) instead of libav's\n // pthreads. Threading can still be force-enabled with\n // `globalThis.AVBRIDGE_LIBAV_THREADS = true` for testing if libav.js fixes\n // those bugs in a future release.\n const env = globalThis as { AVBRIDGE_LIBAV_THREADS?: boolean };\n const wantThreads =\n opts.threads !== undefined\n ? opts.threads\n : env.AVBRIDGE_LIBAV_THREADS === true;\n\n const key = cacheKey(variant, wantThreads);\n let entry = cache.get(key);\n if (!entry) {\n entry = loadVariant(variant, wantThreads);\n cache.set(key, entry);\n }\n return entry;\n}\n\nasync function loadVariant(\n variant: LibavVariant,\n wantThreads: boolean,\n): Promise<LibavInstance> {\n return dbg.timed(\"libav-load\", `load \"${variant}\" (threads=${wantThreads})`, 5000, () =>\n loadVariantInner(variant, wantThreads),\n );\n}\n\nasync function loadVariantInner(\n variant: LibavVariant,\n wantThreads: boolean,\n): Promise<LibavInstance> {\n const key = cacheKey(variant, wantThreads);\n const base = `${libavBaseUrl()}/${variant}`;\n // The custom variant is named `libav-avbridge.mjs`; the npm variants follow\n // the same convention (`libav-webcodecs.mjs`, `libav-default.mjs`).\n const variantUrl = `${base}/libav-${variant}.mjs`;\n dbg.info(\"libav-load\", `fetching ${variantUrl}`);\n\n // Preflight HEAD-ish check: issue a bytes=0-0 range request so a missing\n // file fails fast with a clear error instead of hanging deep inside the\n // dynamic import or inside libav's own WASM instantiation. Surfaces the\n // most common mistake (\"libav base path is wrong\") in <100 ms instead of\n // an indeterminate stall.\n if (typeof fetch === \"function\") {\n try {\n const head = await fetch(variantUrl, { method: \"GET\", headers: { Range: \"bytes=0-0\" } });\n if (!head.ok && head.status !== 206) {\n throw new Error(\n `HTTP ${head.status} ${head.statusText} — check that libav files are served ` +\n `at ${base}/ (override via globalThis.AVBRIDGE_LIBAV_BASE)`,\n );\n }\n // Drain the tiny response so the connection can be reused.\n try { await head.arrayBuffer(); } catch { /* ignore */ }\n } catch (err) {\n cache.delete(key);\n throw chain(\n `libav.js \"${variant}\" variant not reachable at ${variantUrl}`,\n err,\n );\n }\n }\n\n let mod: LoadedVariant;\n try {\n // @ts-ignore runtime URL\n const imported: unknown = await import(/* @vite-ignore */ variantUrl);\n if (!imported || typeof (imported as { LibAV?: unknown }).LibAV !== \"function\") {\n throw new Error(`module at ${variantUrl} did not export LibAV`);\n }\n mod = imported as LoadedVariant;\n } catch (err) {\n cache.delete(key);\n const hint =\n variant === \"avbridge\"\n ? `The \"avbridge\" variant is a custom local build. Run \\`./scripts/build-libav.sh\\` ` +\n `to produce it (requires Emscripten; ~15-30 min the first time).`\n : `Make sure the variant files are present at ${base}/ (set ` +\n `globalThis.AVBRIDGE_LIBAV_BASE to override the default lookup path).`;\n throw new Error(\n `failed to load libav.js \"${variant}\" variant from ${variantUrl}. ${hint} ` +\n `Original error: ${(err as Error).message || String(err)}`,\n );\n }\n\n try {\n const inst = (await mod.LibAV(buildOpts(base, wantThreads))) as LibavInstance;\n await silenceLibavLogs(inst);\n return inst;\n } catch (err) {\n cache.delete(key);\n throw chain(`LibAV() factory failed for \"${variant}\" variant (threads=${wantThreads})`, err);\n }\n}\n\n/**\n * Lower libav's internal log level so the console doesn't get flooded with\n * `[mp3 @ ...] Header missing` and `Video uses a non-standard and wasteful\n * way to store B-frames` warnings on every legacy file. We still get any\n * actual JS-level errors via the normal Error path; this only affects\n * libav's own ffmpeg log channel.\n *\n * AV_LOG_QUIET = -8 (no output at all). If you want to keep fatal errors,\n * use AV_LOG_FATAL = 8 instead.\n */\nasync function silenceLibavLogs(inst: LibavInstance): Promise<void> {\n try {\n const setLevel = (inst as { av_log_set_level?: (n: number) => Promise<void> })\n .av_log_set_level;\n if (typeof setLevel === \"function\") {\n const quiet = (inst as { AV_LOG_QUIET?: number }).AV_LOG_QUIET ?? -8;\n await setLevel(quiet);\n }\n } catch {\n /* not fatal — verbose logs are noise, not an error */\n }\n}\n\nfunction buildOpts(base: string, wantThreads: boolean): Record<string, unknown> {\n // The wantThreads decision is made by `loadLibav()` so callers (probe,\n // decoder) can override per-load. Decode wants pthreads for speed; probe\n // forces them off because libav.js's cross-thread reader-device protocol\n // is unreliable mid-`avformat_find_stream_info` for some AVI files.\n return {\n base,\n nothreads: !wantThreads,\n yesthreads: wantThreads,\n };\n}\n\nfunction libavBaseUrl(): string {\n // Consumer override — the documented \"LGPL replaceability\" hook.\n // Setting `globalThis.AVBRIDGE_LIBAV_BASE = \"/my/path\"` lets anyone swap\n // in a different libav build (custom fragments, security patches, etc.)\n // without rebuilding avbridge.\n const override =\n typeof globalThis !== \"undefined\"\n ? (globalThis as { AVBRIDGE_LIBAV_BASE?: string }).AVBRIDGE_LIBAV_BASE\n : undefined;\n if (override) return override;\n\n // Default: resolve relative to this module's URL. When avbridge is installed\n // under `node_modules/avbridge/`, this module lives at `dist/chunk-*.js` (or\n // `dist/element-browser.js` for the browser entry) and `../vendor/libav`\n // resolves to `node_modules/avbridge/vendor/libav`, where the build step\n // vendored every variant's binaries. That's the zero-config path.\n //\n // `import.meta.url` throws in some synthetic environments (CJS tests, some\n // SSR evaluators). If it fails, fall back to the legacy `/libav` path so\n // consumers who relied on the pre-2.1 behavior still work.\n try {\n return new URL(\"../vendor/libav\", import.meta.url).href;\n } catch {\n if (typeof location !== \"undefined\" && location.protocol.startsWith(\"http\")) {\n return `${location.origin}/libav`;\n }\n return \"/libav\";\n }\n}\n\nfunction chain(message: string, err: unknown): Error {\n const inner = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(`[avbridge] ${message}:`, err);\n return new Error(`${message}: ${inner || \"(no message — see browser console)\"}`);\n}\n\ninterface LoadedVariant {\n LibAV: (opts?: Record<string, unknown>) => Promise<Record<string, unknown>>;\n}\n\n/** Loose structural type — the AVI probe and the fallback decoder add fields. */\nexport type LibavInstance = Record<string, unknown> & {\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n};\n"]}