moqtail 0.8.0 → 0.9.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.
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- import Heap from 'heap-js';
2
-
3
1
  var __defProp = Object.defineProperty;
4
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
3
  var __esm = (fn, res) => function __init() {
@@ -4534,6 +4532,219 @@ init_byte_buffer();
4534
4532
  init_error();
4535
4533
  init_constant2();
4536
4534
 
4535
+ // src/model/catalog/cmsf.ts
4536
+ function isString(v) {
4537
+ return typeof v === "string";
4538
+ }
4539
+ function isNumber(v) {
4540
+ return typeof v === "number";
4541
+ }
4542
+ function isStringArray(v) {
4543
+ return Array.isArray(v) && v.every((item) => isString(item));
4544
+ }
4545
+ function isValidPackaging(v) {
4546
+ return v === "cmaf" || v === "chunk-per-object" || v === "timeline";
4547
+ }
4548
+ function isValidRole(v) {
4549
+ return v === "video" || v === "audio" || v === "timeline";
4550
+ }
4551
+ function isValidBase64(str) {
4552
+ try {
4553
+ return btoa(atob(str)) === str;
4554
+ } catch {
4555
+ return false;
4556
+ }
4557
+ }
4558
+ function validateTrack(track) {
4559
+ if (typeof track !== "object" || track === null) {
4560
+ throw new Error("Track must be an object");
4561
+ }
4562
+ const t = track;
4563
+ if (!isString(t["name"])) {
4564
+ throw new Error("Track.name must be a string");
4565
+ }
4566
+ if (!isValidPackaging(t["packaging"])) {
4567
+ throw new Error("Track.packaging must be 'cmaf', 'chunk-per-object', or 'timeline'");
4568
+ }
4569
+ if (!isValidRole(t["role"])) {
4570
+ throw new Error("Track.role must be 'video', 'audio', or 'timeline'");
4571
+ }
4572
+ const name = t["name"];
4573
+ const packaging = t["packaging"];
4574
+ const role = t["role"];
4575
+ let codec;
4576
+ if (t["codec"] !== void 0) {
4577
+ if (!isString(t["codec"])) {
4578
+ throw new Error("Track.codec must be a string");
4579
+ }
4580
+ codec = t["codec"];
4581
+ }
4582
+ let depends;
4583
+ if (t["depends"] !== void 0) {
4584
+ if (!isStringArray(t["depends"])) {
4585
+ throw new Error("Track.depends must be an array of strings");
4586
+ }
4587
+ depends = t["depends"];
4588
+ }
4589
+ let mimeType;
4590
+ if (t["mimeType"] !== void 0) {
4591
+ if (!isString(t["mimeType"])) {
4592
+ throw new Error("Track.mimeType must be a string");
4593
+ }
4594
+ mimeType = t["mimeType"];
4595
+ }
4596
+ let width;
4597
+ if (t["width"] !== void 0) {
4598
+ if (!isNumber(t["width"])) {
4599
+ throw new Error("Track.width must be a number");
4600
+ }
4601
+ width = t["width"];
4602
+ }
4603
+ let height;
4604
+ if (t["height"] !== void 0) {
4605
+ if (!isNumber(t["height"])) {
4606
+ throw new Error("Track.height must be a number");
4607
+ }
4608
+ height = t["height"];
4609
+ }
4610
+ let timescale;
4611
+ if (t["timescale"] !== void 0) {
4612
+ if (!isNumber(t["timescale"])) {
4613
+ throw new Error("Track.timescale must be a number");
4614
+ }
4615
+ timescale = t["timescale"];
4616
+ }
4617
+ let bitrate;
4618
+ if (t["bitrate"] !== void 0) {
4619
+ if (!isNumber(t["bitrate"])) {
4620
+ throw new Error("Track.bitrate must be a number");
4621
+ }
4622
+ bitrate = t["bitrate"];
4623
+ }
4624
+ let initData;
4625
+ if (t["initData"] !== void 0) {
4626
+ if (!isString(t["initData"])) {
4627
+ throw new Error("Track.initData must be a string");
4628
+ }
4629
+ if (!isValidBase64(t["initData"])) {
4630
+ throw new Error("Track.initData must be a valid base64 string");
4631
+ }
4632
+ initData = t["initData"];
4633
+ }
4634
+ if (packaging === "cmaf" && (!codec || codec.length === 0)) {
4635
+ throw new Error("codec is required when packaging is 'cmaf'");
4636
+ }
4637
+ if (packaging === "timeline" && mimeType !== "text/csv") {
4638
+ throw new Error("mimeType must be 'text/csv' when packaging is 'timeline'");
4639
+ }
4640
+ if (packaging === "timeline" && (!depends || depends.length === 0)) {
4641
+ throw new Error("At least one dependee must be present when packaging is 'timeline'");
4642
+ }
4643
+ const result = {
4644
+ name,
4645
+ packaging,
4646
+ role
4647
+ };
4648
+ if (codec !== void 0) result.codec = codec;
4649
+ if (depends !== void 0) result.depends = depends;
4650
+ if (mimeType !== void 0) result.mimeType = mimeType;
4651
+ if (width !== void 0) result.width = width;
4652
+ if (height !== void 0) result.height = height;
4653
+ if (timescale !== void 0) result.timescale = timescale;
4654
+ if (bitrate !== void 0) result.bitrate = bitrate;
4655
+ if (initData !== void 0) result.initData = initData;
4656
+ return result;
4657
+ }
4658
+ function validateCMSF(obj) {
4659
+ if (typeof obj !== "object" || obj === null) {
4660
+ throw new Error("CMSF must be an object");
4661
+ }
4662
+ const o = obj;
4663
+ if (!isNumber(o["version"])) {
4664
+ throw new Error("CMSF.version must be a number");
4665
+ }
4666
+ if (!Array.isArray(o["tracks"])) {
4667
+ throw new Error("CMSF.tracks must be an array");
4668
+ }
4669
+ const version = o["version"];
4670
+ const tracksArray = o["tracks"];
4671
+ const tracks = tracksArray.map(validateTrack);
4672
+ return {
4673
+ version,
4674
+ tracks
4675
+ };
4676
+ }
4677
+ var CMSFCatalog = class _CMSFCatalog {
4678
+ #catalog;
4679
+ constructor(catalog) {
4680
+ this.#catalog = catalog;
4681
+ }
4682
+ static from(payload) {
4683
+ const decoder = new TextDecoder();
4684
+ const json = decoder.decode(payload);
4685
+ const catalog = validateCMSF(JSON.parse(json));
4686
+ return new _CMSFCatalog(catalog);
4687
+ }
4688
+ getByTrackName(trackName) {
4689
+ return this.#catalog.tracks.find((track) => track.name === this.extractTrackName(trackName));
4690
+ }
4691
+ getTracks(role) {
4692
+ if (role) return this.#catalog.tracks.filter((track) => track.role === role);
4693
+ return this.#catalog.tracks;
4694
+ }
4695
+ getVideo(index = 0) {
4696
+ const videos = this.#catalog.tracks.filter((track) => track.role === "video");
4697
+ if (index < 0 || index >= videos.length) return void 0;
4698
+ return videos[index];
4699
+ }
4700
+ getAudio(index = 0) {
4701
+ const audios = this.#catalog.tracks.filter((track) => track.role === "audio");
4702
+ if (index < 0 || index >= audios.length) return void 0;
4703
+ return audios[index];
4704
+ }
4705
+ getTimeline(index = 0) {
4706
+ const timelines = this.#catalog.tracks.filter((track) => track.role === "timeline");
4707
+ if (index < 0 || index >= timelines.length) return void 0;
4708
+ return timelines[index];
4709
+ }
4710
+ getCodecString(trackName) {
4711
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
4712
+ if (!track) return void 0;
4713
+ if (!track.codec) throw new Error(`Track ${trackName} does not have a codec`);
4714
+ return track.codec;
4715
+ }
4716
+ getRole(trackName) {
4717
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
4718
+ if (!track) return void 0;
4719
+ return track.role;
4720
+ }
4721
+ getPackaging(trackName) {
4722
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
4723
+ if (!track) return void 0;
4724
+ return track.packaging;
4725
+ }
4726
+ isCMAF(trackName) {
4727
+ const packaging = this.getPackaging(trackName);
4728
+ return packaging === "cmaf" || packaging === "chunk-per-object";
4729
+ }
4730
+ getTimescale(trackName) {
4731
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
4732
+ return track?.timescale;
4733
+ }
4734
+ getInitData(trackName) {
4735
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
4736
+ if (!track) return void 0;
4737
+ if (!track.initData) throw new Error(`Track ${trackName} does not have initData`);
4738
+ return new Uint8Array(
4739
+ atob(track.initData).split("").map((c) => c.charCodeAt(0))
4740
+ );
4741
+ }
4742
+ extractTrackName(input) {
4743
+ const parts = input.split("/");
4744
+ return parts[parts.length - 1];
4745
+ }
4746
+ };
4747
+
4537
4748
  // src/model/control/switch.ts
4538
4749
  init_byte_buffer();
4539
4750
  init_pair();
@@ -6171,13 +6382,13 @@ var handlerSubscribeNamespaceOk = async (_client, _msg) => {
6171
6382
  };
6172
6383
 
6173
6384
  // src/client/handler/publish_done.ts
6174
- init_error2();
6175
6385
  var handlerPublishDone = async (client, msg) => {
6386
+ if (client.onPeerPublishDone) {
6387
+ client.onPeerPublishDone(msg);
6388
+ }
6176
6389
  const request = client.requests.get(msg.requestId);
6177
6390
  if (request instanceof SubscribeRequest) {
6178
6391
  request.expectedStreams = msg.streamCount;
6179
- } else {
6180
- throw new ProtocolViolationError("handlerPublishDone", "No publish request was found with the given request id");
6181
6392
  }
6182
6393
  };
6183
6394
 
@@ -6267,17 +6478,6 @@ var handlerPublish = async (client, msg) => {
6267
6478
  if (client.onPeerPublish) {
6268
6479
  client.onPeerPublish(msg, stream);
6269
6480
  }
6270
- const publishOk = new PublishOk(
6271
- msg.requestId,
6272
- 1,
6273
- 255,
6274
- 1 /* Ascending */,
6275
- 2 /* LatestObject */,
6276
- void 0,
6277
- void 0,
6278
- []
6279
- );
6280
- await client.controlStream.send(publishOk);
6281
6481
  };
6282
6482
 
6283
6483
  // src/client/publication/publish.ts
@@ -6799,6 +6999,8 @@ var MOQtailClient = class _MOQtailClient {
6799
6999
  onDatagramSent;
6800
7000
  /** Fired when an inbound PUBLISH control message is received. */
6801
7001
  onPeerPublish;
7002
+ /** Fired when an inbound PUBLISH_DONE control message is received. */
7003
+ onPeerPublishDone;
6802
7004
  /** Fired when an inbound SUBSCRIBE_NAMESPACE control message is received. */
6803
7005
  onPeerSubscribeNamespace;
6804
7006
  /** Datagram writer for sending datagrams. */
@@ -7880,6 +8082,26 @@ var MOQtailClient = class _MOQtailClient {
7880
8082
  throw error;
7881
8083
  }
7882
8084
  }
8085
+ /**
8086
+ * Signals the end of a published track to the peer/relay.
8087
+ * * @param publishRequestId - The original requestId used when `publish()` was called.
8088
+ */
8089
+ async publishDone(publishRequestId, statusCode = 0, reasonPhrase = "Track Ended") {
8090
+ this.#ensureActive();
8091
+ try {
8092
+ if (typeof publishRequestId === "number") publishRequestId = BigInt(publishRequestId);
8093
+ const msg = new PublishDone(publishRequestId, statusCode, 0n, new ReasonPhrase(reasonPhrase));
8094
+ await this.controlStream.send(msg);
8095
+ this.requests.delete(publishRequestId);
8096
+ this.requestIdMap.removeMappingByRequestId(publishRequestId);
8097
+ this.subscriptionAliasMap.delete(publishRequestId);
8098
+ } catch (error) {
8099
+ await this.disconnect(
8100
+ new InternalError("MOQtailClient.publishDone", error instanceof Error ? error.message : String(error))
8101
+ );
8102
+ throw error;
8103
+ }
8104
+ }
7883
8105
  /**
7884
8106
  * Registers an incoming PUBLISH announcement as a valid data receiver.
7885
8107
  * This prepares the client to ingest pushed data streams matching the published alias.
@@ -8466,300 +8688,6 @@ var NetworkTelemetry = class {
8466
8688
  }
8467
8689
  };
8468
8690
 
8469
- // src/util/playout_buffer.ts
8470
- init_extension_header2();
8471
- var DEFAULT_TARGET_LATENCY_MS = 100;
8472
- var DEFAULT_MAX_LATENCY_MS = 1e3;
8473
- var PlayoutBuffer = class {
8474
- constructor(objectStream, options) {
8475
- this.options = options;
8476
- this.#targetLatencyMs = this.options?.targetLatencyMs ?? DEFAULT_TARGET_LATENCY_MS;
8477
- this.#maxLatencyMs = this.options?.maxLatencyMs ?? DEFAULT_MAX_LATENCY_MS;
8478
- this.#clock = this.options?.clock;
8479
- this.#reader = objectStream.getReader();
8480
- this.#fillBuffer();
8481
- this.#serveBuffer();
8482
- }
8483
- #reader;
8484
- #buffer = new Heap((a, b) => {
8485
- return a.object.location.compare(b.object.location);
8486
- });
8487
- #isRunning = true;
8488
- #targetLatencyMs;
8489
- #moqObjectCountInBuffer = 0;
8490
- #moqObjectCountExitingBuffer = 0;
8491
- #maxLatencyMs;
8492
- #clock;
8493
- onObject = null;
8494
- async hasObjectReady() {
8495
- const now = this.#getNormalizedTime();
8496
- const oldest = this.#buffer.peek();
8497
- return oldest ? now - oldest.createdAt >= this.#targetLatencyMs : false;
8498
- }
8499
- getStatus() {
8500
- const oldest = this.#buffer.peek();
8501
- const result = {
8502
- bufferSize: this.#buffer.length,
8503
- isRunning: this.#isRunning
8504
- };
8505
- if (oldest) {
8506
- result.oldestTimestamp = oldest.createdAt;
8507
- }
8508
- return result;
8509
- }
8510
- cleanup() {
8511
- this.#isRunning = false;
8512
- this.onObject?.(null);
8513
- }
8514
- #getNormalizedTime() {
8515
- if (this.#clock) {
8516
- return this.#clock.now();
8517
- }
8518
- return Date.now();
8519
- }
8520
- async #serveBuffer() {
8521
- while (this.#isRunning) {
8522
- const now = this.#getNormalizedTime();
8523
- const oldest = this.#buffer.peek();
8524
- if (oldest && this.onObject) {
8525
- const timeUntilReady = this.#targetLatencyMs - (now - oldest.createdAt);
8526
- if (timeUntilReady <= 0) {
8527
- const bufferedObj = this.#buffer.pop();
8528
- this.#moqObjectCountExitingBuffer++;
8529
- if (this.#moqObjectCountExitingBuffer % 50 === 0) ;
8530
- this.onObject(bufferedObj.object);
8531
- if (this.#moqObjectCountExitingBuffer % 50 === 0) ;
8532
- } else {
8533
- const sleepTime = Math.min(timeUntilReady, 50);
8534
- await new Promise((resolve) => setTimeout(resolve, sleepTime));
8535
- }
8536
- } else {
8537
- await new Promise((resolve) => setTimeout(resolve, 10));
8538
- }
8539
- }
8540
- }
8541
- async #fillBuffer() {
8542
- while (this.#isRunning) {
8543
- try {
8544
- const { value, done } = await this.#reader.read();
8545
- if (done) {
8546
- this.cleanup();
8547
- return;
8548
- }
8549
- this.#evictOnMaxLatency();
8550
- const bufferedObject = {
8551
- object: value,
8552
- createdAt: this.#extractCreatedAt(value)
8553
- };
8554
- this.#moqObjectCountInBuffer++;
8555
- if (this.#moqObjectCountInBuffer % 50 === 0) {
8556
- }
8557
- this.#buffer.push(bufferedObject);
8558
- } catch (error) {
8559
- this.cleanup();
8560
- }
8561
- }
8562
- }
8563
- #extractCreatedAt(object) {
8564
- if (object.extensionHeaders) {
8565
- const extensionHeaders = ExtensionHeaders.fromKeyValuePairs(object.extensionHeaders);
8566
- for (const header of extensionHeaders) {
8567
- if (ExtensionHeader.isCaptureTimestamp(header)) {
8568
- return Number(header.timestamp);
8569
- }
8570
- }
8571
- }
8572
- return this.#getNormalizedTime();
8573
- }
8574
- #evictOnMaxLatency() {
8575
- const now = this.#getNormalizedTime();
8576
- const oldest = this.#buffer.peek();
8577
- if (oldest && now - oldest.createdAt > this.#maxLatencyMs) {
8578
- if (oldest.object.location.object === 0n) {
8579
- const groupToDrop = oldest.object.location.group;
8580
- this.#dropGop(groupToDrop);
8581
- } else {
8582
- this.#buffer.pop();
8583
- }
8584
- this.#evictOnMaxLatency();
8585
- }
8586
- }
8587
- #dropGop(groupId) {
8588
- while (this.#buffer.length > 0) {
8589
- const oldest = this.#buffer.peek();
8590
- if (oldest && oldest.object.location.group === groupId) {
8591
- this.#buffer.pop();
8592
- } else {
8593
- break;
8594
- }
8595
- }
8596
- }
8597
- };
8598
- var DEFAULT_BUFFER_CAPACITY = 50;
8599
- var DEFAULT_TARGET_LATENCY_MS2 = 500;
8600
- var DEFAULT_MAX_LATENCY_MS2 = 2e3;
8601
- var PullPlayoutBuffer = class {
8602
- constructor(writeStream, options) {
8603
- this.options = options;
8604
- this.#bucketCapacity = this.options.bucketCapacity ?? DEFAULT_BUFFER_CAPACITY;
8605
- this.#targetLatencyMs = this.options.targetLatencyMs ?? DEFAULT_TARGET_LATENCY_MS2;
8606
- this.#maxLatencyMs = this.options.maxLatencyMs ?? DEFAULT_MAX_LATENCY_MS2;
8607
- this.#reader = writeStream.getReader();
8608
- this.#fillBuffer();
8609
- }
8610
- #reader;
8611
- #buffer = new Heap((a, b) => {
8612
- if (a.location.compare(b.location) <= 0) {
8613
- if (b.location.compare(a.location) <= 0) {
8614
- return 0;
8615
- }
8616
- return -1;
8617
- }
8618
- return 1;
8619
- });
8620
- #isRunning = true;
8621
- #bucketCapacity;
8622
- #targetLatencyMs;
8623
- #maxLatencyMs;
8624
- #lastIncomingTimestamp = 0;
8625
- #pendingCallback = null;
8626
- // Pull-based API: Consumer calls this when ready for next object
8627
- nextObject(callback) {
8628
- if (this.#buffer.length > 0) {
8629
- const obj = this.#buffer.pop();
8630
- callback(obj || null);
8631
- return;
8632
- }
8633
- this.#pendingCallback = callback;
8634
- }
8635
- // Check if there's an object ready immediately (non-blocking)
8636
- hasObjectReady() {
8637
- return this.#buffer.length > 0;
8638
- }
8639
- // Get current buffer status for debugging
8640
- getStatus() {
8641
- return {
8642
- bufferSize: this.#buffer.length,
8643
- isRunning: this.#isRunning
8644
- };
8645
- }
8646
- // Cleanup method - called when buffer is destroyed
8647
- cleanup() {
8648
- this.#isRunning = false;
8649
- }
8650
- // Simple background filling - just fills the buffer as objects arrive
8651
- async #fillBuffer() {
8652
- while (this.#isRunning) {
8653
- try {
8654
- const { value, done } = await this.#reader.read();
8655
- if (done) {
8656
- this.#isRunning = false;
8657
- if (this.#pendingCallback) {
8658
- const callback = this.#pendingCallback;
8659
- this.#pendingCallback = null;
8660
- callback(null);
8661
- }
8662
- return;
8663
- }
8664
- this.#lastIncomingTimestamp = performance.now();
8665
- if (this.#buffer.length >= this.#bucketCapacity) {
8666
- this.#manageBufferOverflow();
8667
- }
8668
- this.#buffer.push(value);
8669
- if (this.#pendingCallback) {
8670
- const callback = this.#pendingCallback;
8671
- this.#pendingCallback = null;
8672
- const obj = this.#buffer.pop();
8673
- callback(obj || null);
8674
- }
8675
- } catch (error) {
8676
- console.error("Error in fillBuffer:", error);
8677
- this.#isRunning = false;
8678
- if (this.#pendingCallback) {
8679
- const callback = this.#pendingCallback;
8680
- this.#pendingCallback = null;
8681
- callback(null);
8682
- }
8683
- }
8684
- }
8685
- }
8686
- // Manage buffer overflow by dropping oldest GOPs
8687
- #manageBufferOverflow() {
8688
- const droppedGops = this.#dropMultipleGopsToTarget();
8689
- if (droppedGops === 0) {
8690
- const dropCount = Math.floor(this.#bucketCapacity * 0.2);
8691
- for (let i = 0; i < dropCount; i++) {
8692
- this.#buffer.pop();
8693
- }
8694
- console.log(`\u{1F5D1}\uFE0F [PULL BUFFER] Buffer overflow: dropped ${dropCount} oldest objects (fallback)`);
8695
- }
8696
- }
8697
- // Find GOP boundaries based on group IDs
8698
- #findGopBoundaries(objects) {
8699
- const gops = [];
8700
- if (objects.length === 0) return gops;
8701
- const groupMap = /* @__PURE__ */ new Map();
8702
- objects.forEach((obj, index) => {
8703
- const groupId = obj.location.group;
8704
- if (!groupMap.has(groupId)) {
8705
- groupMap.set(groupId, []);
8706
- }
8707
- groupMap.get(groupId).push(index);
8708
- });
8709
- const sortedGroups = Array.from(groupMap.entries()).sort(([a], [b]) => {
8710
- if (a < b) return -1;
8711
- if (a > b) return 1;
8712
- return 0;
8713
- });
8714
- sortedGroups.forEach(([, indices]) => {
8715
- if (indices.length > 0) {
8716
- gops.push({
8717
- start: Math.min(...indices),
8718
- end: Math.max(...indices)
8719
- });
8720
- }
8721
- });
8722
- console.log(`\u{1F3AC} [PULL BUFFER] Found ${gops.length} GOPs (groups) in buffer`);
8723
- return gops;
8724
- }
8725
- // Drop oldest GOP (complete group)
8726
- #dropOldestGop() {
8727
- const allObjects = this.#buffer.toArray();
8728
- const gops = this.#findGopBoundaries(allObjects);
8729
- if (gops.length > 0) {
8730
- const oldestGop = gops[0];
8731
- if (oldestGop) {
8732
- const firstObj = allObjects[oldestGop.start];
8733
- const groupId = firstObj?.location.group;
8734
- for (let i = oldestGop.start; i <= oldestGop.end; i++) {
8735
- this.#buffer.pop();
8736
- }
8737
- console.log(`\u{1F5D1}\uFE0F [PULL BUFFER] Dropped GOP (Group ${groupId}): ${oldestGop.end - oldestGop.start + 1} objects`);
8738
- return true;
8739
- }
8740
- }
8741
- return false;
8742
- }
8743
- // Drop multiple GOPs to reach target buffer size
8744
- #dropMultipleGopsToTarget() {
8745
- const targetBufferSize = Math.floor(this.#bucketCapacity * 0.7);
8746
- let droppedGops = 0;
8747
- while (this.#buffer.length > targetBufferSize && droppedGops < 3) {
8748
- if (this.#dropOldestGop()) {
8749
- droppedGops++;
8750
- } else {
8751
- break;
8752
- }
8753
- }
8754
- if (droppedGops > 0) {
8755
- console.log(
8756
- `\u{1F5D1}\uFE0F [PULL BUFFER] Dropped ${droppedGops} GOPs to reduce buffer size. New buffer size: ${this.#buffer.length}`
8757
- );
8758
- }
8759
- return droppedGops;
8760
- }
8761
- };
8762
-
8763
8691
  // src/util/clock_normalizer.ts
8764
8692
  var DEFAULT_SAMPLE_SIZE = 5;
8765
8693
  var DEFAULT_TIME_SERVER = "https://time.akamai.com/?ms";
@@ -8829,4 +8757,4 @@ var ClockNormalizer = class _ClockNormalizer {
8829
8757
  }
8830
8758
  };
8831
8759
 
8832
- export { AudioLevel, AuthorizationToken, BaseByteBuffer12 as BaseByteBuffer, ByteBuffer, CaptureTimestamp, CastingError, ClientSetup, ClockNormalizer, CommonType, ControlMessage, ControlMessageType, ControlStream, DRAFT_14, DatagramObject, DatagramStatus, DeliveryTimeout, ExtensionHeader, ExtensionHeaders, Fetch, FetchCancel, FetchError, FetchErrorCode, FetchHeader, FetchHeaderType, FetchObject, FetchOk, FetchPublication, FetchRequest, FetchType, FilterType, FrozenByteBuffer5 as FrozenByteBuffer, FullTrackName, GoAway, GroupOrder, Header, HybridTrackSource, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, LiveTrackSource, Location, MAX_FULL_TRACK_NAME_LENGTH, MAX_NAMESPACE_TUPLE_COUNT, MAX_REASON_PHRASE_LEN, MOQtailClient, MOQtailError, MaxAuthTokenCacheSize, MaxCacheDuration, MaxRequestId, MaxRequestId2 as MaxRequestIdParameter, MemoryObjectCache, MoqtObject, NetworkTelemetry, NotEnoughBytesError, ObjectDatagramStatusType, ObjectDatagramType, ObjectForwardingPreference, ObjectStatus, Path, PlayoutBuffer, ProtocolViolationError, Publish, PublishDone, PublishDoneStatusCode, PublishError, PublishErrorCode, PublishNamespace, PublishNamespaceCancel, PublishNamespaceDone, PublishNamespaceError, PublishNamespaceErrorCode, PublishNamespaceOk, PublishNamespaceRequest, PublishOk, PublishPublication, PublishRequest, PullPlayoutBuffer, ReasonPhrase, RecvDatagramStream, RecvStream, RequestIdError, RequestIdMap, RequestsBlocked, RingBufferObjectCache, SendDatagramStream, SendStream, ServerSetup, SetupParameter, SetupParameterType, SetupParameters, StaticTrackSource, SubgroupHeader, SubgroupHeaderType, SubgroupObject, Subscribe, SubscribeError, SubscribeErrorCode, SubscribeNamespace, SubscribeNamespaceError, SubscribeNamespaceErrorCode, SubscribeNamespaceOk, SubscribeNamespaceRequest, SubscribeOk, SubscribePublication, SubscribeRequest, SubscribeUpdate, Switch, TerminationCode, TerminationError, TimeoutError, TokenAliasType, TrackNameError, TrackStatus, TrackStatusCode, TrackStatusError, TrackStatusOk, Tuple, TupleField, Unsubscribe, UnsubscribeNamespace, VarIntOverflowError, VersionSpecificParameter, VersionSpecificParameterType, VersionSpecificParameters, VideoConfig, VideoFrameMarking, commonTypeFromNumber, controlMessageTypeFromBigInt, fetchErrorCodeFromBigInt, fetchTypeFromBigInt, filterTypeFromBigInt, groupOrderFromNumber, isBytes, isVarInt, locHeaderExtensionIdFromNumber, publishDoneStatusCodeFromBigInt, publishErrorCodeFromBigInt, publishNamespaceErrorCodeFromBigInt, setupParameterTypeFromNumber, subscribeErrorCodeFromBigInt, subscribeNamespaceErrorCodeFromBigInt, tokenAliasTypeFromNumber, trackStatusCodeFromBigInt, versionSpecificParameterTypeFromNumber };
8760
+ export { AudioLevel, AuthorizationToken, BaseByteBuffer12 as BaseByteBuffer, ByteBuffer, CMSFCatalog, CaptureTimestamp, CastingError, ClientSetup, ClockNormalizer, CommonType, ControlMessage, ControlMessageType, ControlStream, DRAFT_14, DatagramObject, DatagramStatus, DeliveryTimeout, ExtensionHeader, ExtensionHeaders, Fetch, FetchCancel, FetchError, FetchErrorCode, FetchHeader, FetchHeaderType, FetchObject, FetchOk, FetchPublication, FetchRequest, FetchType, FilterType, FrozenByteBuffer5 as FrozenByteBuffer, FullTrackName, GoAway, GroupOrder, Header, HybridTrackSource, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, LiveTrackSource, Location, MAX_FULL_TRACK_NAME_LENGTH, MAX_NAMESPACE_TUPLE_COUNT, MAX_REASON_PHRASE_LEN, MOQtailClient, MOQtailError, MaxAuthTokenCacheSize, MaxCacheDuration, MaxRequestId, MaxRequestId2 as MaxRequestIdParameter, MemoryObjectCache, MoqtObject, NetworkTelemetry, NotEnoughBytesError, ObjectDatagramStatusType, ObjectDatagramType, ObjectForwardingPreference, ObjectStatus, Path, ProtocolViolationError, Publish, PublishDone, PublishDoneStatusCode, PublishError, PublishErrorCode, PublishNamespace, PublishNamespaceCancel, PublishNamespaceDone, PublishNamespaceError, PublishNamespaceErrorCode, PublishNamespaceOk, PublishNamespaceRequest, PublishOk, PublishPublication, PublishRequest, ReasonPhrase, RecvDatagramStream, RecvStream, RequestIdError, RequestIdMap, RequestsBlocked, RingBufferObjectCache, SendDatagramStream, SendStream, ServerSetup, SetupParameter, SetupParameterType, SetupParameters, StaticTrackSource, SubgroupHeader, SubgroupHeaderType, SubgroupObject, Subscribe, SubscribeError, SubscribeErrorCode, SubscribeNamespace, SubscribeNamespaceError, SubscribeNamespaceErrorCode, SubscribeNamespaceOk, SubscribeNamespaceRequest, SubscribeOk, SubscribePublication, SubscribeRequest, SubscribeUpdate, Switch, TerminationCode, TerminationError, TimeoutError, TokenAliasType, TrackNameError, TrackStatus, TrackStatusCode, TrackStatusError, TrackStatusOk, Tuple, TupleField, Unsubscribe, UnsubscribeNamespace, VarIntOverflowError, VersionSpecificParameter, VersionSpecificParameterType, VersionSpecificParameters, VideoConfig, VideoFrameMarking, commonTypeFromNumber, controlMessageTypeFromBigInt, fetchErrorCodeFromBigInt, fetchTypeFromBigInt, filterTypeFromBigInt, groupOrderFromNumber, isBytes, isVarInt, locHeaderExtensionIdFromNumber, publishDoneStatusCodeFromBigInt, publishErrorCodeFromBigInt, publishNamespaceErrorCodeFromBigInt, setupParameterTypeFromNumber, subscribeErrorCodeFromBigInt, subscribeNamespaceErrorCodeFromBigInt, tokenAliasTypeFromNumber, trackStatusCodeFromBigInt, versionSpecificParameterTypeFromNumber };