avbridge 2.3.0 → 2.6.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 (111) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/dist/{chunk-6UUT4BEA.cjs → chunk-2IJ66NTD.cjs} +13 -20
  3. package/dist/chunk-2IJ66NTD.cjs.map +1 -0
  4. package/dist/{chunk-XKPSTC34.cjs → chunk-2XW2O3YI.cjs} +5 -20
  5. package/dist/chunk-2XW2O3YI.cjs.map +1 -0
  6. package/dist/chunk-5KVLE6YI.js +167 -0
  7. package/dist/chunk-5KVLE6YI.js.map +1 -0
  8. package/dist/{chunk-7RGG6ME7.cjs → chunk-6SOFJV44.cjs} +422 -688
  9. package/dist/chunk-6SOFJV44.cjs.map +1 -0
  10. package/dist/{chunk-2PGRFCWB.js → chunk-CPJLFFCC.js} +8 -18
  11. package/dist/chunk-CPJLFFCC.js.map +1 -0
  12. package/dist/chunk-CPZ7PXAM.cjs +240 -0
  13. package/dist/chunk-CPZ7PXAM.cjs.map +1 -0
  14. package/dist/{chunk-QQXBPW72.js → chunk-E76AMWI4.js} +4 -18
  15. package/dist/chunk-E76AMWI4.js.map +1 -0
  16. package/dist/chunk-LUFA47FP.js +19 -0
  17. package/dist/chunk-LUFA47FP.js.map +1 -0
  18. package/dist/{chunk-NV7ILLWH.js → chunk-OGYHFY6K.js} +404 -665
  19. package/dist/chunk-OGYHFY6K.js.map +1 -0
  20. package/dist/chunk-Q2VUO52Z.cjs +374 -0
  21. package/dist/chunk-Q2VUO52Z.cjs.map +1 -0
  22. package/dist/chunk-QDJLQR53.cjs +22 -0
  23. package/dist/chunk-QDJLQR53.cjs.map +1 -0
  24. package/dist/chunk-S4WAZC2T.cjs +173 -0
  25. package/dist/chunk-S4WAZC2T.cjs.map +1 -0
  26. package/dist/chunk-SMH6IOP2.js +368 -0
  27. package/dist/chunk-SMH6IOP2.js.map +1 -0
  28. package/dist/chunk-SR3MPV4D.js +237 -0
  29. package/dist/chunk-SR3MPV4D.js.map +1 -0
  30. package/dist/chunk-X2K3GIWE.js +235 -0
  31. package/dist/chunk-X2K3GIWE.js.map +1 -0
  32. package/dist/chunk-ZCUXHW55.cjs +242 -0
  33. package/dist/chunk-ZCUXHW55.cjs.map +1 -0
  34. package/dist/element-browser.js +883 -492
  35. package/dist/element-browser.js.map +1 -1
  36. package/dist/element.cjs +88 -6
  37. package/dist/element.cjs.map +1 -1
  38. package/dist/element.d.cts +51 -1
  39. package/dist/element.d.ts +51 -1
  40. package/dist/element.js +87 -5
  41. package/dist/element.js.map +1 -1
  42. package/dist/index.cjs +523 -393
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +2 -2
  45. package/dist/index.d.ts +2 -2
  46. package/dist/index.js +494 -366
  47. package/dist/index.js.map +1 -1
  48. package/dist/libav-demux-H2GS46GH.cjs +27 -0
  49. package/dist/libav-demux-H2GS46GH.cjs.map +1 -0
  50. package/dist/libav-demux-OWZ4T2YW.js +6 -0
  51. package/dist/libav-demux-OWZ4T2YW.js.map +1 -0
  52. package/dist/{libav-import-GST2AMPL.cjs → libav-import-2ZVKV2E7.cjs} +2 -2
  53. package/dist/{libav-import-GST2AMPL.cjs.map → libav-import-2ZVKV2E7.cjs.map} +1 -1
  54. package/dist/{libav-import-2JURFHEW.js → libav-import-6MGLCXVQ.js} +2 -2
  55. package/dist/{libav-import-2JURFHEW.js.map → libav-import-6MGLCXVQ.js.map} +1 -1
  56. package/dist/{player-B6WB74RD.d.ts → player-DGXeCNfD.d.cts} +41 -1
  57. package/dist/{player-B6WB74RD.d.cts → player-DGXeCNfD.d.ts} +41 -1
  58. package/dist/player.cjs +731 -472
  59. package/dist/player.cjs.map +1 -1
  60. package/dist/player.d.cts +229 -120
  61. package/dist/player.d.ts +229 -120
  62. package/dist/player.js +710 -451
  63. package/dist/player.js.map +1 -1
  64. package/dist/remux-OBSMIENG.cjs +35 -0
  65. package/dist/remux-OBSMIENG.cjs.map +1 -0
  66. package/dist/remux-WBYIZBBX.js +10 -0
  67. package/dist/remux-WBYIZBBX.js.map +1 -0
  68. package/dist/source-4TZ6KMNV.js +4 -0
  69. package/dist/{source-F656KYYV.js.map → source-4TZ6KMNV.js.map} +1 -1
  70. package/dist/source-7YLO6E7X.cjs +29 -0
  71. package/dist/{source-73CAH6HW.cjs.map → source-7YLO6E7X.cjs.map} +1 -1
  72. package/dist/source-MTX5ELUZ.js +4 -0
  73. package/dist/{source-QJR3OHTW.js.map → source-MTX5ELUZ.js.map} +1 -1
  74. package/dist/source-VFLXLOCN.cjs +29 -0
  75. package/dist/{source-VB74JQ7Z.cjs.map → source-VFLXLOCN.cjs.map} +1 -1
  76. package/dist/subtitles-4T74JRGT.js +4 -0
  77. package/dist/subtitles-4T74JRGT.js.map +1 -0
  78. package/dist/subtitles-QUH4LPI4.cjs +29 -0
  79. package/dist/subtitles-QUH4LPI4.cjs.map +1 -0
  80. package/package.json +1 -1
  81. package/src/convert/remux.ts +1 -35
  82. package/src/convert/transcode-libav.ts +691 -0
  83. package/src/convert/transcode.ts +12 -4
  84. package/src/element/avbridge-player.ts +100 -0
  85. package/src/element/avbridge-video.ts +140 -3
  86. package/src/element/player-styles.ts +12 -0
  87. package/src/errors.ts +6 -0
  88. package/src/player.ts +15 -16
  89. package/src/strategies/fallback/decoder.ts +96 -173
  90. package/src/strategies/fallback/index.ts +46 -2
  91. package/src/strategies/fallback/libav-import.ts +9 -1
  92. package/src/strategies/fallback/video-renderer.ts +107 -0
  93. package/src/strategies/hybrid/decoder.ts +88 -180
  94. package/src/strategies/hybrid/index.ts +35 -2
  95. package/src/strategies/native.ts +6 -3
  96. package/src/strategies/remux/index.ts +14 -2
  97. package/src/strategies/remux/pipeline.ts +72 -12
  98. package/src/subtitles/render.ts +8 -0
  99. package/src/types.ts +32 -0
  100. package/src/util/libav-demux.ts +405 -0
  101. package/src/util/time-ranges.ts +40 -0
  102. package/dist/chunk-2PGRFCWB.js.map +0 -1
  103. package/dist/chunk-6UUT4BEA.cjs.map +0 -1
  104. package/dist/chunk-7RGG6ME7.cjs.map +0 -1
  105. package/dist/chunk-NV7ILLWH.js.map +0 -1
  106. package/dist/chunk-QQXBPW72.js.map +0 -1
  107. package/dist/chunk-XKPSTC34.cjs.map +0 -1
  108. package/dist/source-73CAH6HW.cjs +0 -28
  109. package/dist/source-F656KYYV.js +0 -3
  110. package/dist/source-QJR3OHTW.js +0 -3
  111. package/dist/source-VB74JQ7Z.cjs +0 -28
@@ -0,0 +1,242 @@
1
+ 'use strict';
2
+
3
+ var chunk2IJ66NTD_cjs = require('./chunk-2IJ66NTD.cjs');
4
+
5
+ // src/probe/mediabunny.ts
6
+ async function probeWithMediabunny(source, sniffedContainer) {
7
+ const mb = await import('mediabunny');
8
+ const input = new mb.Input({
9
+ source: await buildMediabunnySource(mb, source),
10
+ formats: mb.ALL_FORMATS
11
+ });
12
+ const allTracks = await input.getTracks();
13
+ const duration = await safeNumber(() => input.computeDuration());
14
+ const videoTracks = [];
15
+ const audioTracks = [];
16
+ for (const track of allTracks) {
17
+ if (track.isVideoTrack()) {
18
+ const codecParam = await safe(() => track.getCodecParameterString());
19
+ videoTracks.push({
20
+ id: track.id,
21
+ codec: mediabunnyVideoToAvbridge(track.codec),
22
+ width: track.displayWidth ?? track.codedWidth ?? 0,
23
+ height: track.displayHeight ?? track.codedHeight ?? 0,
24
+ codecString: codecParam ?? void 0
25
+ });
26
+ } else if (track.isAudioTrack()) {
27
+ const codecParam = await safe(() => track.getCodecParameterString());
28
+ audioTracks.push({
29
+ id: track.id,
30
+ codec: mediabunnyAudioToAvbridge(track.codec),
31
+ channels: track.numberOfChannels ?? 0,
32
+ sampleRate: track.sampleRate ?? 0,
33
+ language: track.languageCode,
34
+ codecString: codecParam ?? void 0
35
+ });
36
+ }
37
+ }
38
+ const format = await safe(() => input.getFormat());
39
+ const container = resolveContainer(format?.name, sniffedContainer);
40
+ return {
41
+ source: source.original,
42
+ name: source.name,
43
+ byteLength: source.byteLength,
44
+ container,
45
+ videoTracks,
46
+ audioTracks,
47
+ subtitleTracks: [],
48
+ probedBy: "mediabunny",
49
+ duration
50
+ };
51
+ }
52
+ async function buildMediabunnySource(mb, source) {
53
+ if (source.kind === "url") {
54
+ return new mb.UrlSource(source.url);
55
+ }
56
+ return new mb.BlobSource(source.blob);
57
+ }
58
+ async function buildMediabunnySourceFromInput(mb, source) {
59
+ if (typeof source === "string") return new mb.UrlSource(source);
60
+ if (source instanceof URL) return new mb.UrlSource(source.toString());
61
+ if (source instanceof Blob) return new mb.BlobSource(source);
62
+ if (source instanceof ArrayBuffer) return new mb.BlobSource(new Blob([source]));
63
+ if (source instanceof Uint8Array) return new mb.BlobSource(new Blob([source]));
64
+ throw new TypeError("unsupported source type for mediabunny");
65
+ }
66
+ function resolveContainer(formatName, sniffed) {
67
+ const name = (formatName ?? "").toLowerCase();
68
+ if (name.includes("matroska") || name.includes("mkv")) return "mkv";
69
+ if (name.includes("webm")) return "webm";
70
+ if (name.includes("mp4") || name.includes("isom")) return "mp4";
71
+ if (name.includes("mov") || name.includes("quicktime")) return "mov";
72
+ if (name.includes("ogg")) return "ogg";
73
+ if (name.includes("wav")) return "wav";
74
+ if (name.includes("flac")) return "flac";
75
+ if (name.includes("mp3")) return "mp3";
76
+ if (name.includes("adts") || name.includes("aac")) return "adts";
77
+ if (name.includes("mpegts") || name.includes("mpeg-ts") || name.includes("transport")) return "mpegts";
78
+ return sniffed;
79
+ }
80
+ function mediabunnyVideoToAvbridge(c) {
81
+ switch (c) {
82
+ case "avc":
83
+ return "h264";
84
+ case "hevc":
85
+ return "h265";
86
+ case "vp8":
87
+ return "vp8";
88
+ case "vp9":
89
+ return "vp9";
90
+ case "av1":
91
+ return "av1";
92
+ default:
93
+ return c ? c : "unknown";
94
+ }
95
+ }
96
+ function avbridgeVideoToMediabunny(c) {
97
+ switch (c) {
98
+ case "h264":
99
+ return "avc";
100
+ case "h265":
101
+ return "hevc";
102
+ case "vp8":
103
+ return "vp8";
104
+ case "vp9":
105
+ return "vp9";
106
+ case "av1":
107
+ return "av1";
108
+ default:
109
+ return null;
110
+ }
111
+ }
112
+ function mediabunnyAudioToAvbridge(c) {
113
+ switch (c) {
114
+ case "aac":
115
+ return "aac";
116
+ case "mp3":
117
+ return "mp3";
118
+ case "opus":
119
+ return "opus";
120
+ case "vorbis":
121
+ return "vorbis";
122
+ case "flac":
123
+ return "flac";
124
+ case "ac3":
125
+ return "ac3";
126
+ case "eac3":
127
+ return "eac3";
128
+ default:
129
+ return c ? c : "unknown";
130
+ }
131
+ }
132
+ function avbridgeAudioToMediabunny(c) {
133
+ switch (c) {
134
+ case "aac":
135
+ return "aac";
136
+ case "mp3":
137
+ return "mp3";
138
+ case "opus":
139
+ return "opus";
140
+ case "vorbis":
141
+ return "vorbis";
142
+ case "flac":
143
+ return "flac";
144
+ case "ac3":
145
+ return "ac3";
146
+ case "eac3":
147
+ return "eac3";
148
+ default:
149
+ return null;
150
+ }
151
+ }
152
+ async function safeNumber(fn) {
153
+ try {
154
+ const v = await fn();
155
+ return typeof v === "number" && Number.isFinite(v) ? v : void 0;
156
+ } catch {
157
+ return void 0;
158
+ }
159
+ }
160
+ async function safe(fn) {
161
+ try {
162
+ return await fn();
163
+ } catch {
164
+ return void 0;
165
+ }
166
+ }
167
+
168
+ // src/probe/index.ts
169
+ var MEDIABUNNY_CONTAINERS = /* @__PURE__ */ new Set([
170
+ "mp4",
171
+ "mov",
172
+ "mkv",
173
+ "webm",
174
+ "ogg",
175
+ "wav",
176
+ "mp3",
177
+ "flac",
178
+ "adts",
179
+ "mpegts"
180
+ ]);
181
+ async function probe(source, transport) {
182
+ const normalized = await chunk2IJ66NTD_cjs.normalizeSource(source, transport);
183
+ const sniffed = await chunk2IJ66NTD_cjs.sniffNormalizedSource(normalized);
184
+ if (MEDIABUNNY_CONTAINERS.has(sniffed)) {
185
+ try {
186
+ const result = await probeWithMediabunny(normalized, sniffed);
187
+ const hasUnknownCodec = result.videoTracks.some((t) => t.codec === "unknown") || result.audioTracks.some((t) => t.codec === "unknown");
188
+ if (hasUnknownCodec) {
189
+ try {
190
+ const { probeWithLibav } = await import('./avi-W6L3BTWU.cjs');
191
+ return await probeWithLibav(normalized, sniffed);
192
+ } catch {
193
+ return result;
194
+ }
195
+ }
196
+ return result;
197
+ } catch (mediabunnyErr) {
198
+ console.warn(
199
+ `[avbridge] mediabunny rejected ${sniffed} file, falling back to libav:`,
200
+ mediabunnyErr.message
201
+ );
202
+ try {
203
+ const { probeWithLibav } = await import('./avi-W6L3BTWU.cjs');
204
+ return await probeWithLibav(normalized, sniffed);
205
+ } catch (libavErr) {
206
+ const mbMsg = mediabunnyErr.message || String(mediabunnyErr);
207
+ const lvMsg = libavErr instanceof Error ? libavErr.message : String(libavErr);
208
+ throw new chunk2IJ66NTD_cjs.AvbridgeError(
209
+ chunk2IJ66NTD_cjs.ERR_PROBE_FAILED,
210
+ `Failed to probe ${sniffed.toUpperCase()} file. mediabunny: ${mbMsg}. libav: ${lvMsg}.`,
211
+ "The file may be corrupt, truncated, or in an unsupported format. Enable AVBRIDGE_DEBUG for detailed logs."
212
+ );
213
+ }
214
+ }
215
+ }
216
+ try {
217
+ const { probeWithLibav } = await import('./avi-W6L3BTWU.cjs');
218
+ return await probeWithLibav(normalized, sniffed);
219
+ } catch (err) {
220
+ const inner = err instanceof Error ? err.message : String(err);
221
+ console.error("[avbridge] libav probe failed for", sniffed, "file:", err);
222
+ if (sniffed === "unknown") {
223
+ throw new chunk2IJ66NTD_cjs.AvbridgeError(
224
+ chunk2IJ66NTD_cjs.ERR_PROBE_UNKNOWN_CONTAINER,
225
+ `Unable to probe source: container format could not be identified. libav fallback: ${inner || "(no details)"}`,
226
+ "The file may be corrupt or in a format avbridge doesn't recognize. Check the file plays in VLC or ffprobe."
227
+ );
228
+ }
229
+ throw new chunk2IJ66NTD_cjs.AvbridgeError(
230
+ chunk2IJ66NTD_cjs.ERR_LIBAV_NOT_REACHABLE,
231
+ `${sniffed.toUpperCase()} files require libav.js, which failed to load: ${inner || "(no details)"}`,
232
+ "Install @libav.js/variant-webcodecs, or check that AVBRIDGE_LIBAV_BASE points to the correct path."
233
+ );
234
+ }
235
+ }
236
+
237
+ exports.avbridgeAudioToMediabunny = avbridgeAudioToMediabunny;
238
+ exports.avbridgeVideoToMediabunny = avbridgeVideoToMediabunny;
239
+ exports.buildMediabunnySourceFromInput = buildMediabunnySourceFromInput;
240
+ exports.probe = probe;
241
+ //# sourceMappingURL=chunk-ZCUXHW55.cjs.map
242
+ //# sourceMappingURL=chunk-ZCUXHW55.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/probe/mediabunny.ts","../src/probe/index.ts"],"names":["normalizeSource","sniffNormalizedSource","AvbridgeError","ERR_PROBE_FAILED","ERR_PROBE_UNKNOWN_CONTAINER","ERR_LIBAV_NOT_REACHABLE"],"mappings":"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","file":"chunk-ZCUXHW55.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\";\n\n/**\n * Probe via mediabunny. Built against the real (typed) API exported by\n * `mediabunny.d.ts`:\n *\n * - `Input.getTracks()` returns `InputTrack[]`; each track has `isVideoTrack()`\n * / `isAudioTrack()` type guards plus a `codec` getter that returns one of\n * the enum strings (`\"avc\"|\"hevc\"|\"vp9\"|\"vp8\"|\"av1\"` for video,\n * `\"aac\"|\"opus\"|...` for audio).\n * - For decoder metadata + codec parameter strings we call\n * `getDecoderConfig()` and `getCodecParameterString()` on the typed track.\n *\n * The bridging back to avbridge's own codec naming (`h264` instead of mediabunny's\n * `avc`) happens here so the rest of the codebase keeps a single vocabulary.\n */\nexport async function probeWithMediabunny(\n source: NormalizedSource,\n sniffedContainer: ContainerKind,\n): Promise<MediaContext> {\n const mb = await import(\"mediabunny\");\n const input = new mb.Input({\n source: await buildMediabunnySource(mb, source),\n formats: mb.ALL_FORMATS,\n });\n\n const allTracks = await input.getTracks();\n const duration = await safeNumber(() => input.computeDuration());\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const track of allTracks) {\n if (track.isVideoTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n videoTracks.push({\n id: track.id,\n codec: mediabunnyVideoToAvbridge(track.codec),\n width: track.displayWidth ?? track.codedWidth ?? 0,\n height: track.displayHeight ?? track.codedHeight ?? 0,\n codecString: codecParam ?? undefined,\n });\n } else if (track.isAudioTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n audioTracks.push({\n id: track.id,\n codec: mediabunnyAudioToAvbridge(track.codec),\n channels: track.numberOfChannels ?? 0,\n sampleRate: track.sampleRate ?? 0,\n language: track.languageCode,\n codecString: codecParam ?? undefined,\n });\n }\n }\n\n const format = await safe(() => input.getFormat());\n const container = resolveContainer(format?.name, sniffedContainer);\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"mediabunny\",\n duration,\n };\n}\n\n/**\n * Build the right mediabunny `Source` for a normalized input. URL sources\n * use `UrlSource` (Range requests, prefetch, parallelism) so we don't\n * buffer the whole file into memory. Blob/File sources use `BlobSource`.\n *\n * Exported so the remux strategy can use the same routing logic.\n */\nexport async function buildMediabunnySource(\n mb: typeof import(\"mediabunny\"),\n source: NormalizedSource,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (source.kind === \"url\") {\n return new mb.UrlSource(source.url);\n }\n return new mb.BlobSource(source.blob);\n}\n\n/**\n * Build a mediabunny `Source` directly from a raw `MediaInput`, bypassing\n * `normalizeSource`. Used by strategies that already have the original\n * input on hand (via `MediaContext.source`) and don't need a sniff window.\n *\n * This is the routing point that decides \"stream from URL via Range\n * requests\" vs \"wrap in-memory bytes as BlobSource\". Always prefer\n * `UrlSource` for URL inputs so we don't accidentally buffer the file.\n */\nexport async function buildMediabunnySourceFromInput(\n mb: typeof import(\"mediabunny\"),\n source: import(\"../types.js\").MediaInput,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (typeof source === \"string\") return new mb.UrlSource(source);\n if (source instanceof URL) return new mb.UrlSource(source.toString());\n if (source instanceof Blob) return new mb.BlobSource(source);\n if (source instanceof ArrayBuffer) return new mb.BlobSource(new Blob([source]));\n if (source instanceof Uint8Array) return new mb.BlobSource(new Blob([source as BlobPart]));\n throw new TypeError(\"unsupported source type for mediabunny\");\n}\n\nfunction resolveContainer(formatName: string | undefined, sniffed: ContainerKind): ContainerKind {\n const name = (formatName ?? \"\").toLowerCase();\n if (name.includes(\"matroska\") || name.includes(\"mkv\")) return \"mkv\";\n if (name.includes(\"webm\")) return \"webm\";\n if (name.includes(\"mp4\") || name.includes(\"isom\")) return \"mp4\";\n if (name.includes(\"mov\") || name.includes(\"quicktime\")) return \"mov\";\n if (name.includes(\"ogg\")) return \"ogg\";\n if (name.includes(\"wav\")) return \"wav\";\n if (name.includes(\"flac\")) return \"flac\";\n if (name.includes(\"mp3\")) return \"mp3\";\n if (name.includes(\"adts\") || name.includes(\"aac\")) return \"adts\";\n if (name.includes(\"mpegts\") || name.includes(\"mpeg-ts\") || name.includes(\"transport\")) return \"mpegts\";\n return sniffed;\n}\n\n/** Mediabunny video codec → avbridge video codec. */\nexport function mediabunnyVideoToAvbridge(c: string | null | undefined): VideoCodec {\n switch (c) {\n case \"avc\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default:\n // Preserve the original codec string when mediabunny gave us something\n // we don't recognize. The classifier checks `NATIVE_VIDEO_CODECS.has()`\n // and routes anything outside that set through the fallback chain — so\n // returning the unknown name (instead of silently relabeling it as\n // \"h264\") gets correct routing AND honest diagnostics.\n return c ? (c as VideoCodec) : \"unknown\";\n }\n}\n\n/** avbridge video codec → mediabunny video codec (for output sources). */\nexport function avbridgeVideoToMediabunny(c: VideoCodec): \"avc\" | \"hevc\" | \"vp9\" | \"vp8\" | \"av1\" | null {\n switch (c) {\n case \"h264\": return \"avc\";\n case \"h265\": return \"hevc\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default: return null;\n }\n}\n\nexport function mediabunnyAudioToAvbridge(c: string | null | undefined): AudioCodec {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": 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 default: return c ? (c as AudioCodec) : \"unknown\";\n }\n}\n\nexport function avbridgeAudioToMediabunny(c: AudioCodec): string | null {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": 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 default: return null;\n }\n}\n\nasync function safeNumber(fn: () => Promise<number> | number): Promise<number | undefined> {\n try {\n const v = await fn();\n return typeof v === \"number\" && Number.isFinite(v) ? v : undefined;\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","import type { ContainerKind, MediaContext, MediaInput, TransportConfig } from \"../types.js\";\nimport { normalizeSource, sniffNormalizedSource } from \"../util/source.js\";\nimport { probeWithMediabunny } from \"./mediabunny.js\";\nimport { AvbridgeError, ERR_PROBE_FAILED, ERR_PROBE_UNKNOWN_CONTAINER, ERR_LIBAV_NOT_REACHABLE } from \"../errors.js\";\n\n/** Containers mediabunny can demux. Sniff results outside this set go straight to libav. */\nconst MEDIABUNNY_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"mkv\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n \"mpegts\",\n]);\n\n/**\n * Probe a source and produce a {@link MediaContext}.\n *\n * Routing:\n * 1. Sniff the magic header. Cheap, deterministic, ignores file extensions.\n * 2. If the container is one mediabunny supports → try mediabunny first\n * (fast path — it's a single pass of WASM-free JS parsing). If mediabunny\n * throws (e.g. an assertion on an unsupported sample entry like `mp4v`\n * for MPEG-4 Part 2 in ISOBMFF, or an exotic MKV codec), fall through to\n * libav.js which handles the long tail of codecs mediabunny doesn't.\n * The combined-error case surfaces *both* failures so the user sees\n * which path each step took.\n * 3. If sniffing identifies AVI/ASF/FLV (or `unknown`) → libav.js directly.\n * mediabunny can't read those containers at all, so there's no fast path\n * to try.\n */\nexport async function probe(\n source: MediaInput,\n transport?: TransportConfig,\n): Promise<MediaContext> {\n const normalized = await normalizeSource(source, transport);\n const sniffed = await sniffNormalizedSource(normalized);\n\n if (MEDIABUNNY_CONTAINERS.has(sniffed)) {\n try {\n const result = await probeWithMediabunny(normalized, sniffed);\n // If mediabunny returned unknown codecs, try libav which recognizes\n // a wider range (DTS, TrueHD, etc.). Only escalate if there ARE\n // tracks with unknown codecs — otherwise mediabunny's result is fine.\n const hasUnknownCodec =\n result.videoTracks.some((t) => t.codec === \"unknown\") ||\n result.audioTracks.some((t) => t.codec === \"unknown\");\n if (hasUnknownCodec) {\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch {\n // libav also failed — return mediabunny's result (unknown codecs\n // are better than no result at all)\n return result;\n }\n }\n return result;\n } catch (mediabunnyErr) {\n // mediabunny rejected the file. Before giving up, try libav — it can\n // demux a much wider range of codec combinations in ISOBMFF/MKV/etc.\n // than mediabunny's pure-JS parser (e.g. mp4v, wmv3-in-asf, flac in\n // an MP4 container). This is \"escalation\", not \"masking\": if libav\n // also fails we surface both errors below.\n // eslint-disable-next-line no-console\n console.warn(\n `[avbridge] mediabunny rejected ${sniffed} file, falling back to libav:`,\n (mediabunnyErr as Error).message,\n );\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (libavErr) {\n const mbMsg = (mediabunnyErr as Error).message || String(mediabunnyErr);\n const lvMsg = libavErr instanceof Error ? libavErr.message : String(libavErr);\n throw new AvbridgeError(\n ERR_PROBE_FAILED,\n `Failed to probe ${sniffed.toUpperCase()} file. mediabunny: ${mbMsg}. libav: ${lvMsg}.`,\n \"The file may be corrupt, truncated, or in an unsupported format. Enable AVBRIDGE_DEBUG for detailed logs.\",\n );\n }\n }\n }\n\n // sniffed === avi | asf | flv | unknown — try libav.\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (err) {\n const inner = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] libav probe failed for\", sniffed, \"file:\", err);\n if (sniffed === \"unknown\") {\n throw new AvbridgeError(\n ERR_PROBE_UNKNOWN_CONTAINER,\n `Unable to probe source: container format could not be identified. libav fallback: ${inner || \"(no details)\"}`,\n \"The file may be corrupt or in a format avbridge doesn't recognize. Check the file plays in VLC or ffprobe.\",\n );\n }\n throw new AvbridgeError(\n ERR_LIBAV_NOT_REACHABLE,\n `${sniffed.toUpperCase()} files require libav.js, which failed to load: ${inner || \"(no details)\"}`,\n \"Install @libav.js/variant-webcodecs, or check that AVBRIDGE_LIBAV_BASE points to the correct path.\",\n );\n }\n}\n"]}