avbridge 2.1.2 → 2.2.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 +93 -0
- package/dist/{avi-GNTV5ZOH.cjs → avi-6SJLWIWW.cjs} +19 -4
- package/dist/avi-6SJLWIWW.cjs.map +1 -0
- package/dist/{avi-V6HYQVR2.js → avi-GCGM7OJI.js} +18 -3
- package/dist/avi-GCGM7OJI.js.map +1 -0
- package/dist/{chunk-EJH67FXG.js → chunk-5DMTJVIU.js} +99 -3
- package/dist/chunk-5DMTJVIU.js.map +1 -0
- package/dist/{chunk-3AUGRKPY.js → chunk-C5VA5U5O.js} +94 -16
- package/dist/chunk-C5VA5U5O.js.map +1 -0
- package/dist/{chunk-JQH6D4OE.cjs → chunk-G4APZMCP.cjs} +100 -3
- package/dist/chunk-G4APZMCP.cjs.map +1 -0
- package/dist/{chunk-Y5FYF5KG.cjs → chunk-HZLQNKFN.cjs} +5 -2
- package/dist/chunk-HZLQNKFN.cjs.map +1 -0
- package/dist/{chunk-PQTZS7OA.js → chunk-ILKDNBSE.js} +5 -2
- package/dist/chunk-ILKDNBSE.js.map +1 -0
- package/dist/{chunk-DPVIOYGC.cjs → chunk-OE66B34H.cjs} +98 -20
- package/dist/chunk-OE66B34H.cjs.map +1 -0
- package/dist/element-browser.js +210 -10
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +4 -4
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.js +3 -3
- package/dist/index.cjs +18 -18
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/libav-loader-27RDIN2I.js +3 -0
- package/dist/{libav-loader-XKH2TKUW.js.map → libav-loader-27RDIN2I.js.map} +1 -1
- package/dist/libav-loader-IV4AJ2HW.cjs +12 -0
- package/dist/{libav-loader-6APXVNIV.cjs.map → libav-loader-IV4AJ2HW.cjs.map} +1 -1
- package/dist/{player-BdtUG4rh.d.cts → player-DUyvltvy.d.cts} +3 -3
- package/dist/{player-BdtUG4rh.d.ts → player-DUyvltvy.d.ts} +3 -3
- package/dist/source-CN43EI7Z.cjs +28 -0
- package/dist/{source-SC6ZEQYR.cjs.map → source-CN43EI7Z.cjs.map} +1 -1
- package/dist/source-FFZ7TW2B.js +3 -0
- package/dist/{source-ZFS4H7J3.js.map → source-FFZ7TW2B.js.map} +1 -1
- package/package.json +1 -1
- package/src/classify/rules.ts +9 -2
- package/src/player.ts +22 -1
- package/src/probe/avi.ts +8 -1
- package/src/strategies/fallback/audio-output.ts +25 -3
- package/src/strategies/fallback/decoder.ts +96 -8
- package/src/strategies/fallback/index.ts +90 -6
- package/src/strategies/fallback/libav-loader.ts +12 -0
- package/src/types.ts +10 -1
- package/src/util/debug.ts +131 -0
- package/src/util/source.ts +4 -0
- package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +1 -1
- package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
- package/dist/avi-GNTV5ZOH.cjs.map +0 -1
- package/dist/avi-V6HYQVR2.js.map +0 -1
- package/dist/chunk-3AUGRKPY.js.map +0 -1
- package/dist/chunk-DPVIOYGC.cjs.map +0 -1
- package/dist/chunk-EJH67FXG.js.map +0 -1
- package/dist/chunk-JQH6D4OE.cjs.map +0 -1
- package/dist/chunk-PQTZS7OA.js.map +0 -1
- package/dist/chunk-Y5FYF5KG.cjs.map +0 -1
- package/dist/libav-loader-6APXVNIV.cjs +0 -12
- package/dist/libav-loader-XKH2TKUW.js +0 -3
- package/dist/source-SC6ZEQYR.cjs +0 -28
- package/dist/source-ZFS4H7J3.js +0 -3
package/dist/element-browser.js
CHANGED
|
@@ -145,6 +145,9 @@ function sniffContainerFromBytes(head) {
|
|
|
145
145
|
}
|
|
146
146
|
if (head[0] === 48 && head[1] === 38 && head[2] === 178 && head[3] === 117 && head[4] === 142 && head[5] === 102 && head[6] === 207 && head[7] === 17) return "asf";
|
|
147
147
|
if (head[0] === 70 && head[1] === 76 && head[2] === 86) return "flv";
|
|
148
|
+
if (head[0] === 46 && head[1] === 82 && head[2] === 77 && head[3] === 70) {
|
|
149
|
+
return "rm";
|
|
150
|
+
}
|
|
148
151
|
if (head[0] === 79 && head[1] === 103 && head[2] === 103 && head[3] === 83) return "ogg";
|
|
149
152
|
if (head[0] === 102 && head[1] === 76 && head[2] === 97 && head[3] === 67) return "flac";
|
|
150
153
|
if (head[0] === 73 && head[1] === 68 && head[2] === 51) return "mp3";
|
|
@@ -29628,6 +29631,98 @@ var init_libav_http_reader = __esm({
|
|
|
29628
29631
|
}
|
|
29629
29632
|
});
|
|
29630
29633
|
|
|
29634
|
+
// src/util/debug.ts
|
|
29635
|
+
function isDebugEnabled() {
|
|
29636
|
+
if (typeof globalThis === "undefined") return false;
|
|
29637
|
+
const g = globalThis;
|
|
29638
|
+
if (g.AVBRIDGE_DEBUG === true) return true;
|
|
29639
|
+
if (typeof location !== "undefined" && typeof URLSearchParams !== "undefined") {
|
|
29640
|
+
try {
|
|
29641
|
+
const p = new URLSearchParams(location.search);
|
|
29642
|
+
if (p.has("avbridge_debug")) {
|
|
29643
|
+
g.AVBRIDGE_DEBUG = true;
|
|
29644
|
+
return true;
|
|
29645
|
+
}
|
|
29646
|
+
} catch {
|
|
29647
|
+
}
|
|
29648
|
+
}
|
|
29649
|
+
return false;
|
|
29650
|
+
}
|
|
29651
|
+
function fmt(tag) {
|
|
29652
|
+
return `[avbridge:${tag}]`;
|
|
29653
|
+
}
|
|
29654
|
+
function hintForTag(tag) {
|
|
29655
|
+
switch (tag) {
|
|
29656
|
+
case "probe":
|
|
29657
|
+
return "slow network (range request), large sniff window, or libav cold-start";
|
|
29658
|
+
case "libav-load":
|
|
29659
|
+
return "large .wasm download, misconfigured AVBRIDGE_LIBAV_BASE, or server-side MIME type";
|
|
29660
|
+
case "bootstrap":
|
|
29661
|
+
return "probe+classify+strategy-init chain; enable AVBRIDGE_DEBUG for a phase breakdown";
|
|
29662
|
+
case "cold-start":
|
|
29663
|
+
return "decoder is producing output slower than realtime \u2014 check framesDecoded in getDiagnostics()";
|
|
29664
|
+
default:
|
|
29665
|
+
return "unknown stage \u2014 enable globalThis.AVBRIDGE_DEBUG for more detail";
|
|
29666
|
+
}
|
|
29667
|
+
}
|
|
29668
|
+
var dbg;
|
|
29669
|
+
var init_debug = __esm({
|
|
29670
|
+
"src/util/debug.ts"() {
|
|
29671
|
+
dbg = {
|
|
29672
|
+
/** Verbose — only when debug is enabled. The hot-path normal case. */
|
|
29673
|
+
info(tag, ...args) {
|
|
29674
|
+
if (isDebugEnabled()) console.info(fmt(tag), ...args);
|
|
29675
|
+
},
|
|
29676
|
+
/** Warning — only when debug is enabled. Non-fatal oddities. */
|
|
29677
|
+
warn(tag, ...args) {
|
|
29678
|
+
if (isDebugEnabled()) console.warn(fmt(tag), ...args);
|
|
29679
|
+
},
|
|
29680
|
+
/**
|
|
29681
|
+
* Self-diagnosis warning. **Always** emits regardless of debug flag.
|
|
29682
|
+
* Use this only for conditions that mean something is actually wrong
|
|
29683
|
+
* or degraded — not for routine chatter.
|
|
29684
|
+
*/
|
|
29685
|
+
diag(tag, ...args) {
|
|
29686
|
+
console.warn(fmt(tag), ...args);
|
|
29687
|
+
},
|
|
29688
|
+
/**
|
|
29689
|
+
* Timing helper: wraps an async call and logs its elapsed time when
|
|
29690
|
+
* debug is on. The callback runs whether debug is on or off — this is
|
|
29691
|
+
* just for the `dbg.info` at the end.
|
|
29692
|
+
*
|
|
29693
|
+
* Also unconditionally fires `dbg.diag` if the elapsed time exceeds
|
|
29694
|
+
* `slowMs`, so "the bootstrap took 8 seconds" shows up even without
|
|
29695
|
+
* debug mode enabled.
|
|
29696
|
+
*/
|
|
29697
|
+
async timed(tag, label, slowMs, fn) {
|
|
29698
|
+
const start = performance.now();
|
|
29699
|
+
try {
|
|
29700
|
+
const result = await fn();
|
|
29701
|
+
const elapsed = performance.now() - start;
|
|
29702
|
+
if (isDebugEnabled()) {
|
|
29703
|
+
console.info(fmt(tag), `${label} ${elapsed.toFixed(0)}ms`);
|
|
29704
|
+
}
|
|
29705
|
+
if (elapsed > slowMs) {
|
|
29706
|
+
console.warn(
|
|
29707
|
+
fmt(tag),
|
|
29708
|
+
`${label} took ${elapsed.toFixed(0)}ms (>${slowMs}ms expected) \u2014 this is unusually slow; possible causes: ${hintForTag(tag)}`
|
|
29709
|
+
);
|
|
29710
|
+
}
|
|
29711
|
+
return result;
|
|
29712
|
+
} catch (err) {
|
|
29713
|
+
const elapsed = performance.now() - start;
|
|
29714
|
+
console.warn(
|
|
29715
|
+
fmt(tag),
|
|
29716
|
+
`${label} FAILED after ${elapsed.toFixed(0)}ms:`,
|
|
29717
|
+
err
|
|
29718
|
+
);
|
|
29719
|
+
throw err;
|
|
29720
|
+
}
|
|
29721
|
+
}
|
|
29722
|
+
};
|
|
29723
|
+
}
|
|
29724
|
+
});
|
|
29725
|
+
|
|
29631
29726
|
// src/strategies/fallback/libav-loader.ts
|
|
29632
29727
|
function cacheKey(variant, threads) {
|
|
29633
29728
|
return `${variant}:${threads ? "thr" : "wasm"}`;
|
|
@@ -29644,9 +29739,18 @@ function loadLibav(variant = "webcodecs", opts = {}) {
|
|
|
29644
29739
|
return entry;
|
|
29645
29740
|
}
|
|
29646
29741
|
async function loadVariant(variant, wantThreads) {
|
|
29742
|
+
return dbg.timed(
|
|
29743
|
+
"libav-load",
|
|
29744
|
+
`load "${variant}" (threads=${wantThreads})`,
|
|
29745
|
+
5e3,
|
|
29746
|
+
() => loadVariantInner(variant, wantThreads)
|
|
29747
|
+
);
|
|
29748
|
+
}
|
|
29749
|
+
async function loadVariantInner(variant, wantThreads) {
|
|
29647
29750
|
const key = cacheKey(variant, wantThreads);
|
|
29648
29751
|
const base = `${libavBaseUrl()}/${variant}`;
|
|
29649
29752
|
const variantUrl = `${base}/libav-${variant}.mjs`;
|
|
29753
|
+
dbg.info("libav-load", `fetching ${variantUrl}`);
|
|
29650
29754
|
if (typeof fetch === "function") {
|
|
29651
29755
|
try {
|
|
29652
29756
|
const head = await fetch(variantUrl, { method: "GET", headers: { Range: "bytes=0-0" } });
|
|
@@ -29730,6 +29834,7 @@ function chain(message, err) {
|
|
|
29730
29834
|
var cache;
|
|
29731
29835
|
var init_libav_loader = __esm({
|
|
29732
29836
|
"src/strategies/fallback/libav-loader.ts"() {
|
|
29837
|
+
init_debug();
|
|
29733
29838
|
cache = /* @__PURE__ */ new Map();
|
|
29734
29839
|
}
|
|
29735
29840
|
});
|
|
@@ -29858,7 +29963,12 @@ function ffmpegToAvbridgeVideo(name) {
|
|
|
29858
29963
|
return "mpeg1";
|
|
29859
29964
|
case "theora":
|
|
29860
29965
|
return "theora";
|
|
29966
|
+
case "rv10":
|
|
29967
|
+
return "rv10";
|
|
29968
|
+
case "rv20":
|
|
29969
|
+
return "rv20";
|
|
29861
29970
|
case "rv30":
|
|
29971
|
+
return "rv30";
|
|
29862
29972
|
case "rv40":
|
|
29863
29973
|
return "rv40";
|
|
29864
29974
|
default:
|
|
@@ -29889,6 +29999,16 @@ function ffmpegToAvbridgeAudio(name) {
|
|
|
29889
29999
|
return "wmapro";
|
|
29890
30000
|
case "alac":
|
|
29891
30001
|
return "alac";
|
|
30002
|
+
case "cook":
|
|
30003
|
+
return "cook";
|
|
30004
|
+
case "ra_144":
|
|
30005
|
+
return "ra_144";
|
|
30006
|
+
case "ra_288":
|
|
30007
|
+
return "ra_288";
|
|
30008
|
+
case "sipr":
|
|
30009
|
+
return "sipr";
|
|
30010
|
+
case "atrac3":
|
|
30011
|
+
return "atrac3";
|
|
29892
30012
|
default:
|
|
29893
30013
|
return name;
|
|
29894
30014
|
}
|
|
@@ -31154,8 +31274,29 @@ var NATIVE_AUDIO_CODECS = /* @__PURE__ */ new Set([
|
|
|
31154
31274
|
"vorbis",
|
|
31155
31275
|
"flac"
|
|
31156
31276
|
]);
|
|
31157
|
-
var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
|
|
31158
|
-
|
|
31277
|
+
var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
|
|
31278
|
+
"wmv3",
|
|
31279
|
+
"vc1",
|
|
31280
|
+
"mpeg4",
|
|
31281
|
+
"rv10",
|
|
31282
|
+
"rv20",
|
|
31283
|
+
"rv30",
|
|
31284
|
+
"rv40",
|
|
31285
|
+
"mpeg2",
|
|
31286
|
+
"mpeg1",
|
|
31287
|
+
"theora"
|
|
31288
|
+
]);
|
|
31289
|
+
var FALLBACK_AUDIO_CODECS = /* @__PURE__ */ new Set([
|
|
31290
|
+
"wmav2",
|
|
31291
|
+
"wmapro",
|
|
31292
|
+
"ac3",
|
|
31293
|
+
"eac3",
|
|
31294
|
+
"cook",
|
|
31295
|
+
"ra_144",
|
|
31296
|
+
"ra_288",
|
|
31297
|
+
"sipr",
|
|
31298
|
+
"atrac3"
|
|
31299
|
+
]);
|
|
31159
31300
|
var NATIVE_CONTAINERS = /* @__PURE__ */ new Set([
|
|
31160
31301
|
"mp4",
|
|
31161
31302
|
"mov",
|
|
@@ -32906,6 +33047,9 @@ async function startDecoder(opts) {
|
|
|
32906
33047
|
let packetsRead = 0;
|
|
32907
33048
|
let videoFramesDecoded = 0;
|
|
32908
33049
|
let audioFramesDecoded = 0;
|
|
33050
|
+
let watchdogFirstFrameMs = 0;
|
|
33051
|
+
let watchdogSlowSinceMs = 0;
|
|
33052
|
+
let watchdogWarned = false;
|
|
32909
33053
|
let syntheticVideoUs = 0;
|
|
32910
33054
|
let syntheticAudioUs = 0;
|
|
32911
33055
|
const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);
|
|
@@ -32917,7 +33061,7 @@ async function startDecoder(opts) {
|
|
|
32917
33061
|
let packets;
|
|
32918
33062
|
try {
|
|
32919
33063
|
[readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {
|
|
32920
|
-
limit:
|
|
33064
|
+
limit: 64 * 1024
|
|
32921
33065
|
});
|
|
32922
33066
|
} catch (err) {
|
|
32923
33067
|
console.error("[avbridge] ff_read_frame_multi failed:", err);
|
|
@@ -32934,6 +33078,28 @@ async function startDecoder(opts) {
|
|
|
32934
33078
|
await decodeAudioBatch(audioPackets, myToken);
|
|
32935
33079
|
}
|
|
32936
33080
|
packetsRead += (videoPackets?.length ?? 0) + (audioPackets?.length ?? 0);
|
|
33081
|
+
if (videoFramesDecoded > 0) {
|
|
33082
|
+
if (watchdogFirstFrameMs === 0) {
|
|
33083
|
+
watchdogFirstFrameMs = performance.now();
|
|
33084
|
+
}
|
|
33085
|
+
const elapsedSinceFirst = (performance.now() - watchdogFirstFrameMs) / 1e3;
|
|
33086
|
+
if (elapsedSinceFirst > 1 && !watchdogWarned) {
|
|
33087
|
+
const expectedFrames = elapsedSinceFirst * videoFps;
|
|
33088
|
+
const ratio = videoFramesDecoded / expectedFrames;
|
|
33089
|
+
if (ratio < 0.6) {
|
|
33090
|
+
if (watchdogSlowSinceMs === 0) watchdogSlowSinceMs = performance.now();
|
|
33091
|
+
if ((performance.now() - watchdogSlowSinceMs) / 1e3 > 5) {
|
|
33092
|
+
watchdogWarned = true;
|
|
33093
|
+
console.warn(
|
|
33094
|
+
"[avbridge:decode-rate]",
|
|
33095
|
+
`decoder is running slower than realtime: ${videoFramesDecoded} frames in ${elapsedSinceFirst.toFixed(1)}s (${(videoFramesDecoded / elapsedSinceFirst).toFixed(1)} fps vs ${videoFps} fps source \u2014 ${(ratio * 100).toFixed(0)}% of realtime). Playback will stutter. Typical causes: software decode of a codec with no WebCodecs support (rv40, mpeg4 @ 720p+, wmv3), or a resolution too large for single-threaded WASM to keep up with.`
|
|
33096
|
+
);
|
|
33097
|
+
}
|
|
33098
|
+
} else {
|
|
33099
|
+
watchdogSlowSinceMs = 0;
|
|
33100
|
+
}
|
|
33101
|
+
}
|
|
33102
|
+
}
|
|
32937
33103
|
while (!destroyed && myToken === pumpToken && (opts.audio.bufferAhead() > 2 || opts.renderer.queueDepth() >= opts.renderer.queueHighWater)) {
|
|
32938
33104
|
await new Promise((r) => setTimeout(r, 50));
|
|
32939
33105
|
}
|
|
@@ -33260,8 +33426,9 @@ async function loadBridge2() {
|
|
|
33260
33426
|
}
|
|
33261
33427
|
|
|
33262
33428
|
// src/strategies/fallback/index.ts
|
|
33263
|
-
|
|
33264
|
-
var
|
|
33429
|
+
init_debug();
|
|
33430
|
+
var READY_AUDIO_BUFFER_SECONDS2 = 0.04;
|
|
33431
|
+
var READY_TIMEOUT_SECONDS2 = 3;
|
|
33265
33432
|
async function createFallbackSession(ctx, target) {
|
|
33266
33433
|
const { normalizeSource: normalizeSource2 } = await Promise.resolve().then(() => (init_source(), source_exports));
|
|
33267
33434
|
const source = await normalizeSource2(ctx.source);
|
|
@@ -33297,12 +33464,26 @@ async function createFallbackSession(ctx, target) {
|
|
|
33297
33464
|
}
|
|
33298
33465
|
async function waitForBuffer() {
|
|
33299
33466
|
const start = performance.now();
|
|
33467
|
+
dbg.info(
|
|
33468
|
+
"cold-start",
|
|
33469
|
+
`gate entry: need audio >= ${READY_AUDIO_BUFFER_SECONDS2 * 1e3}ms + 1 frame`
|
|
33470
|
+
);
|
|
33300
33471
|
while (true) {
|
|
33301
|
-
const
|
|
33302
|
-
|
|
33472
|
+
const audioAhead = audio.isNoAudio() ? Infinity : audio.bufferAhead();
|
|
33473
|
+
const audioReady = audio.isNoAudio() || audioAhead >= READY_AUDIO_BUFFER_SECONDS2;
|
|
33474
|
+
const hasFrames = renderer.hasFrames();
|
|
33475
|
+
if (audioReady && hasFrames) {
|
|
33476
|
+
dbg.info(
|
|
33477
|
+
"cold-start",
|
|
33478
|
+
`gate satisfied in ${(performance.now() - start).toFixed(0)}ms (audio=${(audioAhead * 1e3).toFixed(0)}ms, frames=${renderer.queueDepth()})`
|
|
33479
|
+
);
|
|
33303
33480
|
return;
|
|
33304
33481
|
}
|
|
33305
33482
|
if ((performance.now() - start) / 1e3 > READY_TIMEOUT_SECONDS2) {
|
|
33483
|
+
dbg.diag(
|
|
33484
|
+
"cold-start",
|
|
33485
|
+
`gate TIMEOUT after ${READY_TIMEOUT_SECONDS2}s \u2014 audio=${(audioAhead * 1e3).toFixed(0)}ms (needed ${READY_AUDIO_BUFFER_SECONDS2 * 1e3}ms), frames=${renderer.queueDepth()} (needed \u22651). Software decoder is producing output slower than realtime \u2014 playback will stutter. Check getDiagnostics().runtime for the decode rate.`
|
|
33486
|
+
);
|
|
33306
33487
|
return;
|
|
33307
33488
|
}
|
|
33308
33489
|
await new Promise((r) => setTimeout(r, 50));
|
|
@@ -33413,8 +33594,8 @@ function convertTiming(line) {
|
|
|
33413
33594
|
line.trim()
|
|
33414
33595
|
);
|
|
33415
33596
|
if (!m) return null;
|
|
33416
|
-
const
|
|
33417
|
-
return `${
|
|
33597
|
+
const fmt2 = (h, mm, s, ms) => `${h.padStart(2, "0")}:${mm}:${s}.${ms.padEnd(3, "0").slice(0, 3)}`;
|
|
33598
|
+
return `${fmt2(m[1], m[2], m[3], m[4])} --> ${fmt2(m[5], m[6], m[7], m[8])}${m[9] ?? ""}`;
|
|
33418
33599
|
}
|
|
33419
33600
|
|
|
33420
33601
|
// src/subtitles/vtt.ts
|
|
@@ -33500,6 +33681,7 @@ async function attachSubtitleTracks(video, tracks, bag, onError) {
|
|
|
33500
33681
|
}
|
|
33501
33682
|
|
|
33502
33683
|
// src/player.ts
|
|
33684
|
+
init_debug();
|
|
33503
33685
|
var UnifiedPlayer = class _UnifiedPlayer {
|
|
33504
33686
|
/**
|
|
33505
33687
|
* @internal Use {@link createPlayer} or {@link UnifiedPlayer.create} instead.
|
|
@@ -33547,8 +33729,14 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
33547
33729
|
return player;
|
|
33548
33730
|
}
|
|
33549
33731
|
async bootstrap() {
|
|
33732
|
+
const bootstrapStart = performance.now();
|
|
33550
33733
|
try {
|
|
33551
|
-
|
|
33734
|
+
dbg.info("bootstrap", "start");
|
|
33735
|
+
const ctx = await dbg.timed("probe", "probe", 3e3, () => probe(this.options.source));
|
|
33736
|
+
dbg.info(
|
|
33737
|
+
"probe",
|
|
33738
|
+
`container=${ctx.container} video=${ctx.videoTracks[0]?.codec ?? "-"} audio=${ctx.audioTracks[0]?.codec ?? "-"} probedBy=${ctx.probedBy}`
|
|
33739
|
+
);
|
|
33552
33740
|
this.diag.recordProbe(ctx);
|
|
33553
33741
|
this.mediaContext = ctx;
|
|
33554
33742
|
if (this.options.subtitles) {
|
|
@@ -33574,6 +33762,10 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
33574
33762
|
}
|
|
33575
33763
|
}
|
|
33576
33764
|
const decision = this.options.initialStrategy ? buildInitialDecision(this.options.initialStrategy, ctx) : classifyContext(ctx);
|
|
33765
|
+
dbg.info(
|
|
33766
|
+
"classify",
|
|
33767
|
+
`strategy=${decision.strategy} class=${decision.class} reason="${decision.reason}"` + (decision.fallbackChain ? ` fallback=${decision.fallbackChain.join("\u2192")}` : "")
|
|
33768
|
+
);
|
|
33577
33769
|
this.classification = decision;
|
|
33578
33770
|
this.diag.recordClassification(decision);
|
|
33579
33771
|
this.emitter.emitSticky("strategy", {
|
|
@@ -33599,6 +33791,14 @@ var UnifiedPlayer = class _UnifiedPlayer {
|
|
|
33599
33791
|
this.startTimeupdateLoop();
|
|
33600
33792
|
this.options.target.addEventListener("ended", () => this.emitter.emit("ended", void 0));
|
|
33601
33793
|
this.emitter.emitSticky("ready", void 0);
|
|
33794
|
+
const bootstrapElapsed = performance.now() - bootstrapStart;
|
|
33795
|
+
dbg.info("bootstrap", `ready in ${bootstrapElapsed.toFixed(0)}ms`);
|
|
33796
|
+
if (bootstrapElapsed > 5e3) {
|
|
33797
|
+
console.warn(
|
|
33798
|
+
"[avbridge:bootstrap]",
|
|
33799
|
+
`total bootstrap time ${bootstrapElapsed.toFixed(0)}ms \u2014 unusually slow. Enable globalThis.AVBRIDGE_DEBUG for a per-phase breakdown.`
|
|
33800
|
+
);
|
|
33801
|
+
}
|
|
33602
33802
|
} catch (err) {
|
|
33603
33803
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
33604
33804
|
this.diag.recordError(e);
|