@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.js CHANGED
@@ -429,6 +429,7 @@ var LIVE_FLV_CONFIG = {
429
429
  var MAX_DRIFT_S = 2;
430
430
  var EDGE_MARGIN_S = 0.4;
431
431
  var AUDIO_RETRY_MS = 2500;
432
+ var ESTIMATED_LATENCY_MS = 3e3;
432
433
  function stalledWithData(video, ms) {
433
434
  if (video.currentTime > 0) return Promise.resolve(false);
434
435
  return new Promise((resolve) => {
@@ -557,6 +558,15 @@ var FlvViewTransport = class {
557
558
  }
558
559
  return { bitrateKbps, framesPerSecond, latencyMs: void 0 };
559
560
  }
561
+ /**
562
+ * Estimate only — see {@link ESTIMATED_LATENCY_MS}. Without this, captions
563
+ * never render on the FLV route at all: {@link MebiusCaptions} withholds
564
+ * every segment until the playhead reaches its `epochMs`, and a transport
565
+ * returning `null` here means the playhead comparison never runs.
566
+ */
567
+ playheadEpochMs() {
568
+ return Date.now() - ESTIMATED_LATENCY_MS;
569
+ }
560
570
  };
561
571
 
562
572
  // src/internal/transport.ts
@@ -788,6 +798,7 @@ function normalize(c, fallback) {
788
798
  // src/captions.ts
789
799
  var TICK_MS = 100;
790
800
  var STALE_MS = 5e3;
801
+ var MAX_QUEUE_MS = 4e3;
791
802
  var MebiusCaptions = class extends TypedEmitter {
792
803
  /** @internal */
793
804
  constructor(signaling, player, opts) {
@@ -829,22 +840,27 @@ var MebiusCaptions = class extends TypedEmitter {
829
840
  if (frame.type !== "caption" || !frame.segmentId) return;
830
841
  const prev = this.pending.get(frame.segmentId);
831
842
  if (prev && (frame.rev ?? 0) < (prev.rev ?? 0)) return;
843
+ frame.receivedAtMs = Date.now();
832
844
  this.pending.set(frame.segmentId, frame);
833
845
  }
834
846
  tick() {
835
847
  const now = this.player.currentEpochMs();
836
- if (now == null) return;
837
848
  for (const [id, frame] of this.pending) {
838
849
  const due = frame.epochMs ?? 0;
839
- if (due > now) continue;
840
- if (due < now - STALE_MS) {
850
+ const waitedMs = Date.now() - (frame.receivedAtMs ?? 0);
851
+ const dueNow = now == null ? true : due <= now;
852
+ if (!dueNow) {
853
+ if (waitedMs < MAX_QUEUE_MS) continue;
854
+ }
855
+ if (waitedMs > STALE_MS && this.shown.has(id)) {
841
856
  this.pending.delete(id);
842
- if (this.shown.delete(id)) this.emit("cleared", { segmentId: id });
857
+ this.shown.delete(id);
858
+ this.emit("cleared", { segmentId: id });
843
859
  continue;
844
860
  }
861
+ if (this.shown.has(id) && frame.state === "final") continue;
845
862
  this.shown.add(id);
846
863
  this.emit("segment", toSegment(id, frame, this.opts.lang));
847
- if (frame.state === "final") this.pending.delete(id);
848
864
  }
849
865
  }
850
866
  };