avbridge 2.8.4 → 2.10.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.
- package/CHANGELOG.md +164 -0
- package/README.md +74 -1
- package/dist/{avi-F6WZJK5T.cjs → avi-2ILLBNPQ.cjs} +8 -2
- package/dist/avi-2ILLBNPQ.cjs.map +1 -0
- package/dist/{avi-W6L3BTWU.cjs → avi-B5CQYB7L.cjs} +8 -2
- package/dist/avi-B5CQYB7L.cjs.map +1 -0
- package/dist/{avi-2JPBSHGA.js → avi-JXU4GQL2.js} +8 -2
- package/dist/avi-JXU4GQL2.js.map +1 -0
- package/dist/{avi-NJXAXUXK.js → avi-RWWPN2PR.js} +8 -2
- package/dist/avi-RWWPN2PR.js.map +1 -0
- package/dist/{chunk-X2K3GIWE.js → chunk-2NSOOMXW.js} +14 -3
- package/dist/chunk-2NSOOMXW.js.map +1 -0
- package/dist/{chunk-KBWQRGHS.js → chunk-3GKM5DFM.js} +119 -8
- package/dist/chunk-3GKM5DFM.js.map +1 -0
- package/dist/{chunk-ZCUXHW55.cjs → chunk-BYGZN4Z5.cjs} +5 -5
- package/dist/{chunk-ZCUXHW55.cjs.map → chunk-BYGZN4Z5.cjs.map} +1 -1
- package/dist/{chunk-SMH6IOP2.js → chunk-CL6UEUQF.js} +4 -4
- package/dist/{chunk-SMH6IOP2.js.map → chunk-CL6UEUQF.js.map} +1 -1
- package/dist/{chunk-SR3MPV4D.js → chunk-GYIJU44C.js} +5 -5
- package/dist/{chunk-SR3MPV4D.js.map → chunk-GYIJU44C.js.map} +1 -1
- package/dist/{chunk-CPZ7PXAM.cjs → chunk-L7A3ECI2.cjs} +14 -2
- package/dist/chunk-L7A3ECI2.cjs.map +1 -0
- package/dist/{chunk-YX4AGLNF.cjs → chunk-NQULEIA3.cjs} +129 -18
- package/dist/chunk-NQULEIA3.cjs.map +1 -0
- package/dist/{chunk-Q2VUO52Z.cjs → chunk-OTFS7DC4.cjs} +12 -12
- package/dist/{chunk-Q2VUO52Z.cjs.map → chunk-OTFS7DC4.cjs.map} +1 -1
- package/dist/element-browser.js +144 -10
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +16 -10
- package/dist/element.cjs.map +1 -1
- package/dist/element.d.cts +11 -6
- package/dist/element.d.ts +11 -6
- package/dist/element.js +15 -9
- package/dist/element.js.map +1 -1
- package/dist/index.cjs +20 -20
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/libav-demux-3N5Y3VQA.cjs +31 -0
- package/dist/{libav-demux-H2GS46GH.cjs.map → libav-demux-3N5Y3VQA.cjs.map} +1 -1
- package/dist/libav-demux-JXD4OTLM.js +6 -0
- package/dist/{libav-demux-OWZ4T2YW.js.map → libav-demux-JXD4OTLM.js.map} +1 -1
- package/dist/{player-BptSJPfn.d.cts → player-DDdNVFDv.d.cts} +24 -2
- package/dist/{player-BptSJPfn.d.ts → player-DDdNVFDv.d.ts} +24 -2
- package/dist/player.cjs +413 -117
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +44 -11
- package/dist/player.d.ts +44 -11
- package/dist/player.js +413 -117
- package/dist/player.js.map +1 -1
- package/dist/{remux-WBYIZBBX.js → remux-56V7LDAD.js} +5 -5
- package/dist/{remux-WBYIZBBX.js.map → remux-56V7LDAD.js.map} +1 -1
- package/dist/{remux-OBSMIENG.cjs → remux-KUS5GIL6.cjs} +10 -10
- package/dist/{remux-OBSMIENG.cjs.map → remux-KUS5GIL6.cjs.map} +1 -1
- package/package.json +1 -1
- package/src/classify/rules.ts +2 -0
- package/src/element/avbridge-player.ts +172 -86
- package/src/element/avbridge-video.ts +22 -6
- package/src/element/player-styles.ts +149 -34
- package/src/index.ts +1 -0
- package/src/probe/avi.ts +2 -0
- package/src/strategies/fallback/audio-output.ts +29 -4
- package/src/strategies/fallback/decoder.ts +30 -0
- package/src/strategies/fallback/index.ts +42 -0
- package/src/strategies/hybrid/decoder.ts +35 -0
- package/src/strategies/hybrid/index.ts +26 -0
- package/src/strategies/remux/index.ts +8 -0
- package/src/types.ts +31 -0
- package/src/util/libav-demux.ts +26 -0
- package/dist/avi-2JPBSHGA.js.map +0 -1
- package/dist/avi-F6WZJK5T.cjs.map +0 -1
- package/dist/avi-NJXAXUXK.js.map +0 -1
- package/dist/avi-W6L3BTWU.cjs.map +0 -1
- package/dist/chunk-CPZ7PXAM.cjs.map +0 -1
- package/dist/chunk-KBWQRGHS.js.map +0 -1
- package/dist/chunk-X2K3GIWE.js.map +0 -1
- package/dist/chunk-YX4AGLNF.cjs.map +0 -1
- package/dist/libav-demux-H2GS46GH.cjs +0 -27
- package/dist/libav-demux-OWZ4T2YW.js +0 -6
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkS4WAZC2T_cjs = require('./chunk-S4WAZC2T.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkBYGZN4Z5_cjs = require('./chunk-BYGZN4Z5.cjs');
|
|
5
5
|
var chunk2IJ66NTD_cjs = require('./chunk-2IJ66NTD.cjs');
|
|
6
|
-
var
|
|
6
|
+
var chunkL7A3ECI2_cjs = require('./chunk-L7A3ECI2.cjs');
|
|
7
7
|
var chunkG4APZMCP_cjs = require('./chunk-G4APZMCP.cjs');
|
|
8
8
|
var chunkF3LQJKXK_cjs = require('./chunk-F3LQJKXK.cjs');
|
|
9
9
|
|
|
@@ -92,7 +92,13 @@ var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
|
|
|
92
92
|
"rv40",
|
|
93
93
|
"mpeg2",
|
|
94
94
|
"mpeg1",
|
|
95
|
-
"theora"
|
|
95
|
+
"theora",
|
|
96
|
+
"dv",
|
|
97
|
+
"hq_hqa",
|
|
98
|
+
"rawvideo",
|
|
99
|
+
"qtrle",
|
|
100
|
+
"png",
|
|
101
|
+
"vp6f"
|
|
96
102
|
]);
|
|
97
103
|
var FALLBACK_AUDIO_CODECS = /* @__PURE__ */ new Set([
|
|
98
104
|
"wmav2",
|
|
@@ -728,12 +734,12 @@ async function createRemuxPipeline(ctx, video) {
|
|
|
728
734
|
const mb = await import('mediabunny');
|
|
729
735
|
const videoTrackInfo = ctx.videoTracks[0];
|
|
730
736
|
if (!videoTrackInfo) throw new Error("remux: source has no video track");
|
|
731
|
-
const mbVideoCodec =
|
|
737
|
+
const mbVideoCodec = chunkBYGZN4Z5_cjs.avbridgeVideoToMediabunny(videoTrackInfo.codec);
|
|
732
738
|
if (!mbVideoCodec) {
|
|
733
739
|
throw new Error(`remux: video codec "${videoTrackInfo.codec}" is not supported by mediabunny output`);
|
|
734
740
|
}
|
|
735
741
|
const input = new mb.Input({
|
|
736
|
-
source: await
|
|
742
|
+
source: await chunkBYGZN4Z5_cjs.buildMediabunnySourceFromInput(mb, ctx.source),
|
|
737
743
|
formats: mb.ALL_FORMATS
|
|
738
744
|
});
|
|
739
745
|
const allTracks = await input.getTracks();
|
|
@@ -765,7 +771,7 @@ async function createRemuxPipeline(ctx, video) {
|
|
|
765
771
|
throw new Error("remux: audio track not found in input");
|
|
766
772
|
}
|
|
767
773
|
inputAudio = newInput;
|
|
768
|
-
mbAudioCodec =
|
|
774
|
+
mbAudioCodec = chunkBYGZN4Z5_cjs.avbridgeAudioToMediabunny(trackInfo.codec);
|
|
769
775
|
audioSink = new mb.EncodedPacketSink(newInput);
|
|
770
776
|
audioConfig = await newInput.getDecoderConfig();
|
|
771
777
|
}
|
|
@@ -976,6 +982,12 @@ async function createRemuxSession(context, video) {
|
|
|
976
982
|
}
|
|
977
983
|
const wasPlaying = !video.paused;
|
|
978
984
|
await pipeline.seek(time, wasPlaying || wantPlay);
|
|
985
|
+
queueMicrotask(() => {
|
|
986
|
+
try {
|
|
987
|
+
video.dispatchEvent(new Event("seeked"));
|
|
988
|
+
} catch {
|
|
989
|
+
}
|
|
990
|
+
});
|
|
979
991
|
},
|
|
980
992
|
async setAudioTrack(id) {
|
|
981
993
|
if (!context.audioTracks.some((t) => t.id === id)) {
|
|
@@ -1364,6 +1376,10 @@ var AudioOutput = class {
|
|
|
1364
1376
|
_volume = 1;
|
|
1365
1377
|
/** User-set muted flag. When true, gain is forced to 0. */
|
|
1366
1378
|
_muted = false;
|
|
1379
|
+
/** Playback rate. Scales the media clock and each AudioBufferSourceNode's
|
|
1380
|
+
* playbackRate so audio pitches up/down accordingly (same as native
|
|
1381
|
+
* <video>.playbackRate). Default 1. */
|
|
1382
|
+
_rate = 1;
|
|
1367
1383
|
constructor() {
|
|
1368
1384
|
this.ctx = new AudioContext();
|
|
1369
1385
|
this.gain = this.ctx.createGain();
|
|
@@ -1385,6 +1401,20 @@ var AudioOutput = class {
|
|
|
1385
1401
|
getMuted() {
|
|
1386
1402
|
return this._muted;
|
|
1387
1403
|
}
|
|
1404
|
+
/** Set playback rate. Scales the media clock and pitches audio output
|
|
1405
|
+
* (same as native <video>.playbackRate — speed without pitch correction).
|
|
1406
|
+
* Rebases the anchor so the clock transition is seamless. */
|
|
1407
|
+
setPlaybackRate(rate) {
|
|
1408
|
+
if (rate === this._rate) return;
|
|
1409
|
+
const t = this.now();
|
|
1410
|
+
this.mediaTimeOfAnchor = t;
|
|
1411
|
+
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
1412
|
+
this.wallAnchorMs = performance.now();
|
|
1413
|
+
this._rate = rate;
|
|
1414
|
+
}
|
|
1415
|
+
getPlaybackRate() {
|
|
1416
|
+
return this._rate;
|
|
1417
|
+
}
|
|
1388
1418
|
applyGain() {
|
|
1389
1419
|
const target = this._muted ? 0 : this._volume;
|
|
1390
1420
|
try {
|
|
@@ -1405,12 +1435,12 @@ var AudioOutput = class {
|
|
|
1405
1435
|
now() {
|
|
1406
1436
|
if (this.noAudio) {
|
|
1407
1437
|
if (this.state === "playing") {
|
|
1408
|
-
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3;
|
|
1438
|
+
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3 * this._rate;
|
|
1409
1439
|
}
|
|
1410
1440
|
return this.mediaTimeOfAnchor;
|
|
1411
1441
|
}
|
|
1412
1442
|
if (this.state === "playing") {
|
|
1413
|
-
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor);
|
|
1443
|
+
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;
|
|
1414
1444
|
}
|
|
1415
1445
|
return this.mediaTimeOfAnchor;
|
|
1416
1446
|
}
|
|
@@ -1462,7 +1492,8 @@ var AudioOutput = class {
|
|
|
1462
1492
|
const node = this.ctx.createBufferSource();
|
|
1463
1493
|
node.buffer = buffer;
|
|
1464
1494
|
node.connect(this.gain);
|
|
1465
|
-
|
|
1495
|
+
if (this._rate !== 1) node.playbackRate.value = this._rate;
|
|
1496
|
+
let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;
|
|
1466
1497
|
if (ctxStart < this.ctx.currentTime) {
|
|
1467
1498
|
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
1468
1499
|
this.mediaTimeOfAnchor = this.mediaTimeOfNext;
|
|
@@ -1703,6 +1734,7 @@ async function startHybridDecoder(opts) {
|
|
|
1703
1734
|
let videoFramesDecoded = 0;
|
|
1704
1735
|
let audioFramesDecoded = 0;
|
|
1705
1736
|
let videoChunksFed = 0;
|
|
1737
|
+
let bufferedUntilSec = 0;
|
|
1706
1738
|
let syntheticVideoUs = 0;
|
|
1707
1739
|
let syntheticAudioUs = 0;
|
|
1708
1740
|
const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);
|
|
@@ -1723,6 +1755,18 @@ async function startHybridDecoder(opts) {
|
|
|
1723
1755
|
if (myToken !== pumpToken || destroyed) return;
|
|
1724
1756
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
1725
1757
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
1758
|
+
if (videoPackets && videoTimeBase) {
|
|
1759
|
+
for (const pkt of videoPackets) {
|
|
1760
|
+
const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, videoTimeBase);
|
|
1761
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
if (audioPackets && audioTimeBase) {
|
|
1765
|
+
for (const pkt of audioPackets) {
|
|
1766
|
+
const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, audioTimeBase);
|
|
1767
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1726
1770
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
1727
1771
|
await decodeAudioBatch(audioPackets, myToken);
|
|
1728
1772
|
}
|
|
@@ -1733,7 +1777,7 @@ async function startHybridDecoder(opts) {
|
|
|
1733
1777
|
const processed = await applyBSF(videoPackets);
|
|
1734
1778
|
for (const pkt of processed) {
|
|
1735
1779
|
if (myToken !== pumpToken || destroyed) return;
|
|
1736
|
-
|
|
1780
|
+
chunkL7A3ECI2_cjs.sanitizePacketTimestamp(pkt, () => {
|
|
1737
1781
|
const ts = syntheticVideoUs;
|
|
1738
1782
|
syntheticVideoUs += videoFrameStepUs;
|
|
1739
1783
|
return ts;
|
|
@@ -1812,7 +1856,7 @@ async function startHybridDecoder(opts) {
|
|
|
1812
1856
|
const frames = allFrames;
|
|
1813
1857
|
for (const f of frames) {
|
|
1814
1858
|
if (myToken !== pumpToken || destroyed) return;
|
|
1815
|
-
|
|
1859
|
+
chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
|
|
1816
1860
|
f,
|
|
1817
1861
|
() => {
|
|
1818
1862
|
const ts = syntheticAudioUs;
|
|
@@ -1823,7 +1867,7 @@ async function startHybridDecoder(opts) {
|
|
|
1823
1867
|
},
|
|
1824
1868
|
audioTimeBase
|
|
1825
1869
|
);
|
|
1826
|
-
const samples =
|
|
1870
|
+
const samples = chunkL7A3ECI2_cjs.libavFrameToInterleavedFloat32(f);
|
|
1827
1871
|
if (samples) {
|
|
1828
1872
|
opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);
|
|
1829
1873
|
audioFramesDecoded++;
|
|
@@ -1979,6 +2023,9 @@ async function startHybridDecoder(opts) {
|
|
|
1979
2023
|
(err) => console.error("[avbridge] hybrid pump failed (post-seek):", err)
|
|
1980
2024
|
);
|
|
1981
2025
|
},
|
|
2026
|
+
bufferedUntilSec() {
|
|
2027
|
+
return bufferedUntilSec;
|
|
2028
|
+
},
|
|
1982
2029
|
stats() {
|
|
1983
2030
|
return {
|
|
1984
2031
|
decoderType: "webcodecs-hybrid",
|
|
@@ -2094,6 +2141,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2094
2141
|
get: () => ctx.duration ?? NaN
|
|
2095
2142
|
});
|
|
2096
2143
|
}
|
|
2144
|
+
Object.defineProperty(target, "playbackRate", {
|
|
2145
|
+
configurable: true,
|
|
2146
|
+
get: () => audio.getPlaybackRate(),
|
|
2147
|
+
set: (v) => {
|
|
2148
|
+
audio.setPlaybackRate(v);
|
|
2149
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
2097
2152
|
Object.defineProperty(target, "readyState", {
|
|
2098
2153
|
configurable: true,
|
|
2099
2154
|
get: () => {
|
|
@@ -2106,6 +2161,13 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2106
2161
|
configurable: true,
|
|
2107
2162
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
2108
2163
|
});
|
|
2164
|
+
Object.defineProperty(target, "buffered", {
|
|
2165
|
+
configurable: true,
|
|
2166
|
+
get: () => {
|
|
2167
|
+
const end = handles.bufferedUntilSec();
|
|
2168
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
2169
|
+
}
|
|
2170
|
+
});
|
|
2109
2171
|
async function waitForBuffer() {
|
|
2110
2172
|
const start = performance.now();
|
|
2111
2173
|
while (true) {
|
|
@@ -2119,6 +2181,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2119
2181
|
}
|
|
2120
2182
|
async function doSeek(timeSec) {
|
|
2121
2183
|
const wasPlaying = audio.isPlaying();
|
|
2184
|
+
target.dispatchEvent(new Event("seeking"));
|
|
2122
2185
|
await audio.pause().catch(() => {
|
|
2123
2186
|
});
|
|
2124
2187
|
await handles.seek(timeSec).catch(
|
|
@@ -2130,7 +2193,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2130
2193
|
await waitForBuffer();
|
|
2131
2194
|
await audio.start();
|
|
2132
2195
|
}
|
|
2196
|
+
target.dispatchEvent(new Event("seeked"));
|
|
2133
2197
|
}
|
|
2198
|
+
queueMicrotask(() => {
|
|
2199
|
+
try {
|
|
2200
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
2201
|
+
} catch {
|
|
2202
|
+
}
|
|
2203
|
+
});
|
|
2134
2204
|
let fatalErrorHandler = null;
|
|
2135
2205
|
handles.onFatalError((reason) => fatalErrorHandler?.(reason));
|
|
2136
2206
|
return {
|
|
@@ -2189,6 +2259,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2189
2259
|
delete target.muted;
|
|
2190
2260
|
delete target.readyState;
|
|
2191
2261
|
delete target.seekable;
|
|
2262
|
+
delete target.playbackRate;
|
|
2192
2263
|
} catch {
|
|
2193
2264
|
}
|
|
2194
2265
|
},
|
|
@@ -2315,6 +2386,7 @@ async function startDecoder(opts) {
|
|
|
2315
2386
|
let pumpRunning = null;
|
|
2316
2387
|
let packetsRead = 0;
|
|
2317
2388
|
let videoFramesDecoded = 0;
|
|
2389
|
+
let bufferedUntilSec = 0;
|
|
2318
2390
|
let audioFramesDecoded = 0;
|
|
2319
2391
|
let watchdogFirstFrameMs = 0;
|
|
2320
2392
|
let watchdogSlowSinceMs = 0;
|
|
@@ -2340,6 +2412,18 @@ async function startDecoder(opts) {
|
|
|
2340
2412
|
if (myToken !== pumpToken || destroyed) return;
|
|
2341
2413
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
2342
2414
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
2415
|
+
if (videoPackets && videoTimeBase) {
|
|
2416
|
+
for (const pkt of videoPackets) {
|
|
2417
|
+
const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, videoTimeBase);
|
|
2418
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
if (audioPackets && audioTimeBase) {
|
|
2422
|
+
for (const pkt of audioPackets) {
|
|
2423
|
+
const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, audioTimeBase);
|
|
2424
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2343
2427
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
2344
2428
|
await decodeAudioBatch(audioPackets, myToken);
|
|
2345
2429
|
}
|
|
@@ -2424,7 +2508,7 @@ async function startDecoder(opts) {
|
|
|
2424
2508
|
if (myToken !== pumpToken || destroyed) return;
|
|
2425
2509
|
for (const f of frames) {
|
|
2426
2510
|
if (myToken !== pumpToken || destroyed) return;
|
|
2427
|
-
|
|
2511
|
+
chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
|
|
2428
2512
|
f,
|
|
2429
2513
|
() => {
|
|
2430
2514
|
const ts = syntheticVideoUs;
|
|
@@ -2462,7 +2546,7 @@ async function startDecoder(opts) {
|
|
|
2462
2546
|
if (myToken !== pumpToken || destroyed) return;
|
|
2463
2547
|
for (const f of frames) {
|
|
2464
2548
|
if (myToken !== pumpToken || destroyed) return;
|
|
2465
|
-
|
|
2549
|
+
chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
|
|
2466
2550
|
f,
|
|
2467
2551
|
() => {
|
|
2468
2552
|
const ts = syntheticAudioUs;
|
|
@@ -2473,7 +2557,7 @@ async function startDecoder(opts) {
|
|
|
2473
2557
|
},
|
|
2474
2558
|
audioTimeBase
|
|
2475
2559
|
);
|
|
2476
|
-
const samples =
|
|
2560
|
+
const samples = chunkL7A3ECI2_cjs.libavFrameToInterleavedFloat32(f);
|
|
2477
2561
|
if (samples) {
|
|
2478
2562
|
opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);
|
|
2479
2563
|
audioFramesDecoded++;
|
|
@@ -2621,6 +2705,9 @@ async function startDecoder(opts) {
|
|
|
2621
2705
|
(err) => console.error("[avbridge] decoder pump failed (post-seek):", err)
|
|
2622
2706
|
);
|
|
2623
2707
|
},
|
|
2708
|
+
bufferedUntilSec() {
|
|
2709
|
+
return bufferedUntilSec;
|
|
2710
|
+
},
|
|
2624
2711
|
stats() {
|
|
2625
2712
|
return {
|
|
2626
2713
|
decoderType: "libav-wasm",
|
|
@@ -2708,6 +2795,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2708
2795
|
get: () => ctx.duration ?? NaN
|
|
2709
2796
|
});
|
|
2710
2797
|
}
|
|
2798
|
+
Object.defineProperty(target, "playbackRate", {
|
|
2799
|
+
configurable: true,
|
|
2800
|
+
get: () => audio.getPlaybackRate(),
|
|
2801
|
+
set: (v) => {
|
|
2802
|
+
audio.setPlaybackRate(v);
|
|
2803
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
2804
|
+
}
|
|
2805
|
+
});
|
|
2711
2806
|
Object.defineProperty(target, "readyState", {
|
|
2712
2807
|
configurable: true,
|
|
2713
2808
|
get: () => {
|
|
@@ -2720,6 +2815,13 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2720
2815
|
configurable: true,
|
|
2721
2816
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
2722
2817
|
});
|
|
2818
|
+
Object.defineProperty(target, "buffered", {
|
|
2819
|
+
configurable: true,
|
|
2820
|
+
get: () => {
|
|
2821
|
+
const end = handles.bufferedUntilSec();
|
|
2822
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
2823
|
+
}
|
|
2824
|
+
});
|
|
2723
2825
|
async function waitForBuffer() {
|
|
2724
2826
|
const start = performance.now();
|
|
2725
2827
|
let firstFrameAtMs = 0;
|
|
@@ -2759,6 +2861,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2759
2861
|
}
|
|
2760
2862
|
async function doSeek(timeSec) {
|
|
2761
2863
|
const wasPlaying = audio.isPlaying();
|
|
2864
|
+
target.dispatchEvent(new Event("seeking"));
|
|
2762
2865
|
await audio.pause().catch(() => {
|
|
2763
2866
|
});
|
|
2764
2867
|
await handles.seek(timeSec).catch(
|
|
@@ -2770,7 +2873,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2770
2873
|
await waitForBuffer();
|
|
2771
2874
|
await audio.start();
|
|
2772
2875
|
}
|
|
2876
|
+
target.dispatchEvent(new Event("seeked"));
|
|
2773
2877
|
}
|
|
2878
|
+
queueMicrotask(() => {
|
|
2879
|
+
try {
|
|
2880
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
2881
|
+
} catch {
|
|
2882
|
+
}
|
|
2883
|
+
});
|
|
2774
2884
|
return {
|
|
2775
2885
|
strategy: "fallback",
|
|
2776
2886
|
async play() {
|
|
@@ -2824,6 +2934,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2824
2934
|
delete target.muted;
|
|
2825
2935
|
delete target.readyState;
|
|
2826
2936
|
delete target.seekable;
|
|
2937
|
+
delete target.playbackRate;
|
|
2827
2938
|
} catch {
|
|
2828
2939
|
}
|
|
2829
2940
|
},
|
|
@@ -2962,7 +3073,7 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
2962
3073
|
const bootstrapStart = performance.now();
|
|
2963
3074
|
try {
|
|
2964
3075
|
chunkG4APZMCP_cjs.dbg.info("bootstrap", "start");
|
|
2965
|
-
const ctx = await chunkG4APZMCP_cjs.dbg.timed("probe", "probe", 3e3, () =>
|
|
3076
|
+
const ctx = await chunkG4APZMCP_cjs.dbg.timed("probe", "probe", 3e3, () => chunkBYGZN4Z5_cjs.probe(this.options.source, this.transport));
|
|
2966
3077
|
chunkG4APZMCP_cjs.dbg.info(
|
|
2967
3078
|
"probe",
|
|
2968
3079
|
`container=${ctx.container} video=${ctx.videoTracks[0]?.codec ?? "-"} audio=${ctx.audioTracks[0]?.codec ?? "-"} probedBy=${ctx.probedBy}`
|
|
@@ -3432,5 +3543,5 @@ exports.NATIVE_VIDEO_CODECS = NATIVE_VIDEO_CODECS;
|
|
|
3432
3543
|
exports.UnifiedPlayer = UnifiedPlayer;
|
|
3433
3544
|
exports.classifyContext = classifyContext;
|
|
3434
3545
|
exports.createPlayer = createPlayer;
|
|
3435
|
-
//# sourceMappingURL=chunk-
|
|
3436
|
-
//# sourceMappingURL=chunk-
|
|
3546
|
+
//# sourceMappingURL=chunk-NQULEIA3.cjs.map
|
|
3547
|
+
//# sourceMappingURL=chunk-NQULEIA3.cjs.map
|