avbridge 2.1.0 → 2.1.2
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.
- package/CHANGELOG.md +56 -0
- package/dist/{chunk-CUQD23WO.js → chunk-3AUGRKPY.js} +31 -10
- package/dist/chunk-3AUGRKPY.js.map +1 -0
- package/dist/{chunk-O34444ID.cjs → chunk-DPVIOYGC.cjs} +31 -10
- package/dist/chunk-DPVIOYGC.cjs.map +1 -0
- package/dist/element-browser.js +945 -17
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +7 -3
- package/dist/element.cjs.map +1 -1
- package/dist/element.js +6 -2
- package/dist/element.js.map +1 -1
- package/dist/index.cjs +14 -14
- package/dist/index.d.cts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/src/element/avbridge-video.ts +12 -1
- package/src/probe/index.ts +30 -9
- package/src/strategies/fallback/video-renderer.ts +29 -4
- package/src/strategies/remux/pipeline.ts +10 -1
- package/dist/chunk-CUQD23WO.js.map +0 -1
- package/dist/chunk-O34444ID.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,62 @@ 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.1.2]
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Fallback strategy video now visible inside `<avbridge-video>`.** The
|
|
12
|
+
fallback renderer attaches its canvas overlay via `target.parentElement`,
|
|
13
|
+
but when the `<video>` lives inside a `ShadowRoot` (as it does in the
|
|
14
|
+
custom element), `parentElement` is `null` because `ShadowRoot` is not
|
|
15
|
+
an `Element`. The canvas silently never got attached to the DOM, so
|
|
16
|
+
frames were decoded and "painted" (the stats counters incremented) but
|
|
17
|
+
nothing was ever visible — just audio. Fixed by wrapping the shadow
|
|
18
|
+
`<video>` in a positioned `<div part="stage">` and hardening the
|
|
19
|
+
renderer's parent lookup to use `parentNode` as a fallback with a loud
|
|
20
|
+
warning if no parent exists at all.
|
|
21
|
+
|
|
22
|
+
- **Remux strategy reseek no longer fails with "First packet must be a
|
|
23
|
+
key packet".** When `setStrategy("remux")` is invoked mid-playback, the
|
|
24
|
+
pipeline recreates mediabunny's `Output` (required because mediabunny's
|
|
25
|
+
fMP4 muxer is one-shot streaming). The pump's packet race could then
|
|
26
|
+
emit an audio packet first on the fresh muxer, which mediabunny rejects
|
|
27
|
+
because the first packet of any muxer run must be a key packet. The
|
|
28
|
+
pump now forces the first video packet — which we fetch via
|
|
29
|
+
`getKeyPacket()` and is guaranteed to be a keyframe — out before any
|
|
30
|
+
audio.
|
|
31
|
+
|
|
32
|
+
- **`mp4v`-in-MP4 files now fall through to libav probing.** mediabunny's
|
|
33
|
+
MP4 demuxer asserts on files whose video sample entry type isn't one
|
|
34
|
+
it recognizes (`mp4v` for MPEG-4 Part 2 / DivX / Xvid packaged in
|
|
35
|
+
ISOBMFF is the common case). Previously the probe rethrew the
|
|
36
|
+
assertion and gave up. The probe now escalates to libav when
|
|
37
|
+
mediabunny fails on any mediabunny-targeted container (mp4, mkv,
|
|
38
|
+
webm, …), which handles the long tail of codec combinations
|
|
39
|
+
mediabunny's pure-JS parser doesn't cover. If libav also fails, both
|
|
40
|
+
errors are surfaced together.
|
|
41
|
+
|
|
42
|
+
- **Demo dev server serves libav binaries via a Vite middleware plugin**
|
|
43
|
+
instead of `demo/public/libav/`. Recent Vite versions refuse to let
|
|
44
|
+
source code `import()` files out of `public/`, which broke the libav
|
|
45
|
+
loader's dynamic import. `serveVendorLibav()` in `vite.config.ts` now
|
|
46
|
+
streams files directly out of `vendor/libav/` at the same `/libav/*`
|
|
47
|
+
URL, bypassing the restriction. `scripts/copy-libav.mjs` is
|
|
48
|
+
simplified — it no longer mirrors to the demo's public tree.
|
|
49
|
+
|
|
50
|
+
## [2.1.1]
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- **`dist/element-browser.js` no longer has a bare `libavjs-webcodecs-bridge`
|
|
55
|
+
import.** 2.1.0 inlined mediabunny into the browser bundle but left
|
|
56
|
+
`libavjs-webcodecs-bridge` external, so direct
|
|
57
|
+
`<script type="module">` consumers hit
|
|
58
|
+
`Failed to resolve module specifier "libavjs-webcodecs-bridge"` on load.
|
|
59
|
+
The browser entry now inlines it via `noExternal`. Only the actual
|
|
60
|
+
libav.js WASM variants stay external, and those are loaded via URL
|
|
61
|
+
dynamic imports relative to `import.meta.url`, not bare specifiers.
|
|
62
|
+
|
|
7
63
|
## [2.1.0]
|
|
8
64
|
|
|
9
65
|
### Added
|
|
@@ -184,10 +184,21 @@ async function probe(source) {
|
|
|
184
184
|
if (MEDIABUNNY_CONTAINERS.has(sniffed)) {
|
|
185
185
|
try {
|
|
186
186
|
return await probeWithMediabunny(normalized, sniffed);
|
|
187
|
-
} catch (
|
|
188
|
-
|
|
189
|
-
`mediabunny
|
|
187
|
+
} catch (mediabunnyErr) {
|
|
188
|
+
console.warn(
|
|
189
|
+
`[avbridge] mediabunny rejected ${sniffed} file, falling back to libav:`,
|
|
190
|
+
mediabunnyErr.message
|
|
190
191
|
);
|
|
192
|
+
try {
|
|
193
|
+
const { probeWithLibav } = await import('./avi-V6HYQVR2.js');
|
|
194
|
+
return await probeWithLibav(normalized, sniffed);
|
|
195
|
+
} catch (libavErr) {
|
|
196
|
+
const mbMsg = mediabunnyErr.message || String(mediabunnyErr);
|
|
197
|
+
const lvMsg = libavErr instanceof Error ? libavErr.message : String(libavErr);
|
|
198
|
+
throw new Error(
|
|
199
|
+
`failed to probe ${sniffed} file. mediabunny: ${mbMsg}. libav fallback: ${lvMsg}.`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
191
202
|
}
|
|
192
203
|
}
|
|
193
204
|
try {
|
|
@@ -988,7 +999,8 @@ async function createRemuxPipeline(ctx, video) {
|
|
|
988
999
|
if (destroyed || pumpToken !== token) break;
|
|
989
1000
|
const vTs = !vNext.done ? vNext.value.timestamp : Number.POSITIVE_INFINITY;
|
|
990
1001
|
const aTs = !aNext.done ? aNext.value.timestamp : Number.POSITIVE_INFINITY;
|
|
991
|
-
|
|
1002
|
+
const forceVideoFirst = firstVideo && !vNext.done;
|
|
1003
|
+
if (!vNext.done && (forceVideoFirst || vTs <= aTs)) {
|
|
992
1004
|
await videoSource.add(
|
|
993
1005
|
vNext.value,
|
|
994
1006
|
firstVideo && videoConfig ? { decoderConfig: videoConfig } : void 0
|
|
@@ -1126,11 +1138,20 @@ var VideoRenderer = class {
|
|
|
1126
1138
|
});
|
|
1127
1139
|
this.canvas = document.createElement("canvas");
|
|
1128
1140
|
this.canvas.style.cssText = "position:absolute;left:0;top:0;width:100%;height:100%;background:black;";
|
|
1129
|
-
const parent = target.parentElement;
|
|
1130
|
-
if (parent &&
|
|
1131
|
-
parent.
|
|
1141
|
+
const parent = target.parentElement ?? target.parentNode;
|
|
1142
|
+
if (parent && parent instanceof HTMLElement) {
|
|
1143
|
+
if (getComputedStyle(parent).position === "static") {
|
|
1144
|
+
parent.style.position = "relative";
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
if (parent) {
|
|
1148
|
+
parent.insertBefore(this.canvas, target);
|
|
1149
|
+
} else {
|
|
1150
|
+
console.warn(
|
|
1151
|
+
"[avbridge] fallback renderer: target <video> has no parent; appending canvas to document.body as a fallback."
|
|
1152
|
+
);
|
|
1153
|
+
document.body.appendChild(this.canvas);
|
|
1132
1154
|
}
|
|
1133
|
-
parent?.insertBefore(this.canvas, target);
|
|
1134
1155
|
target.style.visibility = "hidden";
|
|
1135
1156
|
const ctx = this.canvas.getContext("2d");
|
|
1136
1157
|
if (!ctx) throw new Error("video renderer: failed to acquire 2D context");
|
|
@@ -3056,5 +3077,5 @@ function defaultFallbackChain(strategy) {
|
|
|
3056
3077
|
}
|
|
3057
3078
|
|
|
3058
3079
|
export { UnifiedPlayer, avbridgeAudioToMediabunny, avbridgeVideoToMediabunny, buildMediabunnySourceFromInput, classifyContext, createPlayer, probe, srtToVtt };
|
|
3059
|
-
//# sourceMappingURL=chunk-
|
|
3060
|
-
//# sourceMappingURL=chunk-
|
|
3080
|
+
//# sourceMappingURL=chunk-3AUGRKPY.js.map
|
|
3081
|
+
//# sourceMappingURL=chunk-3AUGRKPY.js.map
|