avbridge 2.8.3 → 2.9.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 +165 -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-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-IUSFLVLJ.cjs → chunk-EY6DZEDT.cjs} +149 -24
- package/dist/chunk-EY6DZEDT.cjs.map +1 -0
- 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-Q2VUO52Z.cjs → chunk-OTFS7DC4.cjs} +12 -12
- package/dist/{chunk-Q2VUO52Z.cjs.map → chunk-OTFS7DC4.cjs.map} +1 -1
- package/dist/{chunk-JSQOBUQB.js → chunk-SN4WZE24.js} +139 -14
- package/dist/chunk-SN4WZE24.js.map +1 -0
- package/dist/element-browser.js +164 -16
- 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-DXEKOky8.d.cts → player-DEcidWk6.d.cts} +8 -1
- package/dist/{player-DXEKOky8.d.ts → player-DEcidWk6.d.ts} +8 -1
- package/dist/player.cjs +266 -36
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +37 -11
- package/dist/player.d.ts +37 -11
- package/dist/player.js +266 -36
- 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 +11 -0
- package/src/element/avbridge-player.ts +22 -11
- package/src/element/avbridge-video.ts +22 -6
- package/src/element/player-styles.ts +68 -3
- package/src/player.ts +96 -8
- package/src/probe/avi.ts +2 -0
- package/src/strategies/fallback/decoder.ts +30 -0
- package/src/strategies/fallback/index.ts +30 -0
- package/src/strategies/hybrid/decoder.ts +35 -0
- package/src/strategies/hybrid/index.ts +17 -0
- package/src/strategies/remux/index.ts +8 -0
- package/src/types.ts +6 -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-IUSFLVLJ.cjs.map +0 -1
- package/dist/chunk-JSQOBUQB.js.map +0 -1
- package/dist/chunk-X2K3GIWE.js.map +0 -1
- package/dist/libav-demux-H2GS46GH.cjs +0 -27
- package/dist/libav-demux-OWZ4T2YW.js +0 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SubtitleResourceBag, discoverSidecars, attachSubtitleTracks, SubtitleOverlay } from './chunk-5KVLE6YI.js';
|
|
2
|
-
import { probe, avbridgeVideoToMediabunny, buildMediabunnySourceFromInput, avbridgeAudioToMediabunny } from './chunk-
|
|
2
|
+
import { probe, avbridgeVideoToMediabunny, buildMediabunnySourceFromInput, avbridgeAudioToMediabunny } from './chunk-GYIJU44C.js';
|
|
3
3
|
import { AvbridgeError, ERR_ALL_STRATEGIES_EXHAUSTED, ERR_PLAYER_NOT_READY, ERR_MSE_NOT_SUPPORTED, ERR_MSE_CODEC_NOT_SUPPORTED } from './chunk-CPJLFFCC.js';
|
|
4
|
-
import { sanitizePacketTimestamp, sanitizeFrameTimestamp, libavFrameToInterleavedFloat32 } from './chunk-
|
|
4
|
+
import { packetPtsSec, sanitizePacketTimestamp, sanitizeFrameTimestamp, libavFrameToInterleavedFloat32 } from './chunk-2NSOOMXW.js';
|
|
5
5
|
import { dbg, loadLibav } from './chunk-5DMTJVIU.js';
|
|
6
6
|
import { pickLibavVariant } from './chunk-5YAWWKA3.js';
|
|
7
7
|
|
|
@@ -90,7 +90,13 @@ var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
|
|
|
90
90
|
"rv40",
|
|
91
91
|
"mpeg2",
|
|
92
92
|
"mpeg1",
|
|
93
|
-
"theora"
|
|
93
|
+
"theora",
|
|
94
|
+
"dv",
|
|
95
|
+
"hq_hqa",
|
|
96
|
+
"rawvideo",
|
|
97
|
+
"qtrle",
|
|
98
|
+
"png",
|
|
99
|
+
"vp6f"
|
|
94
100
|
]);
|
|
95
101
|
var FALLBACK_AUDIO_CODECS = /* @__PURE__ */ new Set([
|
|
96
102
|
"wmav2",
|
|
@@ -231,10 +237,12 @@ function classifyContext(ctx) {
|
|
|
231
237
|
reason: `${ctx.container} container with ${video.codec}${audio ? "/" + audio.codec : ""}; MSE rejects the remux target mime and WebCodecs is unavailable \u2014 falling back to WASM decode`
|
|
232
238
|
};
|
|
233
239
|
}
|
|
240
|
+
const fallbackChain = webCodecsAvailable() ? ["hybrid", "fallback"] : ["fallback"];
|
|
234
241
|
return {
|
|
235
242
|
class: "REMUX_CANDIDATE",
|
|
236
243
|
strategy: "remux",
|
|
237
|
-
reason: `${ctx.container} container with native-supported codecs \u2014 remux to fragmented MP4 for reliable playback
|
|
244
|
+
reason: `${ctx.container} container with native-supported codecs \u2014 remux to fragmented MP4 for reliable playback`,
|
|
245
|
+
fallbackChain
|
|
238
246
|
};
|
|
239
247
|
}
|
|
240
248
|
if (webCodecsAvailable()) {
|
|
@@ -972,6 +980,12 @@ async function createRemuxSession(context, video) {
|
|
|
972
980
|
}
|
|
973
981
|
const wasPlaying = !video.paused;
|
|
974
982
|
await pipeline.seek(time, wasPlaying || wantPlay);
|
|
983
|
+
queueMicrotask(() => {
|
|
984
|
+
try {
|
|
985
|
+
video.dispatchEvent(new Event("seeked"));
|
|
986
|
+
} catch {
|
|
987
|
+
}
|
|
988
|
+
});
|
|
975
989
|
},
|
|
976
990
|
async setAudioTrack(id) {
|
|
977
991
|
if (!context.audioTracks.some((t) => t.id === id)) {
|
|
@@ -1699,6 +1713,7 @@ async function startHybridDecoder(opts) {
|
|
|
1699
1713
|
let videoFramesDecoded = 0;
|
|
1700
1714
|
let audioFramesDecoded = 0;
|
|
1701
1715
|
let videoChunksFed = 0;
|
|
1716
|
+
let bufferedUntilSec = 0;
|
|
1702
1717
|
let syntheticVideoUs = 0;
|
|
1703
1718
|
let syntheticAudioUs = 0;
|
|
1704
1719
|
const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);
|
|
@@ -1719,6 +1734,18 @@ async function startHybridDecoder(opts) {
|
|
|
1719
1734
|
if (myToken !== pumpToken || destroyed) return;
|
|
1720
1735
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
1721
1736
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
1737
|
+
if (videoPackets && videoTimeBase) {
|
|
1738
|
+
for (const pkt of videoPackets) {
|
|
1739
|
+
const sec = packetPtsSec(pkt, videoTimeBase);
|
|
1740
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
if (audioPackets && audioTimeBase) {
|
|
1744
|
+
for (const pkt of audioPackets) {
|
|
1745
|
+
const sec = packetPtsSec(pkt, audioTimeBase);
|
|
1746
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1722
1749
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
1723
1750
|
await decodeAudioBatch(audioPackets, myToken);
|
|
1724
1751
|
}
|
|
@@ -1975,6 +2002,9 @@ async function startHybridDecoder(opts) {
|
|
|
1975
2002
|
(err) => console.error("[avbridge] hybrid pump failed (post-seek):", err)
|
|
1976
2003
|
);
|
|
1977
2004
|
},
|
|
2005
|
+
bufferedUntilSec() {
|
|
2006
|
+
return bufferedUntilSec;
|
|
2007
|
+
},
|
|
1978
2008
|
stats() {
|
|
1979
2009
|
return {
|
|
1980
2010
|
decoderType: "webcodecs-hybrid",
|
|
@@ -2102,6 +2132,13 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2102
2132
|
configurable: true,
|
|
2103
2133
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
2104
2134
|
});
|
|
2135
|
+
Object.defineProperty(target, "buffered", {
|
|
2136
|
+
configurable: true,
|
|
2137
|
+
get: () => {
|
|
2138
|
+
const end = handles.bufferedUntilSec();
|
|
2139
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
2140
|
+
}
|
|
2141
|
+
});
|
|
2105
2142
|
async function waitForBuffer() {
|
|
2106
2143
|
const start = performance.now();
|
|
2107
2144
|
while (true) {
|
|
@@ -2115,6 +2152,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2115
2152
|
}
|
|
2116
2153
|
async function doSeek(timeSec) {
|
|
2117
2154
|
const wasPlaying = audio.isPlaying();
|
|
2155
|
+
target.dispatchEvent(new Event("seeking"));
|
|
2118
2156
|
await audio.pause().catch(() => {
|
|
2119
2157
|
});
|
|
2120
2158
|
await handles.seek(timeSec).catch(
|
|
@@ -2126,7 +2164,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
2126
2164
|
await waitForBuffer();
|
|
2127
2165
|
await audio.start();
|
|
2128
2166
|
}
|
|
2167
|
+
target.dispatchEvent(new Event("seeked"));
|
|
2129
2168
|
}
|
|
2169
|
+
queueMicrotask(() => {
|
|
2170
|
+
try {
|
|
2171
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
2172
|
+
} catch {
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2130
2175
|
let fatalErrorHandler = null;
|
|
2131
2176
|
handles.onFatalError((reason) => fatalErrorHandler?.(reason));
|
|
2132
2177
|
return {
|
|
@@ -2311,6 +2356,7 @@ async function startDecoder(opts) {
|
|
|
2311
2356
|
let pumpRunning = null;
|
|
2312
2357
|
let packetsRead = 0;
|
|
2313
2358
|
let videoFramesDecoded = 0;
|
|
2359
|
+
let bufferedUntilSec = 0;
|
|
2314
2360
|
let audioFramesDecoded = 0;
|
|
2315
2361
|
let watchdogFirstFrameMs = 0;
|
|
2316
2362
|
let watchdogSlowSinceMs = 0;
|
|
@@ -2336,6 +2382,18 @@ async function startDecoder(opts) {
|
|
|
2336
2382
|
if (myToken !== pumpToken || destroyed) return;
|
|
2337
2383
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
2338
2384
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
2385
|
+
if (videoPackets && videoTimeBase) {
|
|
2386
|
+
for (const pkt of videoPackets) {
|
|
2387
|
+
const sec = packetPtsSec(pkt, videoTimeBase);
|
|
2388
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
if (audioPackets && audioTimeBase) {
|
|
2392
|
+
for (const pkt of audioPackets) {
|
|
2393
|
+
const sec = packetPtsSec(pkt, audioTimeBase);
|
|
2394
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2339
2397
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
2340
2398
|
await decodeAudioBatch(audioPackets, myToken);
|
|
2341
2399
|
}
|
|
@@ -2617,6 +2675,9 @@ async function startDecoder(opts) {
|
|
|
2617
2675
|
(err) => console.error("[avbridge] decoder pump failed (post-seek):", err)
|
|
2618
2676
|
);
|
|
2619
2677
|
},
|
|
2678
|
+
bufferedUntilSec() {
|
|
2679
|
+
return bufferedUntilSec;
|
|
2680
|
+
},
|
|
2620
2681
|
stats() {
|
|
2621
2682
|
return {
|
|
2622
2683
|
decoderType: "libav-wasm",
|
|
@@ -2716,6 +2777,13 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2716
2777
|
configurable: true,
|
|
2717
2778
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
2718
2779
|
});
|
|
2780
|
+
Object.defineProperty(target, "buffered", {
|
|
2781
|
+
configurable: true,
|
|
2782
|
+
get: () => {
|
|
2783
|
+
const end = handles.bufferedUntilSec();
|
|
2784
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
2785
|
+
}
|
|
2786
|
+
});
|
|
2719
2787
|
async function waitForBuffer() {
|
|
2720
2788
|
const start = performance.now();
|
|
2721
2789
|
let firstFrameAtMs = 0;
|
|
@@ -2755,6 +2823,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2755
2823
|
}
|
|
2756
2824
|
async function doSeek(timeSec) {
|
|
2757
2825
|
const wasPlaying = audio.isPlaying();
|
|
2826
|
+
target.dispatchEvent(new Event("seeking"));
|
|
2758
2827
|
await audio.pause().catch(() => {
|
|
2759
2828
|
});
|
|
2760
2829
|
await handles.seek(timeSec).catch(
|
|
@@ -2766,7 +2835,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
2766
2835
|
await waitForBuffer();
|
|
2767
2836
|
await audio.start();
|
|
2768
2837
|
}
|
|
2838
|
+
target.dispatchEvent(new Event("seeked"));
|
|
2769
2839
|
}
|
|
2840
|
+
queueMicrotask(() => {
|
|
2841
|
+
try {
|
|
2842
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
2843
|
+
} catch {
|
|
2844
|
+
}
|
|
2845
|
+
});
|
|
2770
2846
|
return {
|
|
2771
2847
|
strategy: "fallback",
|
|
2772
2848
|
async play() {
|
|
@@ -2858,6 +2934,29 @@ function registerBuiltins(registry) {
|
|
|
2858
2934
|
}
|
|
2859
2935
|
|
|
2860
2936
|
// src/player.ts
|
|
2937
|
+
function readDecodedFrameCount(target) {
|
|
2938
|
+
if (typeof HTMLVideoElement === "undefined" || !(target instanceof HTMLVideoElement)) return 0;
|
|
2939
|
+
const vq = target.getVideoPlaybackQuality;
|
|
2940
|
+
if (typeof vq === "function") {
|
|
2941
|
+
try {
|
|
2942
|
+
return vq.call(target).totalVideoFrames;
|
|
2943
|
+
} catch {
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
const legacy = target.webkitDecodedFrameCount;
|
|
2947
|
+
return typeof legacy === "number" ? legacy : 0;
|
|
2948
|
+
}
|
|
2949
|
+
function evaluateDecodeHealth(input) {
|
|
2950
|
+
const timeThreshold = input.timeStallThresholdMs ?? 5e3;
|
|
2951
|
+
const frameThreshold = input.frameStallThresholdMs ?? 3e3;
|
|
2952
|
+
if (!input.timeAdvanced && input.now - input.lastProgressTime > timeThreshold) {
|
|
2953
|
+
return { escalate: true, kind: "time-stall" };
|
|
2954
|
+
}
|
|
2955
|
+
if (input.hasVideoTrack && input.timeAdvanced && !input.framesAdvanced && input.now - input.lastFrameProgressTime > frameThreshold) {
|
|
2956
|
+
return { escalate: true, kind: "silent-video" };
|
|
2957
|
+
}
|
|
2958
|
+
return { escalate: false };
|
|
2959
|
+
}
|
|
2861
2960
|
var UnifiedPlayer = class _UnifiedPlayer {
|
|
2862
2961
|
/**
|
|
2863
2962
|
* @internal Use {@link createPlayer} or {@link UnifiedPlayer.create} instead.
|
|
@@ -2883,6 +2982,13 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
2883
2982
|
stallTimer = null;
|
|
2884
2983
|
lastProgressTime = 0;
|
|
2885
2984
|
lastProgressPosition = -1;
|
|
2985
|
+
/** Last observed `HTMLVideoElement.getVideoPlaybackQuality().totalVideoFrames`
|
|
2986
|
+
* (or `webkitDecodedFrameCount` fallback). Used by the silent-video
|
|
2987
|
+
* watchdog — catches cases where `currentTime` advances (audio plays)
|
|
2988
|
+
* but the decoder produces no frames, e.g. Firefox claiming `hev1.*`
|
|
2989
|
+
* via MSE when the decoder actually can't decode HEVC. */
|
|
2990
|
+
lastVideoFrameCount = 0;
|
|
2991
|
+
lastVideoFrameProgressTime = 0;
|
|
2886
2992
|
errorListener = null;
|
|
2887
2993
|
// Bound so we can removeEventListener in destroy(); without this the
|
|
2888
2994
|
// listener outlives the player and accumulates on elements that swap
|
|
@@ -3127,22 +3233,41 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
3127
3233
|
if (strategy === "native" || strategy === "remux") {
|
|
3128
3234
|
this.lastProgressPosition = this.options.target.currentTime;
|
|
3129
3235
|
this.lastProgressTime = performance.now();
|
|
3236
|
+
this.lastVideoFrameCount = readDecodedFrameCount(this.options.target);
|
|
3237
|
+
this.lastVideoFrameProgressTime = performance.now();
|
|
3238
|
+
const hasVideoTrack = (this.mediaContext?.videoTracks.length ?? 0) > 0;
|
|
3130
3239
|
this.stallTimer = setInterval(() => {
|
|
3131
3240
|
const t = this.options.target;
|
|
3241
|
+
const now = performance.now();
|
|
3132
3242
|
if (t.paused || t.ended || t.readyState < 2) {
|
|
3133
3243
|
this.lastProgressPosition = t.currentTime;
|
|
3134
|
-
this.lastProgressTime =
|
|
3244
|
+
this.lastProgressTime = now;
|
|
3245
|
+
this.lastVideoFrameCount = readDecodedFrameCount(t);
|
|
3246
|
+
this.lastVideoFrameProgressTime = now;
|
|
3135
3247
|
return;
|
|
3136
3248
|
}
|
|
3137
|
-
|
|
3249
|
+
const timeAdvanced = t.currentTime !== this.lastProgressPosition;
|
|
3250
|
+
const frames = readDecodedFrameCount(t);
|
|
3251
|
+
const framesAdvanced = frames > this.lastVideoFrameCount;
|
|
3252
|
+
const health = evaluateDecodeHealth({
|
|
3253
|
+
hasVideoTrack,
|
|
3254
|
+
timeAdvanced,
|
|
3255
|
+
framesAdvanced,
|
|
3256
|
+
now,
|
|
3257
|
+
lastProgressTime: this.lastProgressTime,
|
|
3258
|
+
lastFrameProgressTime: this.lastVideoFrameProgressTime
|
|
3259
|
+
});
|
|
3260
|
+
if (timeAdvanced) {
|
|
3138
3261
|
this.lastProgressPosition = t.currentTime;
|
|
3139
|
-
this.lastProgressTime =
|
|
3140
|
-
return;
|
|
3262
|
+
this.lastProgressTime = now;
|
|
3141
3263
|
}
|
|
3142
|
-
if (
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3264
|
+
if (framesAdvanced) {
|
|
3265
|
+
this.lastVideoFrameCount = frames;
|
|
3266
|
+
this.lastVideoFrameProgressTime = now;
|
|
3267
|
+
}
|
|
3268
|
+
if (health.escalate) {
|
|
3269
|
+
const reason = health.kind === "time-stall" ? `${strategy} strategy stalled for 5s at ${t.currentTime.toFixed(1)}s` : `${strategy} strategy: audio is advancing but the video decoder has produced no new frames for 3s \u2014 likely a silent codec failure`;
|
|
3270
|
+
void this.escalate(reason);
|
|
3146
3271
|
}
|
|
3147
3272
|
}, 1e3);
|
|
3148
3273
|
const onError = () => {
|
|
@@ -3373,5 +3498,5 @@ function defaultFallbackChain(strategy) {
|
|
|
3373
3498
|
}
|
|
3374
3499
|
|
|
3375
3500
|
export { FALLBACK_AUDIO_CODECS, FALLBACK_VIDEO_CODECS, NATIVE_AUDIO_CODECS, NATIVE_VIDEO_CODECS, UnifiedPlayer, classifyContext, createPlayer };
|
|
3376
|
-
//# sourceMappingURL=chunk-
|
|
3377
|
-
//# sourceMappingURL=chunk-
|
|
3501
|
+
//# sourceMappingURL=chunk-SN4WZE24.js.map
|
|
3502
|
+
//# sourceMappingURL=chunk-SN4WZE24.js.map
|