@mebius-io/web 0.5.1 → 0.5.3

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/dist/index.cjs CHANGED
@@ -471,6 +471,7 @@ var LIVE_FLV_CONFIG = {
471
471
  var MAX_DRIFT_S = 2;
472
472
  var EDGE_MARGIN_S = 0.4;
473
473
  var AUDIO_RETRY_MS = 2500;
474
+ var ESTIMATED_LATENCY_MS = 3e3;
474
475
  function stalledWithData(video, ms) {
475
476
  if (video.currentTime > 0) return Promise.resolve(false);
476
477
  return new Promise((resolve) => {
@@ -599,6 +600,15 @@ var FlvViewTransport = class {
599
600
  }
600
601
  return { bitrateKbps, framesPerSecond, latencyMs: void 0 };
601
602
  }
603
+ /**
604
+ * Estimate only — see {@link ESTIMATED_LATENCY_MS}. Without this, captions
605
+ * never render on the FLV route at all: {@link MebiusCaptions} withholds
606
+ * every segment until the playhead reaches its `epochMs`, and a transport
607
+ * returning `null` here means the playhead comparison never runs.
608
+ */
609
+ playheadEpochMs() {
610
+ return Date.now() - ESTIMATED_LATENCY_MS;
611
+ }
602
612
  };
603
613
 
604
614
  // src/internal/transport.ts
@@ -830,6 +840,7 @@ function normalize(c, fallback) {
830
840
  // src/captions.ts
831
841
  var TICK_MS = 100;
832
842
  var STALE_MS = 5e3;
843
+ var MAX_QUEUE_MS = 4e3;
833
844
  var MebiusCaptions = class extends TypedEmitter {
834
845
  /** @internal */
835
846
  constructor(signaling, player, opts) {
@@ -871,22 +882,27 @@ var MebiusCaptions = class extends TypedEmitter {
871
882
  if (frame.type !== "caption" || !frame.segmentId) return;
872
883
  const prev = this.pending.get(frame.segmentId);
873
884
  if (prev && (frame.rev ?? 0) < (prev.rev ?? 0)) return;
885
+ frame.receivedAtMs = Date.now();
874
886
  this.pending.set(frame.segmentId, frame);
875
887
  }
876
888
  tick() {
877
889
  const now = this.player.currentEpochMs();
878
- if (now == null) return;
879
890
  for (const [id, frame] of this.pending) {
880
891
  const due = frame.epochMs ?? 0;
881
- if (due > now) continue;
882
- if (due < now - STALE_MS) {
892
+ const waitedMs = Date.now() - (frame.receivedAtMs ?? 0);
893
+ const dueNow = now == null ? true : due <= now;
894
+ if (!dueNow) {
895
+ if (waitedMs < MAX_QUEUE_MS) continue;
896
+ }
897
+ if (waitedMs > STALE_MS && this.shown.has(id)) {
883
898
  this.pending.delete(id);
884
- if (this.shown.delete(id)) this.emit("cleared", { segmentId: id });
899
+ this.shown.delete(id);
900
+ this.emit("cleared", { segmentId: id });
885
901
  continue;
886
902
  }
903
+ if (this.shown.has(id) && frame.state === "final") continue;
887
904
  this.shown.add(id);
888
905
  this.emit("segment", toSegment(id, frame, this.opts.lang));
889
- if (frame.state === "final") this.pending.delete(id);
890
906
  }
891
907
  }
892
908
  };