moqtail 0.8.1 → 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.
@@ -1,5 +1,218 @@
1
1
  'use strict';
2
2
 
3
+ // src/model/catalog/cmsf.ts
4
+ function isString(v) {
5
+ return typeof v === "string";
6
+ }
7
+ function isNumber(v) {
8
+ return typeof v === "number";
9
+ }
10
+ function isStringArray(v) {
11
+ return Array.isArray(v) && v.every((item) => isString(item));
12
+ }
13
+ function isValidPackaging(v) {
14
+ return v === "cmaf" || v === "chunk-per-object" || v === "timeline";
15
+ }
16
+ function isValidRole(v) {
17
+ return v === "video" || v === "audio" || v === "timeline";
18
+ }
19
+ function isValidBase64(str) {
20
+ try {
21
+ return btoa(atob(str)) === str;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function validateTrack(track) {
27
+ if (typeof track !== "object" || track === null) {
28
+ throw new Error("Track must be an object");
29
+ }
30
+ const t = track;
31
+ if (!isString(t["name"])) {
32
+ throw new Error("Track.name must be a string");
33
+ }
34
+ if (!isValidPackaging(t["packaging"])) {
35
+ throw new Error("Track.packaging must be 'cmaf', 'chunk-per-object', or 'timeline'");
36
+ }
37
+ if (!isValidRole(t["role"])) {
38
+ throw new Error("Track.role must be 'video', 'audio', or 'timeline'");
39
+ }
40
+ const name = t["name"];
41
+ const packaging = t["packaging"];
42
+ const role = t["role"];
43
+ let codec;
44
+ if (t["codec"] !== void 0) {
45
+ if (!isString(t["codec"])) {
46
+ throw new Error("Track.codec must be a string");
47
+ }
48
+ codec = t["codec"];
49
+ }
50
+ let depends;
51
+ if (t["depends"] !== void 0) {
52
+ if (!isStringArray(t["depends"])) {
53
+ throw new Error("Track.depends must be an array of strings");
54
+ }
55
+ depends = t["depends"];
56
+ }
57
+ let mimeType;
58
+ if (t["mimeType"] !== void 0) {
59
+ if (!isString(t["mimeType"])) {
60
+ throw new Error("Track.mimeType must be a string");
61
+ }
62
+ mimeType = t["mimeType"];
63
+ }
64
+ let width;
65
+ if (t["width"] !== void 0) {
66
+ if (!isNumber(t["width"])) {
67
+ throw new Error("Track.width must be a number");
68
+ }
69
+ width = t["width"];
70
+ }
71
+ let height;
72
+ if (t["height"] !== void 0) {
73
+ if (!isNumber(t["height"])) {
74
+ throw new Error("Track.height must be a number");
75
+ }
76
+ height = t["height"];
77
+ }
78
+ let timescale;
79
+ if (t["timescale"] !== void 0) {
80
+ if (!isNumber(t["timescale"])) {
81
+ throw new Error("Track.timescale must be a number");
82
+ }
83
+ timescale = t["timescale"];
84
+ }
85
+ let bitrate;
86
+ if (t["bitrate"] !== void 0) {
87
+ if (!isNumber(t["bitrate"])) {
88
+ throw new Error("Track.bitrate must be a number");
89
+ }
90
+ bitrate = t["bitrate"];
91
+ }
92
+ let initData;
93
+ if (t["initData"] !== void 0) {
94
+ if (!isString(t["initData"])) {
95
+ throw new Error("Track.initData must be a string");
96
+ }
97
+ if (!isValidBase64(t["initData"])) {
98
+ throw new Error("Track.initData must be a valid base64 string");
99
+ }
100
+ initData = t["initData"];
101
+ }
102
+ if (packaging === "cmaf" && (!codec || codec.length === 0)) {
103
+ throw new Error("codec is required when packaging is 'cmaf'");
104
+ }
105
+ if (packaging === "timeline" && mimeType !== "text/csv") {
106
+ throw new Error("mimeType must be 'text/csv' when packaging is 'timeline'");
107
+ }
108
+ if (packaging === "timeline" && (!depends || depends.length === 0)) {
109
+ throw new Error("At least one dependee must be present when packaging is 'timeline'");
110
+ }
111
+ const result = {
112
+ name,
113
+ packaging,
114
+ role
115
+ };
116
+ if (codec !== void 0) result.codec = codec;
117
+ if (depends !== void 0) result.depends = depends;
118
+ if (mimeType !== void 0) result.mimeType = mimeType;
119
+ if (width !== void 0) result.width = width;
120
+ if (height !== void 0) result.height = height;
121
+ if (timescale !== void 0) result.timescale = timescale;
122
+ if (bitrate !== void 0) result.bitrate = bitrate;
123
+ if (initData !== void 0) result.initData = initData;
124
+ return result;
125
+ }
126
+ function validateCMSF(obj) {
127
+ if (typeof obj !== "object" || obj === null) {
128
+ throw new Error("CMSF must be an object");
129
+ }
130
+ const o = obj;
131
+ if (!isNumber(o["version"])) {
132
+ throw new Error("CMSF.version must be a number");
133
+ }
134
+ if (!Array.isArray(o["tracks"])) {
135
+ throw new Error("CMSF.tracks must be an array");
136
+ }
137
+ const version = o["version"];
138
+ const tracksArray = o["tracks"];
139
+ const tracks = tracksArray.map(validateTrack);
140
+ return {
141
+ version,
142
+ tracks
143
+ };
144
+ }
145
+ var CMSFCatalog = class _CMSFCatalog {
146
+ #catalog;
147
+ constructor(catalog) {
148
+ this.#catalog = catalog;
149
+ }
150
+ static from(payload) {
151
+ const decoder = new TextDecoder();
152
+ const json = decoder.decode(payload);
153
+ const catalog = validateCMSF(JSON.parse(json));
154
+ return new _CMSFCatalog(catalog);
155
+ }
156
+ getByTrackName(trackName) {
157
+ return this.#catalog.tracks.find((track) => track.name === this.extractTrackName(trackName));
158
+ }
159
+ getTracks(role) {
160
+ if (role) return this.#catalog.tracks.filter((track) => track.role === role);
161
+ return this.#catalog.tracks;
162
+ }
163
+ getVideo(index = 0) {
164
+ const videos = this.#catalog.tracks.filter((track) => track.role === "video");
165
+ if (index < 0 || index >= videos.length) return void 0;
166
+ return videos[index];
167
+ }
168
+ getAudio(index = 0) {
169
+ const audios = this.#catalog.tracks.filter((track) => track.role === "audio");
170
+ if (index < 0 || index >= audios.length) return void 0;
171
+ return audios[index];
172
+ }
173
+ getTimeline(index = 0) {
174
+ const timelines = this.#catalog.tracks.filter((track) => track.role === "timeline");
175
+ if (index < 0 || index >= timelines.length) return void 0;
176
+ return timelines[index];
177
+ }
178
+ getCodecString(trackName) {
179
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
180
+ if (!track) return void 0;
181
+ if (!track.codec) throw new Error(`Track ${trackName} does not have a codec`);
182
+ return track.codec;
183
+ }
184
+ getRole(trackName) {
185
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
186
+ if (!track) return void 0;
187
+ return track.role;
188
+ }
189
+ getPackaging(trackName) {
190
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
191
+ if (!track) return void 0;
192
+ return track.packaging;
193
+ }
194
+ isCMAF(trackName) {
195
+ const packaging = this.getPackaging(trackName);
196
+ return packaging === "cmaf" || packaging === "chunk-per-object";
197
+ }
198
+ getTimescale(trackName) {
199
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
200
+ return track?.timescale;
201
+ }
202
+ getInitData(trackName) {
203
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
204
+ if (!track) return void 0;
205
+ if (!track.initData) throw new Error(`Track ${trackName} does not have initData`);
206
+ return new Uint8Array(
207
+ atob(track.initData).split("").map((c) => c.charCodeAt(0))
208
+ );
209
+ }
210
+ extractTrackName(input) {
211
+ const parts = input.split("/");
212
+ return parts[parts.length - 1];
213
+ }
214
+ };
215
+
3
216
  // src/model/error/error.ts
4
217
  var MOQtailError = class extends Error {
5
218
  constructor(cause) {
@@ -4711,6 +4924,7 @@ exports.AudioLevel = AudioLevel;
4711
4924
  exports.AuthorizationToken = AuthorizationToken;
4712
4925
  exports.BaseByteBuffer = BaseByteBuffer12;
4713
4926
  exports.ByteBuffer = ByteBuffer;
4927
+ exports.CMSFCatalog = CMSFCatalog;
4714
4928
  exports.CaptureTimestamp = CaptureTimestamp;
4715
4929
  exports.CastingError = CastingError;
4716
4930
  exports.ClientSetup = ClientSetup;
@@ -1,6 +1,55 @@
1
- import { m as FullTrackName, K as KeyValuePair, F as FrozenByteBuffer, B as BaseByteBuffer } from '../byte_buffer-BM4uNj4n.js';
2
- export { a as ByteBuffer, D as DatagramObject, h as DatagramStatus, e as FetchHeaderType, j as FetchObject, L as Location, l as MAX_FULL_TRACK_NAME_LENGTH, k as MAX_NAMESPACE_TUPLE_COUNT, M as MAX_REASON_PHRASE_LEN, n as MoqtObject, O as ObjectDatagramStatusType, d as ObjectDatagramType, f as ObjectForwardingPreference, g as ObjectStatus, R as ReasonPhrase, S as SubgroupHeaderType, o as SubgroupObject, c as Tuple, T as TupleField, b as isBytes, i as isVarInt } from '../byte_buffer-BM4uNj4n.js';
3
- export { ah as AuthTokenVariant, ai as AuthorizationToken, C as ClientSetup, a9 as CommonType, w as ControlMessage, d as ControlMessageType, D as DRAFT_14, am as DeliveryTimeout, x as Fetch, y as FetchCancel, z as FetchError, l as FetchErrorCode, a0 as FetchHeader, A as FetchOk, h as FetchType, F as FilterType, B as GoAway, G as GroupOrder, a3 as Header, al as MaxAuthTokenCacheSize, an as MaxCacheDuration, M as MaxRequestId, aj as MaxRequestIdParameter, a8 as Parameter, ak as Path, L as Publish, K as PublishDone, q as PublishDoneStatusCode, N as PublishError, u as PublishErrorCode, P as PublishNamespace, c as PublishNamespaceCancel, Z as PublishNamespaceDone, a as PublishNamespaceError, f as PublishNamespaceErrorCode, b as PublishNamespaceOk, O as PublishOk, a2 as RequestIdMap, R as RequestsBlocked, E as ServerSetup, a4 as SetupParameter, ab as SetupParameterType, a5 as SetupParameters, a1 as SubgroupHeader, S as Subscribe, Q as SubscribeError, k as SubscribeErrorCode, H as SubscribeNamespace, I as SubscribeNamespaceError, n as SubscribeNamespaceErrorCode, J as SubscribeNamespaceOk, U as SubscribeOk, V as SubscribeUpdate, af as TokenAliasType, W as TrackStatus, T as TrackStatusCode, X as TrackStatusError, Y as TrackStatusOk, _ as Unsubscribe, $ as UnsubscribeNamespace, a6 as VersionSpecificParameter, ad as VersionSpecificParameterType, a7 as VersionSpecificParameters, aa as commonTypeFromNumber, e as controlMessageTypeFromBigInt, m as fetchErrorCodeFromBigInt, i as fetchTypeFromBigInt, g as filterTypeFromBigInt, j as groupOrderFromNumber, r as publishDoneStatusCodeFromBigInt, v as publishErrorCodeFromBigInt, p as publishNamespaceErrorCodeFromBigInt, ac as setupParameterTypeFromNumber, s as subscribeErrorCodeFromBigInt, o as subscribeNamespaceErrorCodeFromBigInt, ag as tokenAliasTypeFromNumber, t as trackStatusCodeFromBigInt, ae as versionSpecificParameterTypeFromNumber } from '../version_parameter-f75NkWiO.js';
1
+ import { s as FullTrackName, K as KeyValuePair, r as FrozenByteBuffer, B as BaseByteBuffer } from './version_parameter-DXBOBueW.cjs';
2
+ export { A as AuthTokenVariant, a as AuthorizationToken, b as ByteBuffer, C as ClientSetup, c as CommonType, d as ControlMessage, e as ControlMessageType, D as DRAFT_14, f as DatagramObject, g as DatagramStatus, h as DeliveryTimeout, F as Fetch, i as FetchCancel, j as FetchError, k as FetchErrorCode, l as FetchHeader, m as FetchHeaderType, n as FetchObject, o as FetchOk, p as FetchType, q as FilterType, G as GoAway, t as GroupOrder, H as Header, L as Location, M as MAX_FULL_TRACK_NAME_LENGTH, u as MAX_NAMESPACE_TUPLE_COUNT, v as MAX_REASON_PHRASE_LEN, w as MaxAuthTokenCacheSize, x as MaxCacheDuration, y as MaxRequestId, z as MaxRequestIdParameter, E as MoqtObject, O as ObjectDatagramStatusType, I as ObjectDatagramType, J as ObjectForwardingPreference, N as ObjectStatus, P as Parameter, Q as Path, R as Publish, S as PublishDone, T as PublishDoneStatusCode, U as PublishError, V as PublishErrorCode, W as PublishNamespace, X as PublishNamespaceCancel, Y as PublishNamespaceDone, Z as PublishNamespaceError, _ as PublishNamespaceErrorCode, $ as PublishNamespaceOk, a0 as PublishOk, a1 as ReasonPhrase, a2 as RequestIdMap, a3 as RequestsBlocked, a4 as ServerSetup, a5 as SetupParameter, a6 as SetupParameterType, a7 as SetupParameters, a8 as SubgroupHeader, a9 as SubgroupHeaderType, aa as SubgroupObject, ab as Subscribe, ac as SubscribeError, ad as SubscribeErrorCode, ae as SubscribeNamespace, af as SubscribeNamespaceError, ag as SubscribeNamespaceErrorCode, ah as SubscribeNamespaceOk, ai as SubscribeOk, aj as SubscribeUpdate, ak as TokenAliasType, al as TrackStatus, am as TrackStatusCode, an as TrackStatusError, ao as TrackStatusOk, ap as Tuple, aq as TupleField, ar as Unsubscribe, as as UnsubscribeNamespace, at as VersionSpecificParameter, au as VersionSpecificParameterType, av as VersionSpecificParameters, aw as commonTypeFromNumber, ax as controlMessageTypeFromBigInt, ay as fetchErrorCodeFromBigInt, az as fetchTypeFromBigInt, aA as filterTypeFromBigInt, aB as groupOrderFromNumber, aC as isBytes, aD as isVarInt, aE as publishDoneStatusCodeFromBigInt, aF as publishErrorCodeFromBigInt, aG as publishNamespaceErrorCodeFromBigInt, aH as setupParameterTypeFromNumber, aI as subscribeErrorCodeFromBigInt, aJ as subscribeNamespaceErrorCodeFromBigInt, aK as tokenAliasTypeFromNumber, aL as trackStatusCodeFromBigInt, aM as versionSpecificParameterTypeFromNumber } from './version_parameter-DXBOBueW.cjs';
3
+
4
+ /**
5
+ * Copyright 2026 The MOQtail Authors
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ interface CMSFTrack {
20
+ name: string;
21
+ packaging: 'cmaf' | 'chunk-per-object' | 'timeline';
22
+ codec?: string;
23
+ role: 'video' | 'audio' | 'timeline';
24
+ depends?: string[];
25
+ mimeType?: string;
26
+ width?: number;
27
+ height?: number;
28
+ timescale?: number;
29
+ bitrate?: number;
30
+ initData?: string;
31
+ }
32
+ interface CMSF {
33
+ version: number;
34
+ tracks: CMSFTrack[];
35
+ }
36
+ declare class CMSFCatalog {
37
+ #private;
38
+ private constructor();
39
+ static from(payload: ArrayBufferLike): CMSFCatalog;
40
+ getByTrackName(trackName: string): CMSFTrack | undefined;
41
+ getTracks(role?: CMSF['tracks'][number]['role']): CMSFTrack[];
42
+ getVideo(index?: number): CMSFTrack | undefined;
43
+ getAudio(index?: number): CMSFTrack | undefined;
44
+ getTimeline(index?: number): CMSFTrack | undefined;
45
+ getCodecString(trackName: string): string | undefined;
46
+ getRole(trackName: string): "timeline" | "video" | "audio" | undefined;
47
+ getPackaging(trackName: string): "cmaf" | "chunk-per-object" | "timeline" | undefined;
48
+ isCMAF(trackName: string): boolean;
49
+ getTimescale(trackName: string): number | undefined;
50
+ getInitData(trackName: string): Uint8Array<ArrayBuffer> | undefined;
51
+ private extractTrackName;
52
+ }
4
53
 
5
54
  /**
6
55
  * Copyright 2025 The MOQtail Authors
@@ -359,4 +408,4 @@ declare class ExtensionHeaders {
359
408
  static fromKeyValuePairs(kvps: KeyValuePair[]): ExtensionHeader[];
360
409
  }
361
410
 
362
- export { AudioLevel, BaseByteBuffer, CaptureTimestamp, CastingError, ExtensionHeader, ExtensionHeaders, FrozenByteBuffer, FullTrackName, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, MOQtailError, NotEnoughBytesError, ProtocolViolationError, RequestIdError, Switch, TerminationCode, TerminationError, TimeoutError, TrackNameError, VarIntOverflowError, VideoConfig, VideoFrameMarking, locHeaderExtensionIdFromNumber };
411
+ export { AudioLevel, BaseByteBuffer, type CMSF, CMSFCatalog, type CMSFTrack, CaptureTimestamp, CastingError, ExtensionHeader, ExtensionHeaders, FrozenByteBuffer, FullTrackName, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, MOQtailError, NotEnoughBytesError, ProtocolViolationError, RequestIdError, Switch, TerminationCode, TerminationError, TimeoutError, TrackNameError, VarIntOverflowError, VideoConfig, VideoFrameMarking, locHeaderExtensionIdFromNumber };
@@ -1,6 +1,55 @@
1
- import { m as FullTrackName, K as KeyValuePair, F as FrozenByteBuffer, B as BaseByteBuffer } from '../byte_buffer-BM4uNj4n.cjs';
2
- export { a as ByteBuffer, D as DatagramObject, h as DatagramStatus, e as FetchHeaderType, j as FetchObject, L as Location, l as MAX_FULL_TRACK_NAME_LENGTH, k as MAX_NAMESPACE_TUPLE_COUNT, M as MAX_REASON_PHRASE_LEN, n as MoqtObject, O as ObjectDatagramStatusType, d as ObjectDatagramType, f as ObjectForwardingPreference, g as ObjectStatus, R as ReasonPhrase, S as SubgroupHeaderType, o as SubgroupObject, c as Tuple, T as TupleField, b as isBytes, i as isVarInt } from '../byte_buffer-BM4uNj4n.cjs';
3
- export { ah as AuthTokenVariant, ai as AuthorizationToken, C as ClientSetup, a9 as CommonType, w as ControlMessage, d as ControlMessageType, D as DRAFT_14, am as DeliveryTimeout, x as Fetch, y as FetchCancel, z as FetchError, l as FetchErrorCode, a0 as FetchHeader, A as FetchOk, h as FetchType, F as FilterType, B as GoAway, G as GroupOrder, a3 as Header, al as MaxAuthTokenCacheSize, an as MaxCacheDuration, M as MaxRequestId, aj as MaxRequestIdParameter, a8 as Parameter, ak as Path, L as Publish, K as PublishDone, q as PublishDoneStatusCode, N as PublishError, u as PublishErrorCode, P as PublishNamespace, c as PublishNamespaceCancel, Z as PublishNamespaceDone, a as PublishNamespaceError, f as PublishNamespaceErrorCode, b as PublishNamespaceOk, O as PublishOk, a2 as RequestIdMap, R as RequestsBlocked, E as ServerSetup, a4 as SetupParameter, ab as SetupParameterType, a5 as SetupParameters, a1 as SubgroupHeader, S as Subscribe, Q as SubscribeError, k as SubscribeErrorCode, H as SubscribeNamespace, I as SubscribeNamespaceError, n as SubscribeNamespaceErrorCode, J as SubscribeNamespaceOk, U as SubscribeOk, V as SubscribeUpdate, af as TokenAliasType, W as TrackStatus, T as TrackStatusCode, X as TrackStatusError, Y as TrackStatusOk, _ as Unsubscribe, $ as UnsubscribeNamespace, a6 as VersionSpecificParameter, ad as VersionSpecificParameterType, a7 as VersionSpecificParameters, aa as commonTypeFromNumber, e as controlMessageTypeFromBigInt, m as fetchErrorCodeFromBigInt, i as fetchTypeFromBigInt, g as filterTypeFromBigInt, j as groupOrderFromNumber, r as publishDoneStatusCodeFromBigInt, v as publishErrorCodeFromBigInt, p as publishNamespaceErrorCodeFromBigInt, ac as setupParameterTypeFromNumber, s as subscribeErrorCodeFromBigInt, o as subscribeNamespaceErrorCodeFromBigInt, ag as tokenAliasTypeFromNumber, t as trackStatusCodeFromBigInt, ae as versionSpecificParameterTypeFromNumber } from '../version_parameter-BpmuiMQj.cjs';
1
+ import { s as FullTrackName, K as KeyValuePair, r as FrozenByteBuffer, B as BaseByteBuffer } from './version_parameter-DXBOBueW.js';
2
+ export { A as AuthTokenVariant, a as AuthorizationToken, b as ByteBuffer, C as ClientSetup, c as CommonType, d as ControlMessage, e as ControlMessageType, D as DRAFT_14, f as DatagramObject, g as DatagramStatus, h as DeliveryTimeout, F as Fetch, i as FetchCancel, j as FetchError, k as FetchErrorCode, l as FetchHeader, m as FetchHeaderType, n as FetchObject, o as FetchOk, p as FetchType, q as FilterType, G as GoAway, t as GroupOrder, H as Header, L as Location, M as MAX_FULL_TRACK_NAME_LENGTH, u as MAX_NAMESPACE_TUPLE_COUNT, v as MAX_REASON_PHRASE_LEN, w as MaxAuthTokenCacheSize, x as MaxCacheDuration, y as MaxRequestId, z as MaxRequestIdParameter, E as MoqtObject, O as ObjectDatagramStatusType, I as ObjectDatagramType, J as ObjectForwardingPreference, N as ObjectStatus, P as Parameter, Q as Path, R as Publish, S as PublishDone, T as PublishDoneStatusCode, U as PublishError, V as PublishErrorCode, W as PublishNamespace, X as PublishNamespaceCancel, Y as PublishNamespaceDone, Z as PublishNamespaceError, _ as PublishNamespaceErrorCode, $ as PublishNamespaceOk, a0 as PublishOk, a1 as ReasonPhrase, a2 as RequestIdMap, a3 as RequestsBlocked, a4 as ServerSetup, a5 as SetupParameter, a6 as SetupParameterType, a7 as SetupParameters, a8 as SubgroupHeader, a9 as SubgroupHeaderType, aa as SubgroupObject, ab as Subscribe, ac as SubscribeError, ad as SubscribeErrorCode, ae as SubscribeNamespace, af as SubscribeNamespaceError, ag as SubscribeNamespaceErrorCode, ah as SubscribeNamespaceOk, ai as SubscribeOk, aj as SubscribeUpdate, ak as TokenAliasType, al as TrackStatus, am as TrackStatusCode, an as TrackStatusError, ao as TrackStatusOk, ap as Tuple, aq as TupleField, ar as Unsubscribe, as as UnsubscribeNamespace, at as VersionSpecificParameter, au as VersionSpecificParameterType, av as VersionSpecificParameters, aw as commonTypeFromNumber, ax as controlMessageTypeFromBigInt, ay as fetchErrorCodeFromBigInt, az as fetchTypeFromBigInt, aA as filterTypeFromBigInt, aB as groupOrderFromNumber, aC as isBytes, aD as isVarInt, aE as publishDoneStatusCodeFromBigInt, aF as publishErrorCodeFromBigInt, aG as publishNamespaceErrorCodeFromBigInt, aH as setupParameterTypeFromNumber, aI as subscribeErrorCodeFromBigInt, aJ as subscribeNamespaceErrorCodeFromBigInt, aK as tokenAliasTypeFromNumber, aL as trackStatusCodeFromBigInt, aM as versionSpecificParameterTypeFromNumber } from './version_parameter-DXBOBueW.js';
3
+
4
+ /**
5
+ * Copyright 2026 The MOQtail Authors
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ interface CMSFTrack {
20
+ name: string;
21
+ packaging: 'cmaf' | 'chunk-per-object' | 'timeline';
22
+ codec?: string;
23
+ role: 'video' | 'audio' | 'timeline';
24
+ depends?: string[];
25
+ mimeType?: string;
26
+ width?: number;
27
+ height?: number;
28
+ timescale?: number;
29
+ bitrate?: number;
30
+ initData?: string;
31
+ }
32
+ interface CMSF {
33
+ version: number;
34
+ tracks: CMSFTrack[];
35
+ }
36
+ declare class CMSFCatalog {
37
+ #private;
38
+ private constructor();
39
+ static from(payload: ArrayBufferLike): CMSFCatalog;
40
+ getByTrackName(trackName: string): CMSFTrack | undefined;
41
+ getTracks(role?: CMSF['tracks'][number]['role']): CMSFTrack[];
42
+ getVideo(index?: number): CMSFTrack | undefined;
43
+ getAudio(index?: number): CMSFTrack | undefined;
44
+ getTimeline(index?: number): CMSFTrack | undefined;
45
+ getCodecString(trackName: string): string | undefined;
46
+ getRole(trackName: string): "timeline" | "video" | "audio" | undefined;
47
+ getPackaging(trackName: string): "cmaf" | "chunk-per-object" | "timeline" | undefined;
48
+ isCMAF(trackName: string): boolean;
49
+ getTimescale(trackName: string): number | undefined;
50
+ getInitData(trackName: string): Uint8Array<ArrayBuffer> | undefined;
51
+ private extractTrackName;
52
+ }
4
53
 
5
54
  /**
6
55
  * Copyright 2025 The MOQtail Authors
@@ -359,4 +408,4 @@ declare class ExtensionHeaders {
359
408
  static fromKeyValuePairs(kvps: KeyValuePair[]): ExtensionHeader[];
360
409
  }
361
410
 
362
- export { AudioLevel, BaseByteBuffer, CaptureTimestamp, CastingError, ExtensionHeader, ExtensionHeaders, FrozenByteBuffer, FullTrackName, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, MOQtailError, NotEnoughBytesError, ProtocolViolationError, RequestIdError, Switch, TerminationCode, TerminationError, TimeoutError, TrackNameError, VarIntOverflowError, VideoConfig, VideoFrameMarking, locHeaderExtensionIdFromNumber };
411
+ export { AudioLevel, BaseByteBuffer, type CMSF, CMSFCatalog, type CMSFTrack, CaptureTimestamp, CastingError, ExtensionHeader, ExtensionHeaders, FrozenByteBuffer, FullTrackName, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, MOQtailError, NotEnoughBytesError, ProtocolViolationError, RequestIdError, Switch, TerminationCode, TerminationError, TimeoutError, TrackNameError, VarIntOverflowError, VideoConfig, VideoFrameMarking, locHeaderExtensionIdFromNumber };
@@ -1,3 +1,216 @@
1
+ // src/model/catalog/cmsf.ts
2
+ function isString(v) {
3
+ return typeof v === "string";
4
+ }
5
+ function isNumber(v) {
6
+ return typeof v === "number";
7
+ }
8
+ function isStringArray(v) {
9
+ return Array.isArray(v) && v.every((item) => isString(item));
10
+ }
11
+ function isValidPackaging(v) {
12
+ return v === "cmaf" || v === "chunk-per-object" || v === "timeline";
13
+ }
14
+ function isValidRole(v) {
15
+ return v === "video" || v === "audio" || v === "timeline";
16
+ }
17
+ function isValidBase64(str) {
18
+ try {
19
+ return btoa(atob(str)) === str;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ function validateTrack(track) {
25
+ if (typeof track !== "object" || track === null) {
26
+ throw new Error("Track must be an object");
27
+ }
28
+ const t = track;
29
+ if (!isString(t["name"])) {
30
+ throw new Error("Track.name must be a string");
31
+ }
32
+ if (!isValidPackaging(t["packaging"])) {
33
+ throw new Error("Track.packaging must be 'cmaf', 'chunk-per-object', or 'timeline'");
34
+ }
35
+ if (!isValidRole(t["role"])) {
36
+ throw new Error("Track.role must be 'video', 'audio', or 'timeline'");
37
+ }
38
+ const name = t["name"];
39
+ const packaging = t["packaging"];
40
+ const role = t["role"];
41
+ let codec;
42
+ if (t["codec"] !== void 0) {
43
+ if (!isString(t["codec"])) {
44
+ throw new Error("Track.codec must be a string");
45
+ }
46
+ codec = t["codec"];
47
+ }
48
+ let depends;
49
+ if (t["depends"] !== void 0) {
50
+ if (!isStringArray(t["depends"])) {
51
+ throw new Error("Track.depends must be an array of strings");
52
+ }
53
+ depends = t["depends"];
54
+ }
55
+ let mimeType;
56
+ if (t["mimeType"] !== void 0) {
57
+ if (!isString(t["mimeType"])) {
58
+ throw new Error("Track.mimeType must be a string");
59
+ }
60
+ mimeType = t["mimeType"];
61
+ }
62
+ let width;
63
+ if (t["width"] !== void 0) {
64
+ if (!isNumber(t["width"])) {
65
+ throw new Error("Track.width must be a number");
66
+ }
67
+ width = t["width"];
68
+ }
69
+ let height;
70
+ if (t["height"] !== void 0) {
71
+ if (!isNumber(t["height"])) {
72
+ throw new Error("Track.height must be a number");
73
+ }
74
+ height = t["height"];
75
+ }
76
+ let timescale;
77
+ if (t["timescale"] !== void 0) {
78
+ if (!isNumber(t["timescale"])) {
79
+ throw new Error("Track.timescale must be a number");
80
+ }
81
+ timescale = t["timescale"];
82
+ }
83
+ let bitrate;
84
+ if (t["bitrate"] !== void 0) {
85
+ if (!isNumber(t["bitrate"])) {
86
+ throw new Error("Track.bitrate must be a number");
87
+ }
88
+ bitrate = t["bitrate"];
89
+ }
90
+ let initData;
91
+ if (t["initData"] !== void 0) {
92
+ if (!isString(t["initData"])) {
93
+ throw new Error("Track.initData must be a string");
94
+ }
95
+ if (!isValidBase64(t["initData"])) {
96
+ throw new Error("Track.initData must be a valid base64 string");
97
+ }
98
+ initData = t["initData"];
99
+ }
100
+ if (packaging === "cmaf" && (!codec || codec.length === 0)) {
101
+ throw new Error("codec is required when packaging is 'cmaf'");
102
+ }
103
+ if (packaging === "timeline" && mimeType !== "text/csv") {
104
+ throw new Error("mimeType must be 'text/csv' when packaging is 'timeline'");
105
+ }
106
+ if (packaging === "timeline" && (!depends || depends.length === 0)) {
107
+ throw new Error("At least one dependee must be present when packaging is 'timeline'");
108
+ }
109
+ const result = {
110
+ name,
111
+ packaging,
112
+ role
113
+ };
114
+ if (codec !== void 0) result.codec = codec;
115
+ if (depends !== void 0) result.depends = depends;
116
+ if (mimeType !== void 0) result.mimeType = mimeType;
117
+ if (width !== void 0) result.width = width;
118
+ if (height !== void 0) result.height = height;
119
+ if (timescale !== void 0) result.timescale = timescale;
120
+ if (bitrate !== void 0) result.bitrate = bitrate;
121
+ if (initData !== void 0) result.initData = initData;
122
+ return result;
123
+ }
124
+ function validateCMSF(obj) {
125
+ if (typeof obj !== "object" || obj === null) {
126
+ throw new Error("CMSF must be an object");
127
+ }
128
+ const o = obj;
129
+ if (!isNumber(o["version"])) {
130
+ throw new Error("CMSF.version must be a number");
131
+ }
132
+ if (!Array.isArray(o["tracks"])) {
133
+ throw new Error("CMSF.tracks must be an array");
134
+ }
135
+ const version = o["version"];
136
+ const tracksArray = o["tracks"];
137
+ const tracks = tracksArray.map(validateTrack);
138
+ return {
139
+ version,
140
+ tracks
141
+ };
142
+ }
143
+ var CMSFCatalog = class _CMSFCatalog {
144
+ #catalog;
145
+ constructor(catalog) {
146
+ this.#catalog = catalog;
147
+ }
148
+ static from(payload) {
149
+ const decoder = new TextDecoder();
150
+ const json = decoder.decode(payload);
151
+ const catalog = validateCMSF(JSON.parse(json));
152
+ return new _CMSFCatalog(catalog);
153
+ }
154
+ getByTrackName(trackName) {
155
+ return this.#catalog.tracks.find((track) => track.name === this.extractTrackName(trackName));
156
+ }
157
+ getTracks(role) {
158
+ if (role) return this.#catalog.tracks.filter((track) => track.role === role);
159
+ return this.#catalog.tracks;
160
+ }
161
+ getVideo(index = 0) {
162
+ const videos = this.#catalog.tracks.filter((track) => track.role === "video");
163
+ if (index < 0 || index >= videos.length) return void 0;
164
+ return videos[index];
165
+ }
166
+ getAudio(index = 0) {
167
+ const audios = this.#catalog.tracks.filter((track) => track.role === "audio");
168
+ if (index < 0 || index >= audios.length) return void 0;
169
+ return audios[index];
170
+ }
171
+ getTimeline(index = 0) {
172
+ const timelines = this.#catalog.tracks.filter((track) => track.role === "timeline");
173
+ if (index < 0 || index >= timelines.length) return void 0;
174
+ return timelines[index];
175
+ }
176
+ getCodecString(trackName) {
177
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
178
+ if (!track) return void 0;
179
+ if (!track.codec) throw new Error(`Track ${trackName} does not have a codec`);
180
+ return track.codec;
181
+ }
182
+ getRole(trackName) {
183
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
184
+ if (!track) return void 0;
185
+ return track.role;
186
+ }
187
+ getPackaging(trackName) {
188
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
189
+ if (!track) return void 0;
190
+ return track.packaging;
191
+ }
192
+ isCMAF(trackName) {
193
+ const packaging = this.getPackaging(trackName);
194
+ return packaging === "cmaf" || packaging === "chunk-per-object";
195
+ }
196
+ getTimescale(trackName) {
197
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
198
+ return track?.timescale;
199
+ }
200
+ getInitData(trackName) {
201
+ const track = this.#catalog.tracks.find((track2) => track2.name === this.extractTrackName(trackName));
202
+ if (!track) return void 0;
203
+ if (!track.initData) throw new Error(`Track ${trackName} does not have initData`);
204
+ return new Uint8Array(
205
+ atob(track.initData).split("").map((c) => c.charCodeAt(0))
206
+ );
207
+ }
208
+ extractTrackName(input) {
209
+ const parts = input.split("/");
210
+ return parts[parts.length - 1];
211
+ }
212
+ };
213
+
1
214
  // src/model/error/error.ts
2
215
  var MOQtailError = class extends Error {
3
216
  constructor(cause) {
@@ -4705,4 +4918,4 @@ var VersionSpecificParameters = class {
4705
4918
  }
4706
4919
  };
4707
4920
 
4708
- export { AudioLevel, AuthorizationToken, BaseByteBuffer12 as BaseByteBuffer, ByteBuffer, CaptureTimestamp, CastingError, ClientSetup, CommonType, ControlMessage, ControlMessageType, DRAFT_14, DatagramObject, DatagramStatus, DeliveryTimeout, ExtensionHeader, ExtensionHeaders, Fetch, FetchCancel, FetchError, FetchErrorCode, FetchHeader, FetchHeaderType, FetchObject, FetchOk, FetchType, FilterType, FrozenByteBuffer5 as FrozenByteBuffer, FullTrackName, GoAway, GroupOrder, Header, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, Location, MAX_FULL_TRACK_NAME_LENGTH, MAX_NAMESPACE_TUPLE_COUNT, MAX_REASON_PHRASE_LEN, MOQtailError, MaxAuthTokenCacheSize, MaxCacheDuration, MaxRequestId, MaxRequestId2 as MaxRequestIdParameter, MoqtObject, NotEnoughBytesError, ObjectDatagramStatusType, ObjectDatagramType, ObjectForwardingPreference, ObjectStatus, Path, ProtocolViolationError, Publish, PublishDone, PublishDoneStatusCode, PublishError, PublishErrorCode, PublishNamespace, PublishNamespaceCancel, PublishNamespaceDone, PublishNamespaceError, PublishNamespaceErrorCode, PublishNamespaceOk, PublishOk, ReasonPhrase, RequestIdError, RequestIdMap, RequestsBlocked, ServerSetup, SetupParameter, SetupParameterType, SetupParameters, SubgroupHeader, SubgroupHeaderType, SubgroupObject, Subscribe, SubscribeError, SubscribeErrorCode, SubscribeNamespace, SubscribeNamespaceError, SubscribeNamespaceErrorCode, SubscribeNamespaceOk, SubscribeOk, 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 };
4921
+ export { AudioLevel, AuthorizationToken, BaseByteBuffer12 as BaseByteBuffer, ByteBuffer, CMSFCatalog, CaptureTimestamp, CastingError, ClientSetup, CommonType, ControlMessage, ControlMessageType, DRAFT_14, DatagramObject, DatagramStatus, DeliveryTimeout, ExtensionHeader, ExtensionHeaders, Fetch, FetchCancel, FetchError, FetchErrorCode, FetchHeader, FetchHeaderType, FetchObject, FetchOk, FetchType, FilterType, FrozenByteBuffer5 as FrozenByteBuffer, FullTrackName, GoAway, GroupOrder, Header, InternalError, InvalidTypeError, InvalidUTF8Error, KeyValueFormattingError, KeyValuePair, LOCHeaderExtensionId, LengthExceedsMaxError, Location, MAX_FULL_TRACK_NAME_LENGTH, MAX_NAMESPACE_TUPLE_COUNT, MAX_REASON_PHRASE_LEN, MOQtailError, MaxAuthTokenCacheSize, MaxCacheDuration, MaxRequestId, MaxRequestId2 as MaxRequestIdParameter, MoqtObject, NotEnoughBytesError, ObjectDatagramStatusType, ObjectDatagramType, ObjectForwardingPreference, ObjectStatus, Path, ProtocolViolationError, Publish, PublishDone, PublishDoneStatusCode, PublishError, PublishErrorCode, PublishNamespace, PublishNamespaceCancel, PublishNamespaceDone, PublishNamespaceError, PublishNamespaceErrorCode, PublishNamespaceOk, PublishOk, ReasonPhrase, RequestIdError, RequestIdMap, RequestsBlocked, ServerSetup, SetupParameter, SetupParameterType, SetupParameters, SubgroupHeader, SubgroupHeaderType, SubgroupObject, Subscribe, SubscribeError, SubscribeErrorCode, SubscribeNamespace, SubscribeNamespaceError, SubscribeNamespaceErrorCode, SubscribeNamespaceOk, SubscribeOk, 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 };