@mebius-io/web 0.4.1 → 0.4.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/README.md +2 -2
- package/dist/index.cjs +93 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +93 -15
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +93 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.global.js
CHANGED
|
@@ -42705,6 +42705,20 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42705
42705
|
};
|
|
42706
42706
|
|
|
42707
42707
|
// src/internal/publish-transport.ts
|
|
42708
|
+
function preferH264(pc) {
|
|
42709
|
+
const caps = RTCRtpSender.getCapabilities?.("video");
|
|
42710
|
+
if (!caps?.codecs) return;
|
|
42711
|
+
const h264 = caps.codecs.filter((c) => c.mimeType.toLowerCase() === "video/h264");
|
|
42712
|
+
if (h264.length === 0) return;
|
|
42713
|
+
const rest = caps.codecs.filter((c) => c.mimeType.toLowerCase() !== "video/h264");
|
|
42714
|
+
for (const tr of pc.getTransceivers()) {
|
|
42715
|
+
if (tr.sender.track?.kind !== "video") continue;
|
|
42716
|
+
try {
|
|
42717
|
+
tr.setCodecPreferences?.([...h264, ...rest]);
|
|
42718
|
+
} catch {
|
|
42719
|
+
}
|
|
42720
|
+
}
|
|
42721
|
+
}
|
|
42708
42722
|
var WhipPublishTransport = class {
|
|
42709
42723
|
constructor(signaling) {
|
|
42710
42724
|
this.signaling = signaling;
|
|
@@ -42717,6 +42731,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42717
42731
|
for (const track of stream.getTracks()) {
|
|
42718
42732
|
pc.addTrack(track, stream);
|
|
42719
42733
|
}
|
|
42734
|
+
preferH264(pc);
|
|
42720
42735
|
const offer = await pc.createOffer();
|
|
42721
42736
|
await pc.setLocalDescription(offer);
|
|
42722
42737
|
await waitForIceGathering(pc);
|
|
@@ -42883,6 +42898,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42883
42898
|
this.video = null;
|
|
42884
42899
|
this.endedCb = null;
|
|
42885
42900
|
this.bufferingCb = null;
|
|
42901
|
+
/** Aborts this attempt's element listeners; see start(). */
|
|
42902
|
+
this.listeners = null;
|
|
42886
42903
|
/** True when playback only started because the element had to be muted. */
|
|
42887
42904
|
this.mutedByPolicy = false;
|
|
42888
42905
|
}
|
|
@@ -42895,8 +42912,10 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42895
42912
|
async start(streamId, video) {
|
|
42896
42913
|
this.video = video;
|
|
42897
42914
|
const url = this.deliveryPath ? this.signaling.deliveryUrl(this.deliveryPath) : this.signaling.scalePlaylistUrl(streamId);
|
|
42898
|
-
|
|
42899
|
-
|
|
42915
|
+
this.listeners = new AbortController();
|
|
42916
|
+
const { signal } = this.listeners;
|
|
42917
|
+
video.addEventListener("ended", () => this.endedCb?.(), { signal });
|
|
42918
|
+
video.addEventListener("waiting", () => this.bufferingCb?.(), { signal });
|
|
42900
42919
|
if (video.canPlayType("application/vnd.apple.mpegurl")) {
|
|
42901
42920
|
video.src = url;
|
|
42902
42921
|
this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
|
|
@@ -42912,7 +42931,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42912
42931
|
if (!Hls2.isSupported()) {
|
|
42913
42932
|
throw mebiusError("CONNECTION_FAILED", "Scale playback is not supported in this browser.");
|
|
42914
42933
|
}
|
|
42915
|
-
const hls = new Hls2();
|
|
42934
|
+
const hls = new Hls2({ maxLiveSyncPlaybackRate: 1.5 });
|
|
42916
42935
|
this.hls = hls;
|
|
42917
42936
|
hls.on(Hls2.Events.ERROR, (_evt, data) => {
|
|
42918
42937
|
if (data.fatal) this.bufferingCb?.();
|
|
@@ -42922,6 +42941,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42922
42941
|
this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
|
|
42923
42942
|
}
|
|
42924
42943
|
async stop() {
|
|
42944
|
+
this.listeners?.abort();
|
|
42945
|
+
this.listeners = null;
|
|
42925
42946
|
this.hls?.destroy();
|
|
42926
42947
|
this.hls = null;
|
|
42927
42948
|
if (this.video) {
|
|
@@ -42941,6 +42962,40 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42941
42962
|
};
|
|
42942
42963
|
|
|
42943
42964
|
// src/internal/balanced-view-transport.ts
|
|
42965
|
+
var LIVE_FLV_CONFIG = {
|
|
42966
|
+
enableStashBuffer: false,
|
|
42967
|
+
stashInitialSize: 128,
|
|
42968
|
+
lazyLoad: false,
|
|
42969
|
+
autoCleanupSourceBuffer: true,
|
|
42970
|
+
autoCleanupMaxBackwardDuration: 30,
|
|
42971
|
+
autoCleanupMinBackwardDuration: 10,
|
|
42972
|
+
reuseRedirectedURL: true
|
|
42973
|
+
};
|
|
42974
|
+
var MAX_DRIFT_S = 2;
|
|
42975
|
+
var EDGE_MARGIN_S = 0.4;
|
|
42976
|
+
var AUDIO_RETRY_MS = 2500;
|
|
42977
|
+
function stalledAtZero(video, ms) {
|
|
42978
|
+
if (video.currentTime > 0) return Promise.resolve(false);
|
|
42979
|
+
return new Promise((resolve) => {
|
|
42980
|
+
const done = (stalled) => {
|
|
42981
|
+
clearTimeout(timer);
|
|
42982
|
+
video.removeEventListener("timeupdate", onTime);
|
|
42983
|
+
resolve(stalled);
|
|
42984
|
+
};
|
|
42985
|
+
const onTime = () => {
|
|
42986
|
+
if (video.currentTime > 0) done(false);
|
|
42987
|
+
};
|
|
42988
|
+
const timer = setTimeout(() => done(true), ms);
|
|
42989
|
+
video.addEventListener("timeupdate", onTime);
|
|
42990
|
+
});
|
|
42991
|
+
}
|
|
42992
|
+
function chaseLiveEdge(video) {
|
|
42993
|
+
const ranges = video.buffered;
|
|
42994
|
+
if (ranges.length === 0) return;
|
|
42995
|
+
const edge = ranges.end(ranges.length - 1);
|
|
42996
|
+
if (edge - video.currentTime <= MAX_DRIFT_S) return;
|
|
42997
|
+
video.currentTime = edge - EDGE_MARGIN_S;
|
|
42998
|
+
}
|
|
42944
42999
|
var FlvViewTransport = class {
|
|
42945
43000
|
constructor(signaling, deliveryPath) {
|
|
42946
43001
|
this.signaling = signaling;
|
|
@@ -42949,6 +43004,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42949
43004
|
this.video = null;
|
|
42950
43005
|
this.endedCb = null;
|
|
42951
43006
|
this.bufferingCb = null;
|
|
43007
|
+
/** Aborts this attempt's element listeners; see start(). */
|
|
43008
|
+
this.listeners = null;
|
|
42952
43009
|
/** True when playback only started because the element had to be muted. */
|
|
42953
43010
|
this.mutedByPolicy = false;
|
|
42954
43011
|
}
|
|
@@ -42961,8 +43018,11 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42961
43018
|
async start(_streamId, video) {
|
|
42962
43019
|
this.video = video;
|
|
42963
43020
|
const url = this.signaling.deliveryUrl(this.deliveryPath);
|
|
42964
|
-
|
|
42965
|
-
|
|
43021
|
+
this.listeners = new AbortController();
|
|
43022
|
+
const { signal } = this.listeners;
|
|
43023
|
+
video.addEventListener("ended", () => this.endedCb?.(), { signal });
|
|
43024
|
+
video.addEventListener("waiting", () => this.bufferingCb?.(), { signal });
|
|
43025
|
+
video.addEventListener("timeupdate", () => chaseLiveEdge(video), { signal });
|
|
42966
43026
|
let mod;
|
|
42967
43027
|
try {
|
|
42968
43028
|
mod = await Promise.resolve().then(() => __toESM(require_flv(), 1));
|
|
@@ -42973,20 +43033,38 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
42973
43033
|
if (!flvjs.isSupported()) {
|
|
42974
43034
|
throw mebiusError("CONNECTION_FAILED", "Balanced playback is not supported in this browser.");
|
|
42975
43035
|
}
|
|
42976
|
-
|
|
43036
|
+
this.attachPlayer(flvjs, video, url, true);
|
|
43037
|
+
const firstPlay = playWithAutoplayFallback(video);
|
|
43038
|
+
firstPlay.catch(() => void 0);
|
|
43039
|
+
if (await stalledAtZero(video, AUDIO_RETRY_MS)) {
|
|
43040
|
+
this.teardownPlayer();
|
|
43041
|
+
this.attachPlayer(flvjs, video, url, false);
|
|
43042
|
+
this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
|
|
43043
|
+
return;
|
|
43044
|
+
}
|
|
43045
|
+
this.mutedByPolicy = (await firstPlay).mutedByPolicy;
|
|
43046
|
+
}
|
|
43047
|
+
attachPlayer(flvjs, video, url, withAudio) {
|
|
43048
|
+
const player = flvjs.createPlayer(
|
|
43049
|
+
{ type: "flv", url, isLive: true, ...withAudio ? {} : { hasAudio: false } },
|
|
43050
|
+
LIVE_FLV_CONFIG
|
|
43051
|
+
);
|
|
42977
43052
|
this.player = player;
|
|
42978
43053
|
player.on(flvjs.Events.ERROR ?? "error", () => this.bufferingCb?.());
|
|
42979
43054
|
player.attachMediaElement(video);
|
|
42980
43055
|
player.load();
|
|
42981
|
-
|
|
43056
|
+
}
|
|
43057
|
+
teardownPlayer() {
|
|
43058
|
+
if (!this.player) return;
|
|
43059
|
+
this.player.unload();
|
|
43060
|
+
this.player.detachMediaElement();
|
|
43061
|
+
this.player.destroy();
|
|
43062
|
+
this.player = null;
|
|
42982
43063
|
}
|
|
42983
43064
|
async stop() {
|
|
42984
|
-
|
|
42985
|
-
|
|
42986
|
-
|
|
42987
|
-
this.player.destroy();
|
|
42988
|
-
this.player = null;
|
|
42989
|
-
}
|
|
43065
|
+
this.listeners?.abort();
|
|
43066
|
+
this.listeners = null;
|
|
43067
|
+
this.teardownPlayer();
|
|
42990
43068
|
if (this.video) {
|
|
42991
43069
|
this.video.removeAttribute("src");
|
|
42992
43070
|
this.video.load();
|
|
@@ -43035,7 +43113,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
43035
43113
|
}
|
|
43036
43114
|
|
|
43037
43115
|
// src/internal/telemetry.ts
|
|
43038
|
-
var SDK_VERSION = "web/0.4.
|
|
43116
|
+
var SDK_VERSION = "web/0.4.2";
|
|
43039
43117
|
var FLUSH_INTERVAL_MS = 15e3;
|
|
43040
43118
|
var MAX_BATCH = 64;
|
|
43041
43119
|
function describeDevice() {
|
|
@@ -43095,7 +43173,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
|
|
|
43095
43173
|
if (beacon && typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
43096
43174
|
const url = `${this.target.url}${this.target.url.includes("?") ? "&" : "?"}token=${encodeURIComponent(this.target.token)}`;
|
|
43097
43175
|
try {
|
|
43098
|
-
navigator.sendBeacon(url, new Blob([body], { type: "
|
|
43176
|
+
navigator.sendBeacon(url, new Blob([body], { type: "text/plain" }));
|
|
43099
43177
|
} catch {
|
|
43100
43178
|
}
|
|
43101
43179
|
return;
|