@mebius-io/web 0.1.2 → 0.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.
@@ -33214,13 +33214,13 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33214
33214
  await waitForIceGathering(pc);
33215
33215
  const localSdp = pc.localDescription?.sdp;
33216
33216
  if (!localSdp) throw mebiusError("CONNECTION_FAILED", "Failed to create a local session.");
33217
- const { answerSdp, resourceUrl } = await this.signaling.exchangeSdp(
33218
- "whip",
33217
+ const { answer, resourceUrl } = await this.signaling.exchangeSession(
33218
+ "publish",
33219
33219
  streamId,
33220
33220
  localSdp
33221
33221
  );
33222
33222
  this.resourceUrl = resourceUrl;
33223
- await pc.setRemoteDescription({ type: "answer", sdp: answerSdp });
33223
+ await pc.setRemoteDescription({ type: "answer", sdp: answer });
33224
33224
  }
33225
33225
  async replaceVideoTrack(track) {
33226
33226
  const sender = this.pc?.getSenders().find((s) => s.track?.kind === "video");
@@ -33294,13 +33294,13 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33294
33294
  await waitForIceGathering(pc);
33295
33295
  const localSdp = pc.localDescription?.sdp;
33296
33296
  if (!localSdp) throw mebiusError("CONNECTION_FAILED", "Failed to create a local session.");
33297
- const { answerSdp, resourceUrl } = await this.signaling.exchangeSdp(
33298
- "whep",
33297
+ const { answer, resourceUrl } = await this.signaling.exchangeSession(
33298
+ "view",
33299
33299
  streamId,
33300
33300
  localSdp
33301
33301
  );
33302
33302
  this.resourceUrl = resourceUrl;
33303
- await pc.setRemoteDescription({ type: "answer", sdp: answerSdp });
33303
+ await pc.setRemoteDescription({ type: "answer", sdp: answer });
33304
33304
  }
33305
33305
  async stop() {
33306
33306
  await this.signaling.deleteResource(this.resourceUrl);
@@ -33329,70 +33329,6 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33329
33329
  }
33330
33330
  };
33331
33331
 
33332
- // src/internal/balanced-view-transport.ts
33333
- var FlvViewTransport = class {
33334
- constructor(signaling) {
33335
- this.signaling = signaling;
33336
- this.player = null;
33337
- this.video = null;
33338
- this.endedCb = null;
33339
- this.bufferingCb = null;
33340
- }
33341
- onEnded(cb) {
33342
- this.endedCb = cb;
33343
- }
33344
- onBuffering(cb) {
33345
- this.bufferingCb = cb;
33346
- }
33347
- async start(streamId, video) {
33348
- this.video = video;
33349
- const url = this.signaling.balancedStreamUrl(streamId);
33350
- video.addEventListener("ended", () => this.endedCb?.());
33351
- video.addEventListener("waiting", () => this.bufferingCb?.());
33352
- let mod;
33353
- try {
33354
- const spec = "flv.js";
33355
- mod = await import(
33356
- /* @vite-ignore */
33357
- spec
33358
- );
33359
- } catch (cause) {
33360
- throw mebiusError("CONNECTION_FAILED", "Balanced playback support failed to load.", cause);
33361
- }
33362
- const flvjs = mod.default;
33363
- if (!flvjs.isSupported()) {
33364
- throw mebiusError("CONNECTION_FAILED", "Balanced playback is not supported in this browser.");
33365
- }
33366
- const player = flvjs.createPlayer({ type: "flv", url, isLive: true });
33367
- this.player = player;
33368
- player.on(flvjs.Events.ERROR ?? "error", () => this.bufferingCb?.());
33369
- player.attachMediaElement(video);
33370
- player.load();
33371
- await Promise.resolve(player.play()).catch(() => void 0);
33372
- }
33373
- async stop() {
33374
- if (this.player) {
33375
- this.player.unload();
33376
- this.player.detachMediaElement();
33377
- this.player.destroy();
33378
- this.player = null;
33379
- }
33380
- if (this.video) {
33381
- this.video.removeAttribute("src");
33382
- this.video.load();
33383
- }
33384
- this.video = null;
33385
- }
33386
- async getStats() {
33387
- if (!this.video) return null;
33388
- return {
33389
- bitrateKbps: 0,
33390
- framesPerSecond: 0,
33391
- latencyMs: void 0
33392
- };
33393
- }
33394
- };
33395
-
33396
33332
  // src/internal/scale-view-transport.ts
33397
33333
  var HlsViewTransport = class {
33398
33334
  constructor(signaling) {
@@ -33464,8 +33400,6 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33464
33400
  switch (mode) {
33465
33401
  case "low-latency":
33466
33402
  return new WhepViewTransport(signaling);
33467
- case "balanced":
33468
- return new FlvViewTransport(signaling);
33469
33403
  case "scale":
33470
33404
  return new HlsViewTransport(signaling);
33471
33405
  }
@@ -33640,28 +33574,27 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33640
33574
  scalePlaylistUrl(streamId) {
33641
33575
  return this.withToken(`${this.base()}/live/${encodeURIComponent(streamId)}/index.m3u8`);
33642
33576
  }
33643
- // Build the HTTP-FLV pull URL used by balanced-mode playback. Served by the
33644
- // CDN (CDN_PULL_FORMAT `.flv`) or an SRS/nginx-rtmp edge in front of the
33645
- // engine MediaMTX itself does not vend HTTP-FLV. Hidden from the public API.
33646
- /** Pull URL for balanced-mode playback. */
33647
- balancedStreamUrl(streamId) {
33648
- return this.withToken(`${this.base()}/flv/${encodeURIComponent(streamId)}.flv`);
33577
+ // Maps a neutral session kind to the concrete signaling path segment. This
33578
+ // mapping (publish -> WHIP, view -> WHEP) lives ONLY in this method body, so
33579
+ // the protocol names never appear in any exported type signature.
33580
+ pathFor(kind) {
33581
+ return kind === "publish" ? "whip" : "whep";
33649
33582
  }
33650
- // Performs the SDP offer/answer exchange for a publish (WHIP) or low-latency
33651
- // view (WHEP) session. Protocol detail kept in line comments so it never
33652
- // leaks into the bundled public .d.ts.
33583
+ // Performs the offer/answer exchange for a publish or a low-latency view
33584
+ // session. Protocol detail kept inside the method body so it never leaks into
33585
+ // the bundled public .d.ts.
33653
33586
  /**
33654
33587
  * Run the session offer/answer exchange. Throws a {@link MebiusError} with a
33655
33588
  * Mebius-flavored code on failure — never the raw protocol name.
33656
33589
  */
33657
- async exchangeSdp(kind, streamId, offerSdp) {
33658
- const url = this.withToken(`${this.base()}/${kind}/${encodeURIComponent(streamId)}`);
33590
+ async exchangeSession(kind, streamId, offer) {
33591
+ const url = this.withToken(`${this.base()}/${this.pathFor(kind)}/${encodeURIComponent(streamId)}`);
33659
33592
  let res;
33660
33593
  try {
33661
33594
  res = await fetch(url, {
33662
33595
  method: "POST",
33663
33596
  headers: this.headers("application/sdp"),
33664
- body: offerSdp
33597
+ body: offer
33665
33598
  });
33666
33599
  } catch (cause) {
33667
33600
  throw mebiusError("CONNECTION_FAILED", void 0, cause);
@@ -33675,10 +33608,10 @@ Schedule: ${scheduleItems.map((seg) => segmentToString(seg))} pos: ${this.timeli
33675
33608
  if (!res.ok) {
33676
33609
  throw mebiusError("CONNECTION_FAILED", `Mebius gateway returned ${res.status}.`);
33677
33610
  }
33678
- const answerSdp = await res.text();
33611
+ const answer = await res.text();
33679
33612
  const location2 = res.headers.get("Location");
33680
33613
  const resourceUrl = location2 ? new URL(location2, url).toString() : null;
33681
- return { answerSdp, resourceUrl };
33614
+ return { answer, resourceUrl };
33682
33615
  }
33683
33616
  /** Tear down a previously-created session resource. Best-effort. */
33684
33617
  async deleteResource(resourceUrl) {