@mebius-io/web 0.4.0 → 0.4.1

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.
@@ -42764,6 +42764,28 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42764
42764
  }
42765
42765
  };
42766
42766
 
42767
+ // src/internal/autoplay.ts
42768
+ function isAutoplayBlocked(e) {
42769
+ return typeof e === "object" && e !== null && e.name === "NotAllowedError";
42770
+ }
42771
+ async function playWithAutoplayFallback(video) {
42772
+ video.playsInline = true;
42773
+ try {
42774
+ await video.play();
42775
+ return { mutedByPolicy: false };
42776
+ } catch (e) {
42777
+ if (!isAutoplayBlocked(e) || video.muted) throw e;
42778
+ video.muted = true;
42779
+ await video.play();
42780
+ return { mutedByPolicy: true };
42781
+ }
42782
+ }
42783
+ function resetVideoElement(video) {
42784
+ video.srcObject = null;
42785
+ video.removeAttribute("src");
42786
+ video.load();
42787
+ }
42788
+
42767
42789
  // src/internal/ll-view-transport.ts
42768
42790
  var WhepViewTransport = class {
42769
42791
  constructor(signaling) {
@@ -42772,6 +42794,10 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42772
42794
  this.resourceUrl = null;
42773
42795
  this.endedCb = null;
42774
42796
  this.bufferingCb = null;
42797
+ /** Element this route attached a MediaStream to, so stop() can release it. */
42798
+ this.video = null;
42799
+ /** True when playback only started because the element had to be muted. */
42800
+ this.mutedByPolicy = false;
42775
42801
  }
42776
42802
  onEnded(cb) {
42777
42803
  this.endedCb = cb;
@@ -42780,6 +42806,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42780
42806
  this.bufferingCb = cb;
42781
42807
  }
42782
42808
  async start(streamId, video) {
42809
+ this.video = video;
42783
42810
  const pc = new RTCPeerConnection(DEFAULT_RTC_CONFIG);
42784
42811
  this.pc = pc;
42785
42812
  const remote = new MediaStream();
@@ -42788,7 +42815,9 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42788
42815
  pc.ontrack = (ev) => {
42789
42816
  remote.addTrack(ev.track);
42790
42817
  video.srcObject = remote;
42791
- void video.play().catch(() => {
42818
+ void playWithAutoplayFallback(video).then((o) => {
42819
+ this.mutedByPolicy = o.mutedByPolicy;
42820
+ }).catch(() => {
42792
42821
  });
42793
42822
  };
42794
42823
  pc.onconnectionstatechange = () => {
@@ -42815,6 +42844,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42815
42844
  this.resourceUrl = null;
42816
42845
  this.pc?.close();
42817
42846
  this.pc = null;
42847
+ if (this.video) resetVideoElement(this.video);
42848
+ this.video = null;
42818
42849
  }
42819
42850
  async getStats() {
42820
42851
  if (!this.pc) return null;
@@ -42852,6 +42883,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42852
42883
  this.video = null;
42853
42884
  this.endedCb = null;
42854
42885
  this.bufferingCb = null;
42886
+ /** True when playback only started because the element had to be muted. */
42887
+ this.mutedByPolicy = false;
42855
42888
  }
42856
42889
  onEnded(cb) {
42857
42890
  this.endedCb = cb;
@@ -42866,7 +42899,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42866
42899
  video.addEventListener("waiting", () => this.bufferingCb?.());
42867
42900
  if (video.canPlayType("application/vnd.apple.mpegurl")) {
42868
42901
  video.src = url;
42869
- await video.play().catch(() => void 0);
42902
+ this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
42870
42903
  return;
42871
42904
  }
42872
42905
  let mod;
@@ -42879,14 +42912,14 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42879
42912
  if (!Hls2.isSupported()) {
42880
42913
  throw mebiusError("CONNECTION_FAILED", "Scale playback is not supported in this browser.");
42881
42914
  }
42882
- const hls = new Hls2({ lowLatencyMode: true });
42915
+ const hls = new Hls2();
42883
42916
  this.hls = hls;
42884
42917
  hls.on(Hls2.Events.ERROR, (_evt, data) => {
42885
42918
  if (data.fatal) this.bufferingCb?.();
42886
42919
  });
42887
42920
  hls.loadSource(url);
42888
42921
  hls.attachMedia(video);
42889
- await video.play().catch(() => void 0);
42922
+ this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
42890
42923
  }
42891
42924
  async stop() {
42892
42925
  this.hls?.destroy();
@@ -42916,6 +42949,8 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42916
42949
  this.video = null;
42917
42950
  this.endedCb = null;
42918
42951
  this.bufferingCb = null;
42952
+ /** True when playback only started because the element had to be muted. */
42953
+ this.mutedByPolicy = false;
42919
42954
  }
42920
42955
  onEnded(cb) {
42921
42956
  this.endedCb = cb;
@@ -42943,7 +42978,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
42943
42978
  player.on(flvjs.Events.ERROR ?? "error", () => this.bufferingCb?.());
42944
42979
  player.attachMediaElement(video);
42945
42980
  player.load();
42946
- await Promise.resolve(player.play()).catch(() => void 0);
42981
+ this.mutedByPolicy = (await playWithAutoplayFallback(video)).mutedByPolicy;
42947
42982
  }
42948
42983
  async stop() {
42949
42984
  if (this.player) {
@@ -43000,7 +43035,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
43000
43035
  }
43001
43036
 
43002
43037
  // src/internal/telemetry.ts
43003
- var SDK_VERSION = "web/0.4.0";
43038
+ var SDK_VERSION = "web/0.4.1";
43004
43039
  var FLUSH_INTERVAL_MS = 15e3;
43005
43040
  var MAX_BATCH = 64;
43006
43041
  function describeDevice() {
@@ -43216,6 +43251,7 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
43216
43251
  let lastError = null;
43217
43252
  for (const candidate of this.candidates) {
43218
43253
  try {
43254
+ resetVideoElement(video);
43219
43255
  this.attach(candidate);
43220
43256
  await candidate.start(streamId, video);
43221
43257
  if (await hasFirstFrame(video)) {