@norskvideo/moq-hang 0.1.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.
Files changed (130) hide show
  1. package/README.md +65 -0
  2. package/catalog/audio.d.ts +139 -0
  3. package/catalog/audio.d.ts.map +1 -0
  4. package/catalog/audio.js +55 -0
  5. package/catalog/audio.js.map +1 -0
  6. package/catalog/consumer.d.ts +34 -0
  7. package/catalog/consumer.d.ts.map +1 -0
  8. package/catalog/consumer.js +30 -0
  9. package/catalog/consumer.js.map +1 -0
  10. package/catalog/container.d.ts +24 -0
  11. package/catalog/container.d.ts.map +1 -0
  12. package/catalog/container.js +30 -0
  13. package/catalog/container.js.map +1 -0
  14. package/catalog/format.d.ts +13 -0
  15. package/catalog/format.d.ts.map +1 -0
  16. package/catalog/format.js +24 -0
  17. package/catalog/format.js.map +1 -0
  18. package/catalog/index.d.ts +18 -0
  19. package/catalog/index.d.ts.map +1 -0
  20. package/catalog/index.js +19 -0
  21. package/catalog/index.js.map +1 -0
  22. package/catalog/integers.d.ts +23 -0
  23. package/catalog/integers.d.ts.map +1 -0
  24. package/catalog/integers.js +24 -0
  25. package/catalog/integers.js.map +1 -0
  26. package/catalog/priority.d.ts +7 -0
  27. package/catalog/priority.d.ts.map +1 -0
  28. package/catalog/priority.js +9 -0
  29. package/catalog/priority.js.map +1 -0
  30. package/catalog/producer.d.ts +31 -0
  31. package/catalog/producer.d.ts.map +1 -0
  32. package/catalog/producer.js +25 -0
  33. package/catalog/producer.js.map +1 -0
  34. package/catalog/root.d.ts +252 -0
  35. package/catalog/root.d.ts.map +1 -0
  36. package/catalog/root.js +17 -0
  37. package/catalog/root.js.map +1 -0
  38. package/catalog/root.test.d.ts +2 -0
  39. package/catalog/root.test.d.ts.map +1 -0
  40. package/catalog/root.test.js +20 -0
  41. package/catalog/root.test.js.map +1 -0
  42. package/catalog/timeline.d.ts +26 -0
  43. package/catalog/timeline.d.ts.map +1 -0
  44. package/catalog/timeline.js +33 -0
  45. package/catalog/timeline.js.map +1 -0
  46. package/catalog/track.d.ts +8 -0
  47. package/catalog/track.d.ts.map +1 -0
  48. package/catalog/track.js +7 -0
  49. package/catalog/track.js.map +1 -0
  50. package/catalog/video.d.ts +171 -0
  51. package/catalog/video.d.ts.map +1 -0
  52. package/catalog/video.js +87 -0
  53. package/catalog/video.js.map +1 -0
  54. package/container/cmaf/decode.d.ts +68 -0
  55. package/container/cmaf/decode.d.ts.map +1 -0
  56. package/container/cmaf/decode.js +303 -0
  57. package/container/cmaf/decode.js.map +1 -0
  58. package/container/cmaf/encode.d.ts +51 -0
  59. package/container/cmaf/encode.d.ts.map +1 -0
  60. package/container/cmaf/encode.js +834 -0
  61. package/container/cmaf/encode.js.map +1 -0
  62. package/container/cmaf/format.d.ts +12 -0
  63. package/container/cmaf/format.d.ts.map +1 -0
  64. package/container/cmaf/format.js +19 -0
  65. package/container/cmaf/format.js.map +1 -0
  66. package/container/cmaf/index.d.ts +9 -0
  67. package/container/cmaf/index.d.ts.map +1 -0
  68. package/container/cmaf/index.js +10 -0
  69. package/container/cmaf/index.js.map +1 -0
  70. package/container/consumer.d.ts +41 -0
  71. package/container/consumer.d.ts.map +1 -0
  72. package/container/consumer.js +424 -0
  73. package/container/consumer.js.map +1 -0
  74. package/container/consumer.test.d.ts +2 -0
  75. package/container/consumer.test.d.ts.map +1 -0
  76. package/container/consumer.test.js +396 -0
  77. package/container/consumer.test.js.map +1 -0
  78. package/container/format.d.ts +12 -0
  79. package/container/format.d.ts.map +1 -0
  80. package/container/format.js +3 -0
  81. package/container/format.js.map +1 -0
  82. package/container/index.d.ts +14 -0
  83. package/container/index.d.ts.map +1 -0
  84. package/container/index.js +18 -0
  85. package/container/index.js.map +1 -0
  86. package/container/legacy.d.ts +39 -0
  87. package/container/legacy.d.ts.map +1 -0
  88. package/container/legacy.js +53 -0
  89. package/container/legacy.js.map +1 -0
  90. package/container/timeline.d.ts +67 -0
  91. package/container/timeline.d.ts.map +1 -0
  92. package/container/timeline.js +87 -0
  93. package/container/timeline.js.map +1 -0
  94. package/container/types.d.ts +22 -0
  95. package/container/types.d.ts.map +1 -0
  96. package/container/types.js +22 -0
  97. package/container/types.js.map +1 -0
  98. package/index.d.ts +13 -0
  99. package/index.d.ts.map +1 -0
  100. package/index.js +18 -0
  101. package/index.js.map +1 -0
  102. package/package.json +37 -0
  103. package/util/aac.d.ts +8 -0
  104. package/util/aac.d.ts.map +1 -0
  105. package/util/aac.js +57 -0
  106. package/util/aac.js.map +1 -0
  107. package/util/aac.test.d.ts +2 -0
  108. package/util/aac.test.d.ts.map +1 -0
  109. package/util/aac.test.js +34 -0
  110. package/util/aac.test.js.map +1 -0
  111. package/util/hacks.d.ts +5 -0
  112. package/util/hacks.d.ts.map +1 -0
  113. package/util/hacks.js +6 -0
  114. package/util/hacks.js.map +1 -0
  115. package/util/hex.d.ts +5 -0
  116. package/util/hex.d.ts.map +1 -0
  117. package/util/hex.js +18 -0
  118. package/util/hex.js.map +1 -0
  119. package/util/index.d.ts +12 -0
  120. package/util/index.d.ts.map +1 -0
  121. package/util/index.js +18 -0
  122. package/util/index.js.map +1 -0
  123. package/util/latency.d.ts +38 -0
  124. package/util/latency.d.ts.map +1 -0
  125. package/util/latency.js +49 -0
  126. package/util/latency.js.map +1 -0
  127. package/util/libav.d.ts +3 -0
  128. package/util/libav.d.ts.map +1 -0
  129. package/util/libav.js +26 -0
  130. package/util/libav.js.map +1 -0
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ <p align="center">
2
+ <img height="128px" src="https://github.com/moq-dev/moq/blob/main/.github/logo.svg" alt="Media over QUIC">
3
+ </p>
4
+
5
+ # @moq/hang
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@moq/hang)](https://www.npmjs.com/package/@moq/hang)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-ready-blue.svg)](https://www.typescriptlang.org/)
9
+
10
+ Core media library for [Media over QUIC](https://moq.dev/) (MoQ). Provides shared primitives used by [`@moq/watch`](../watch) and [`@moq/publish`](../publish), built on top of [`@moq/net`](../lite).
11
+
12
+ ## Features
13
+
14
+ - **Catalog** — JSON track describing other tracks and their codec properties (audio, video, chat, location, etc.)
15
+ - **Container** — Media framing in two formats: CMAF (fMP4) and Legacy (varint-timestamp + raw codec bitstream)
16
+ - **Utilities** — Hex encoding, Opus audio polyfill (libav), latency computation, browser detection workarounds
17
+
18
+ Browser support detection is provided by [`<moq-watch-support>`](../watch) and [`<moq-publish-support>`](../publish).
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm add @moq/hang
24
+ # or
25
+ pnpm add @moq/hang
26
+ yarn add @moq/hang
27
+ bun add @moq/hang
28
+ ```
29
+
30
+ ## JavaScript API
31
+
32
+ ```typescript
33
+ import * as Hang from "@moq/hang";
34
+
35
+ // Catalog — describes tracks and their codec properties
36
+ import * as Catalog from "@moq/hang/catalog";
37
+
38
+ // Container — media framing (CMAF and Legacy formats)
39
+ import * as Container from "@moq/hang/container";
40
+
41
+ // CMAF (fMP4) and Legacy (varint-timestamp + raw bitstream) are both available:
42
+ // Container.Cmaf — createVideoInitSegment, createAudioInitSegment, encodeDataSegment, decodeDataSegment, etc.
43
+ // Container.Legacy — Producer / Consumer classes
44
+ ```
45
+
46
+ For watching and publishing, use the dedicated packages:
47
+
48
+ ```typescript
49
+ import * as Watch from "@moq/watch";
50
+ import * as Publish from "@moq/publish";
51
+ ```
52
+
53
+ ## Related Packages
54
+
55
+ - **[@moq/watch](../watch)** — Subscribe to and render MoQ broadcasts
56
+ - **[@moq/publish](../publish)** — Publish media to MoQ broadcasts
57
+ - **[@moq/net](../lite)** — Core pub/sub transport protocol
58
+ - **[@moq/signals](../signals)** — Reactive signals library
59
+
60
+ ## License
61
+
62
+ Licensed under either:
63
+
64
+ - Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
65
+ - MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT)
@@ -0,0 +1,139 @@
1
+ import * as z from "zod/mini";
2
+ /**
3
+ * Schema for a single audio rendition's decoder config.
4
+ * Mirrors WebCodecs AudioDecoderConfig (https://w3c.github.io/webcodecs/#audio-decoder-config).
5
+ */
6
+ export declare const AudioConfigSchema: z.ZodMiniObject<{
7
+ codec: z.ZodMiniString<string>;
8
+ container: z.ZodMiniDefault<z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
9
+ kind: z.ZodMiniLiteral<"legacy">;
10
+ }, z.core.$strip>, z.ZodMiniObject<{
11
+ kind: z.ZodMiniLiteral<"cmaf">;
12
+ init: z.ZodMiniBase64;
13
+ timescale: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
14
+ trackId: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
15
+ }, z.core.$strip>, z.ZodMiniObject<{
16
+ kind: z.ZodMiniLiteral<"loc">;
17
+ }, z.core.$strip>], "kind">>;
18
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
19
+ sampleRate: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
20
+ numberOfChannels: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
21
+ bitrate: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
22
+ jitter: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
23
+ timeline: z.ZodMiniOptional<z.ZodMiniObject<{
24
+ track: z.ZodMiniString<string>;
25
+ timescale: z.ZodMiniDefault<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
26
+ wall: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
27
+ }, z.core.$strip>>;
28
+ }, z.core.$strip>;
29
+ /** Schema for the catalog audio section: a map of track name to rendition config. */
30
+ export declare const AudioSchema: z.ZodMiniUnion<readonly [z.ZodMiniObject<{
31
+ renditions: z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniObject<{
32
+ codec: z.ZodMiniString<string>;
33
+ container: z.ZodMiniDefault<z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
34
+ kind: z.ZodMiniLiteral<"legacy">;
35
+ }, z.core.$strip>, z.ZodMiniObject<{
36
+ kind: z.ZodMiniLiteral<"cmaf">;
37
+ init: z.ZodMiniBase64;
38
+ timescale: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
39
+ trackId: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
40
+ }, z.core.$strip>, z.ZodMiniObject<{
41
+ kind: z.ZodMiniLiteral<"loc">;
42
+ }, z.core.$strip>], "kind">>;
43
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
44
+ sampleRate: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
45
+ numberOfChannels: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
46
+ bitrate: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
47
+ jitter: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
48
+ timeline: z.ZodMiniOptional<z.ZodMiniObject<{
49
+ track: z.ZodMiniString<string>;
50
+ timescale: z.ZodMiniDefault<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
51
+ wall: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
52
+ }, z.core.$strip>>;
53
+ }, z.core.$strip>>;
54
+ }, z.core.$strip>, z.ZodMiniPipe<z.ZodMiniObject<{
55
+ track: z.ZodMiniObject<{
56
+ name: z.ZodMiniString<string>;
57
+ }, z.core.$strip>;
58
+ config: z.ZodMiniObject<{
59
+ codec: z.ZodMiniString<string>;
60
+ container: z.ZodMiniDefault<z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
61
+ kind: z.ZodMiniLiteral<"legacy">;
62
+ }, z.core.$strip>, z.ZodMiniObject<{
63
+ kind: z.ZodMiniLiteral<"cmaf">;
64
+ init: z.ZodMiniBase64;
65
+ timescale: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
66
+ trackId: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
67
+ }, z.core.$strip>, z.ZodMiniObject<{
68
+ kind: z.ZodMiniLiteral<"loc">;
69
+ }, z.core.$strip>], "kind">>;
70
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
71
+ sampleRate: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
72
+ numberOfChannels: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
73
+ bitrate: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
74
+ jitter: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
75
+ timeline: z.ZodMiniOptional<z.ZodMiniObject<{
76
+ track: z.ZodMiniString<string>;
77
+ timescale: z.ZodMiniDefault<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
78
+ wall: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
79
+ }, z.core.$strip>>;
80
+ }, z.core.$strip>;
81
+ }, z.core.$strip>, z.ZodMiniTransform<{
82
+ renditions: {
83
+ [x: string]: {
84
+ codec: string;
85
+ container: {
86
+ kind: "legacy";
87
+ } | {
88
+ kind: "cmaf";
89
+ init: string;
90
+ timescale?: (number & z.$brand<"u53">) | undefined;
91
+ trackId?: (number & z.$brand<"u53">) | undefined;
92
+ } | {
93
+ kind: "loc";
94
+ };
95
+ description?: string | undefined;
96
+ sampleRate: number & z.$brand<"u53">;
97
+ numberOfChannels: number & z.$brand<"u53">;
98
+ bitrate?: (number & z.$brand<"u53">) | undefined;
99
+ jitter?: (number & z.$brand<"u53">) | undefined;
100
+ timeline?: {
101
+ track: string;
102
+ timescale: number & z.$brand<"u53">;
103
+ wall?: (number & z.$brand<"u53">) | undefined;
104
+ } | undefined;
105
+ };
106
+ };
107
+ }, {
108
+ track: {
109
+ name: string;
110
+ };
111
+ config: {
112
+ codec: string;
113
+ container: {
114
+ kind: "legacy";
115
+ } | {
116
+ kind: "cmaf";
117
+ init: string;
118
+ timescale?: (number & z.$brand<"u53">) | undefined;
119
+ trackId?: (number & z.$brand<"u53">) | undefined;
120
+ } | {
121
+ kind: "loc";
122
+ };
123
+ description?: string | undefined;
124
+ sampleRate: number & z.$brand<"u53">;
125
+ numberOfChannels: number & z.$brand<"u53">;
126
+ bitrate?: (number & z.$brand<"u53">) | undefined;
127
+ jitter?: (number & z.$brand<"u53">) | undefined;
128
+ timeline?: {
129
+ track: string;
130
+ timescale: number & z.$brand<"u53">;
131
+ wall?: (number & z.$brand<"u53">) | undefined;
132
+ } | undefined;
133
+ };
134
+ }>>]>;
135
+ /** The catalog audio section: renditions keyed by track name. */
136
+ export type Audio = z.infer<typeof AudioSchema>;
137
+ /** Decoder config for a single audio rendition. */
138
+ export type AudioConfig = z.infer<typeof AudioConfigSchema>;
139
+ //# sourceMappingURL=audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../src/catalog/audio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAU9B;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;iBAgC5B,CAAC;AAEH,qFAAqF;AACrF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgBtB,CAAC;AAEH,iEAAiE;AACjE,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAChD,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,55 @@
1
+ /* @ts-self-types="./audio.d.ts" */
2
+ import * as z from "zod/mini";
3
+ import { ContainerSchema } from "./container";
4
+ import { u53Schema } from "./integers";
5
+ import { TimelineSchema } from "./timeline";
6
+ // Backwards compatibility: old track schema
7
+ const TrackSchema = z.object({
8
+ name: z.string(),
9
+ });
10
+ /**
11
+ * Schema for a single audio rendition's decoder config.
12
+ * Mirrors WebCodecs AudioDecoderConfig (https://w3c.github.io/webcodecs/#audio-decoder-config).
13
+ */
14
+ export const AudioConfigSchema = z.object({
15
+ // See: https://w3c.github.io/webcodecs/codec_registry.html
16
+ codec: z.string(),
17
+ // The container format, used to decode the timestamp and more.
18
+ container: ContainerSchema,
19
+ // The description is used for some codecs.
20
+ // If provided, we can initialize the decoder based on the catalog alone.
21
+ // Otherwise, the initialization information is in-band.
22
+ description: z.optional(z.string()), // hex encoded TODO use base64
23
+ // The sample rate of the audio in Hz
24
+ sampleRate: u53Schema,
25
+ // The number of channels in the audio
26
+ numberOfChannels: u53Schema,
27
+ // The bitrate of the audio in bits per second
28
+ // TODO: Support up to Number.MAX_SAFE_INTEGER
29
+ bitrate: z.optional(u53Schema),
30
+ // The maximum jitter before the next frame is emitted in milliseconds.
31
+ // The player's jitter buffer should be larger than this value.
32
+ // If not provided, the player should assume each frame is flushed immediately.
33
+ //
34
+ // NOTE: The audio "frame" duration depends on the codec, sample rate, etc.
35
+ // ex: AAC often uses 1024 samples per frame, so at 44100Hz, this would be 1024/44100 = 23ms
36
+ jitter: z.optional(u53Schema),
37
+ // The companion timeline track indexing this rendition's groups, if the publisher offers one.
38
+ timeline: z.optional(TimelineSchema),
39
+ });
40
+ /** Schema for the catalog audio section: a map of track name to rendition config. */
41
+ export const AudioSchema = z.union([
42
+ z.object({
43
+ // A map of track name to rendition configuration.
44
+ // This is not an array so it will work with JSON Merge Patch.
45
+ renditions: z.record(z.string(), AudioConfigSchema),
46
+ }),
47
+ // Backwards compatibility: transform old {track, config} format to new object format
48
+ z.pipe(z.object({
49
+ track: TrackSchema,
50
+ config: AudioConfigSchema,
51
+ }), z.transform((old) => ({
52
+ renditions: { [old.track.name]: old.config },
53
+ }))),
54
+ ]);
55
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../src/catalog/audio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,4CAA4C;AAC5C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,2DAA2D;IAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IAEjB,+DAA+D;IAC/D,SAAS,EAAE,eAAe;IAE1B,2CAA2C;IAC3C,yEAAyE;IACzE,wDAAwD;IACxD,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,8BAA8B;IAEnE,qCAAqC;IACrC,UAAU,EAAE,SAAS;IAErB,sCAAsC;IACtC,gBAAgB,EAAE,SAAS;IAE3B,8CAA8C;IAC9C,8CAA8C;IAC9C,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;IAE9B,uEAAuE;IACvE,+DAA+D;IAC/D,+EAA+E;IAC/E,EAAE;IACF,2EAA2E;IAC3E,4FAA4F;IAC5F,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;IAE7B,8FAA8F;IAC9F,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;CACpC,CAAC,CAAC;AAEH,qFAAqF;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC;IAClC,CAAC,CAAC,MAAM,CAAC;QACR,kDAAkD;QAClD,8DAA8D;QAC9D,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC;KACnD,CAAC;IACF,qFAAqF;IACrF,CAAC,CAAC,IAAI,CACL,CAAC,CAAC,MAAM,CAAC;QACR,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,iBAAiB;KACzB,CAAC,EACF,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrB,UAAU,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;KAC5C,CAAC,CAAC,CACH;CACD,CAAC,CAAC","sourcesContent":["import * as z from \"zod/mini\";\nimport { ContainerSchema } from \"./container\";\nimport { u53Schema } from \"./integers\";\nimport { TimelineSchema } from \"./timeline\";\n\n// Backwards compatibility: old track schema\nconst TrackSchema = z.object({\n\tname: z.string(),\n});\n\n/**\n * Schema for a single audio rendition's decoder config.\n * Mirrors WebCodecs AudioDecoderConfig (https://w3c.github.io/webcodecs/#audio-decoder-config).\n */\nexport const AudioConfigSchema = z.object({\n\t// See: https://w3c.github.io/webcodecs/codec_registry.html\n\tcodec: z.string(),\n\n\t// The container format, used to decode the timestamp and more.\n\tcontainer: ContainerSchema,\n\n\t// The description is used for some codecs.\n\t// If provided, we can initialize the decoder based on the catalog alone.\n\t// Otherwise, the initialization information is in-band.\n\tdescription: z.optional(z.string()), // hex encoded TODO use base64\n\n\t// The sample rate of the audio in Hz\n\tsampleRate: u53Schema,\n\n\t// The number of channels in the audio\n\tnumberOfChannels: u53Schema,\n\n\t// The bitrate of the audio in bits per second\n\t// TODO: Support up to Number.MAX_SAFE_INTEGER\n\tbitrate: z.optional(u53Schema),\n\n\t// The maximum jitter before the next frame is emitted in milliseconds.\n\t// The player's jitter buffer should be larger than this value.\n\t// If not provided, the player should assume each frame is flushed immediately.\n\t//\n\t// NOTE: The audio \"frame\" duration depends on the codec, sample rate, etc.\n\t// ex: AAC often uses 1024 samples per frame, so at 44100Hz, this would be 1024/44100 = 23ms\n\tjitter: z.optional(u53Schema),\n\n\t// The companion timeline track indexing this rendition's groups, if the publisher offers one.\n\ttimeline: z.optional(TimelineSchema),\n});\n\n/** Schema for the catalog audio section: a map of track name to rendition config. */\nexport const AudioSchema = z.union([\n\tz.object({\n\t\t// A map of track name to rendition configuration.\n\t\t// This is not an array so it will work with JSON Merge Patch.\n\t\trenditions: z.record(z.string(), AudioConfigSchema),\n\t}),\n\t// Backwards compatibility: transform old {track, config} format to new object format\n\tz.pipe(\n\t\tz.object({\n\t\t\ttrack: TrackSchema,\n\t\t\tconfig: AudioConfigSchema,\n\t\t}),\n\t\tz.transform((old) => ({\n\t\t\trenditions: { [old.track.name]: old.config },\n\t\t})),\n\t),\n]);\n\n/** The catalog audio section: renditions keyed by track name. */\nexport type Audio = z.infer<typeof AudioSchema>;\n/** Decoder config for a single audio rendition. */\nexport type AudioConfig = z.infer<typeof AudioConfigSchema>;\n"]}
@@ -0,0 +1,34 @@
1
+ import * as Json from "@norskvideo/moq-json";
2
+ import type * as Moq from "@norskvideo/moq-net";
3
+ import type * as z from "zod/mini";
4
+ import { type Root } from "./root";
5
+ /** Options for a catalog {@link Consumer}. */
6
+ export interface ConsumerConfig<T extends Root = Root> {
7
+ /** zod schema validating each catalog. Defaults to {@link RootSchema}. */
8
+ schema?: z.ZodMiniType<T>;
9
+ /**
10
+ * Whether the track's frames are DEFLATE-compressed (the `catalog.json.z` track). Must match the
11
+ * publisher. Defaults to `false`.
12
+ */
13
+ compression?: boolean;
14
+ }
15
+ /**
16
+ * Consumes a {@link Root} catalog from a track, reconstructing it from snapshots and deltas.
17
+ *
18
+ * A thin wrapper around the `@norskvideo/moq-json` consumer, pre-wired with {@link RootSchema}. Call `next()`
19
+ * to get each catalog as it changes, or iterate it. Pass an extended schema (built via
20
+ * `z.extend(RootSchema, ...)`) to validate and type application sections; otherwise unknown
21
+ * sections pass through untouched. Set `compression` to read the `catalog.json.z` track.
22
+ */
23
+ export declare class Consumer<T extends Root = Root> extends Json.Snapshot.Consumer<T> {
24
+ /** Wrap `track`, validating each catalog against `config.schema` (defaults to {@link RootSchema}). */
25
+ constructor(track: Moq.Track, config?: ConsumerConfig<T>);
26
+ }
27
+ /**
28
+ * Read the current catalog from `track` once.
29
+ *
30
+ * @deprecated Use {@link Consumer} instead: `new Catalog.Consumer(track).next()`. A one-shot read
31
+ * returns only the current catalog and misses later updates (and deltas, once enabled).
32
+ */
33
+ export declare function fetch(track: Moq.Track): Promise<Root | undefined>;
34
+ //# sourceMappingURL=consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/catalog/consumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,KAAK,GAAG,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,KAAK,IAAI,EAAc,MAAM,WAAW,CAAC;AAElD,8CAA8C;AAC9C,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,IAAI,GAAG,IAAI;IACpD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAE1B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ,CAAC,CAAC,SAAS,IAAI,GAAG,IAAI,CAAE,SAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7E,sGAAsG;IACtG,YAAY,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,GAAE,cAAc,CAAC,CAAC,CAAM,EAK3D;CACD;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAEjE"}
@@ -0,0 +1,30 @@
1
+ /* @ts-self-types="./consumer.d.ts" */
2
+ import * as Json from "@norskvideo/moq-json";
3
+ import { RootSchema } from "./root.js";
4
+ /**
5
+ * Consumes a {@link Root} catalog from a track, reconstructing it from snapshots and deltas.
6
+ *
7
+ * A thin wrapper around the `@norskvideo/moq-json` consumer, pre-wired with {@link RootSchema}. Call `next()`
8
+ * to get each catalog as it changes, or iterate it. Pass an extended schema (built via
9
+ * `z.extend(RootSchema, ...)`) to validate and type application sections; otherwise unknown
10
+ * sections pass through untouched. Set `compression` to read the `catalog.json.z` track.
11
+ */
12
+ export class Consumer extends Json.Snapshot.Consumer {
13
+ /** Wrap `track`, validating each catalog against `config.schema` (defaults to {@link RootSchema}). */
14
+ constructor(track, config = {}) {
15
+ super(track, {
16
+ schema: (config.schema ?? RootSchema),
17
+ compression: config.compression,
18
+ });
19
+ }
20
+ }
21
+ /**
22
+ * Read the current catalog from `track` once.
23
+ *
24
+ * @deprecated Use {@link Consumer} instead: `new Catalog.Consumer(track).next()`. A one-shot read
25
+ * returns only the current catalog and misses later updates (and deltas, once enabled).
26
+ */
27
+ export function fetch(track) {
28
+ return new Consumer(track).next();
29
+ }
30
+ //# sourceMappingURL=consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.js","sourceRoot":"","sources":["../../src/catalog/consumer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAa,UAAU,EAAE,MAAM,WAAW,CAAC;AAclD;;;;;;;GAOG;AACH,MAAM,OAAO,QAAgC,SAAQ,IAAI,CAAC,QAAQ,CAAC,QAAW;IAC7E,sGAAsG;IACtG,YAAY,KAAgB,EAAE,MAAM,GAAsB,EAAE;QAC3D,KAAK,CAAC,KAAK,EAAE;YACZ,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,UAAU,CAAqB;YACzD,WAAW,EAAE,MAAM,CAAC,WAAW;SAC/B,CAAC,CAAC;IACJ,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,KAAgB;IACrC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import * as Json from \"@moq/json\";\nimport type * as Moq from \"@moq/net\";\nimport type * as z from \"zod/mini\";\n\nimport { type Root, RootSchema } from \"./root.ts\";\n\n/** Options for a catalog {@link Consumer}. */\nexport interface ConsumerConfig<T extends Root = Root> {\n\t/** zod schema validating each catalog. Defaults to {@link RootSchema}. */\n\tschema?: z.ZodMiniType<T>;\n\n\t/**\n\t * Whether the track's frames are DEFLATE-compressed (the `catalog.json.z` track). Must match the\n\t * publisher. Defaults to `false`.\n\t */\n\tcompression?: boolean;\n}\n\n/**\n * Consumes a {@link Root} catalog from a track, reconstructing it from snapshots and deltas.\n *\n * A thin wrapper around the `@moq/json` consumer, pre-wired with {@link RootSchema}. Call `next()`\n * to get each catalog as it changes, or iterate it. Pass an extended schema (built via\n * `z.extend(RootSchema, ...)`) to validate and type application sections; otherwise unknown\n * sections pass through untouched. Set `compression` to read the `catalog.json.z` track.\n */\nexport class Consumer<T extends Root = Root> extends Json.Snapshot.Consumer<T> {\n\t/** Wrap `track`, validating each catalog against `config.schema` (defaults to {@link RootSchema}). */\n\tconstructor(track: Moq.Track, config: ConsumerConfig<T> = {}) {\n\t\tsuper(track, {\n\t\t\tschema: (config.schema ?? RootSchema) as z.ZodMiniType<T>,\n\t\t\tcompression: config.compression,\n\t\t});\n\t}\n}\n\n/**\n * Read the current catalog from `track` once.\n *\n * @deprecated Use {@link Consumer} instead: `new Catalog.Consumer(track).next()`. A one-shot read\n * returns only the current catalog and misses later updates (and deltas, once enabled).\n */\nexport function fetch(track: Moq.Track): Promise<Root | undefined> {\n\treturn new Consumer(track).next();\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import * as z from "zod/mini";
2
+ /**
3
+ * Container format for frame timestamp encoding and frame payload structure.
4
+ *
5
+ * - "legacy": QUIC VarInt timestamp prefix followed by the raw codec payload.
6
+ * Timestamps are in microseconds.
7
+ * - "cmaf": Fragmented MP4 container - frames contain complete moof+mdat fragments.
8
+ * The init segment (ftyp+moov) is base64-encoded in the catalog.
9
+ * - "loc": Low Overhead Container (draft-ietf-moq-loc). Each frame has a small
10
+ * property block followed by the codec payload.
11
+ */
12
+ export declare const ContainerSchema: z.ZodMiniDefault<z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
13
+ kind: z.ZodMiniLiteral<"legacy">;
14
+ }, z.core.$strip>, z.ZodMiniObject<{
15
+ kind: z.ZodMiniLiteral<"cmaf">;
16
+ init: z.ZodMiniBase64;
17
+ timescale: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
18
+ trackId: z.ZodMiniOptional<z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">>;
19
+ }, z.core.$strip>, z.ZodMiniObject<{
20
+ kind: z.ZodMiniLiteral<"loc">;
21
+ }, z.core.$strip>], "kind">>;
22
+ /** The per-frame container format declared in the catalog. */
23
+ export type Container = z.infer<typeof ContainerSchema>;
24
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/catalog/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAG9B;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;4BAkB3B,CAAC;AAEF,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /* @ts-self-types="./container.d.ts" */
2
+ import * as z from "zod/mini";
3
+ import { u53Schema } from "./integers";
4
+ /**
5
+ * Container format for frame timestamp encoding and frame payload structure.
6
+ *
7
+ * - "legacy": QUIC VarInt timestamp prefix followed by the raw codec payload.
8
+ * Timestamps are in microseconds.
9
+ * - "cmaf": Fragmented MP4 container - frames contain complete moof+mdat fragments.
10
+ * The init segment (ftyp+moov) is base64-encoded in the catalog.
11
+ * - "loc": Low Overhead Container (draft-ietf-moq-loc). Each frame has a small
12
+ * property block followed by the codec payload.
13
+ */
14
+ export const ContainerSchema = z._default(z.discriminatedUnion("kind", [
15
+ // The default hang container
16
+ z.object({ kind: z.literal("legacy") }),
17
+ // CMAF container with base64-encoded init segment (ftyp+moov).
18
+ // `timescale` and `trackId` are deprecated: they duplicate info in `init`
19
+ // and are accepted only so catalogs from newer publishers (which still
20
+ // emit them for older players) round-trip cleanly.
21
+ z.object({
22
+ kind: z.literal("cmaf"),
23
+ init: z.base64(),
24
+ timescale: z.optional(u53Schema),
25
+ trackId: z.optional(u53Schema),
26
+ }),
27
+ // Low Overhead Container.
28
+ z.object({ kind: z.literal("loc") }),
29
+ ]), { kind: "legacy" });
30
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/catalog/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,QAAQ,CACxC,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC5B,6BAA6B;IAC7B,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACvC,+DAA+D;IAC/D,0EAA0E;IAC1E,uEAAuE;IACvE,mDAAmD;IACnD,CAAC,CAAC,MAAM,CAAC;QACR,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QACvB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;QAChC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;KAC9B,CAAC;IACF,0BAA0B;IAC1B,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;CACpC,CAAC,EACF,EAAE,IAAI,EAAE,QAAQ,EAAE,CAClB,CAAC","sourcesContent":["import * as z from \"zod/mini\";\nimport { u53Schema } from \"./integers\";\n\n/**\n * Container format for frame timestamp encoding and frame payload structure.\n *\n * - \"legacy\": QUIC VarInt timestamp prefix followed by the raw codec payload.\n * Timestamps are in microseconds.\n * - \"cmaf\": Fragmented MP4 container - frames contain complete moof+mdat fragments.\n * The init segment (ftyp+moov) is base64-encoded in the catalog.\n * - \"loc\": Low Overhead Container (draft-ietf-moq-loc). Each frame has a small\n * property block followed by the codec payload.\n */\nexport const ContainerSchema = z._default(\n\tz.discriminatedUnion(\"kind\", [\n\t\t// The default hang container\n\t\tz.object({ kind: z.literal(\"legacy\") }),\n\t\t// CMAF container with base64-encoded init segment (ftyp+moov).\n\t\t// `timescale` and `trackId` are deprecated: they duplicate info in `init`\n\t\t// and are accepted only so catalogs from newer publishers (which still\n\t\t// emit them for older players) round-trip cleanly.\n\t\tz.object({\n\t\t\tkind: z.literal(\"cmaf\"),\n\t\t\tinit: z.base64(),\n\t\t\ttimescale: z.optional(u53Schema),\n\t\t\ttrackId: z.optional(u53Schema),\n\t\t}),\n\t\t// Low Overhead Container.\n\t\tz.object({ kind: z.literal(\"loc\") }),\n\t]),\n\t{ kind: \"legacy\" },\n);\n\n/** The per-frame container format declared in the catalog. */\nexport type Container = z.infer<typeof ContainerSchema>;\n"]}
@@ -0,0 +1,13 @@
1
+ /** Track name for the uncompressed hang catalog (the `.json` track). */
2
+ export declare const TRACK = "catalog.json";
3
+ /** Track name for the DEFLATE-compressed hang catalog: the `.z` sibling of {@link TRACK}. */
4
+ export declare const TRACK_COMPRESSED = "catalog.json.z";
5
+ /** Recognized catalog format suffixes used in broadcast names. */
6
+ export declare const FORMATS: readonly ["hang", "msf"];
7
+ /** A catalog format advertised by a broadcast name suffix. */
8
+ export type Format = (typeof FORMATS)[number];
9
+ /** The catalog format assumed when a broadcast name has no recognized suffix. */
10
+ export declare const DEFAULT_FORMAT: Format;
11
+ /** Detect the catalog format from a broadcast name suffix, or `undefined` if the name has no recognized extension. */
12
+ export declare function detectFormat(name: string): Format | undefined;
13
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/catalog/format.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,eAAO,MAAM,KAAK,iBAAiB,CAAC;AAEpC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,kEAAkE;AAClE,eAAO,MAAM,OAAO,YAAI,MAAM,EAAE,KAAK,CAAU,CAAC;AAChD,8DAA8D;AAC9D,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,iFAAiF;AACjF,eAAO,MAAM,cAAc,EAAE,MAAe,CAAC;AAE7C,sHAAsH;AACtH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK7D"}
@@ -0,0 +1,24 @@
1
+ /* @ts-self-types="./format.d.ts" */
2
+ // Filename-style format extensions for broadcast names.
3
+ //
4
+ // Broadcast names use a filename-style suffix to advertise their catalog format,
5
+ // e.g. `demo/bbb.hang` or `demo/bbb.msf`. Consumers parse the suffix to pick a
6
+ // catalog track without explicit configuration; publishers should include the
7
+ // suffix in the name they publish so consumers can detect it.
8
+ /** Track name for the uncompressed hang catalog (the `.json` track). */
9
+ export const TRACK = "catalog.json";
10
+ /** Track name for the DEFLATE-compressed hang catalog: the `.z` sibling of {@link TRACK}. */
11
+ export const TRACK_COMPRESSED = "catalog.json.z";
12
+ /** Recognized catalog format suffixes used in broadcast names. */
13
+ export const FORMATS = ["hang", "msf"];
14
+ /** The catalog format assumed when a broadcast name has no recognized suffix. */
15
+ export const DEFAULT_FORMAT = "hang";
16
+ /** Detect the catalog format from a broadcast name suffix, or `undefined` if the name has no recognized extension. */
17
+ export function detectFormat(name) {
18
+ for (const format of FORMATS) {
19
+ if (name.endsWith(`.${format}`))
20
+ return format;
21
+ }
22
+ return undefined;
23
+ }
24
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/catalog/format.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,8EAA8E;AAC9E,8DAA8D;AAE9D,wEAAwE;AACxE,MAAM,CAAC,MAAM,KAAK,GAAG,cAAc,CAAC;AAEpC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEjD,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,CAAU,CAAC;AAIhD,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAW,MAAM,CAAC;AAE7C,sHAAsH;AACtH,MAAM,UAAU,YAAY,CAAC,IAAY;IACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC;YAAE,OAAO,MAAM,CAAC;IAChD,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC","sourcesContent":["// Filename-style format extensions for broadcast names.\n//\n// Broadcast names use a filename-style suffix to advertise their catalog format,\n// e.g. `demo/bbb.hang` or `demo/bbb.msf`. Consumers parse the suffix to pick a\n// catalog track without explicit configuration; publishers should include the\n// suffix in the name they publish so consumers can detect it.\n\n/** Track name for the uncompressed hang catalog (the `.json` track). */\nexport const TRACK = \"catalog.json\";\n\n/** Track name for the DEFLATE-compressed hang catalog: the `.z` sibling of {@link TRACK}. */\nexport const TRACK_COMPRESSED = \"catalog.json.z\";\n\n/** Recognized catalog format suffixes used in broadcast names. */\nexport const FORMATS = [\"hang\", \"msf\"] as const;\n/** A catalog format advertised by a broadcast name suffix. */\nexport type Format = (typeof FORMATS)[number];\n\n/** The catalog format assumed when a broadcast name has no recognized suffix. */\nexport const DEFAULT_FORMAT: Format = \"hang\";\n\n/** Detect the catalog format from a broadcast name suffix, or `undefined` if the name has no recognized extension. */\nexport function detectFormat(name: string): Format | undefined {\n\tfor (const format of FORMATS) {\n\t\tif (name.endsWith(`.${format}`)) return format;\n\t}\n\treturn undefined;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * JSON catalog schema and types describing a broadcast's tracks for WebCodecs:
3
+ * audio/video decoder configs, container format, and rendition layout.
4
+ *
5
+ * @module
6
+ */
7
+ export * from "./audio";
8
+ export * from "./consumer";
9
+ export * from "./container";
10
+ export * from "./format";
11
+ export * from "./integers";
12
+ export * from "./priority";
13
+ export * from "./producer";
14
+ export * from "./root";
15
+ export * from "./timeline";
16
+ export * from "./track";
17
+ export * from "./video";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/catalog/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ /* @ts-self-types="./index.d.ts" */
2
+ /**
3
+ * JSON catalog schema and types describing a broadcast's tracks for WebCodecs:
4
+ * audio/video decoder configs, container format, and rendition layout.
5
+ *
6
+ * @module
7
+ */
8
+ export * from "./audio";
9
+ export * from "./consumer";
10
+ export * from "./container";
11
+ export * from "./format";
12
+ export * from "./integers";
13
+ export * from "./priority";
14
+ export * from "./producer";
15
+ export * from "./root";
16
+ export * from "./timeline";
17
+ export * from "./track";
18
+ export * from "./video";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/catalog/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC","sourcesContent":["/**\n * JSON catalog schema and types describing a broadcast's tracks for WebCodecs:\n * audio/video decoder configs, container format, and rendition layout.\n *\n * @module\n */\n\nexport * from \"./audio\";\nexport * from \"./consumer\";\nexport * from \"./container\";\nexport * from \"./format\";\nexport * from \"./integers\";\nexport * from \"./priority\";\nexport * from \"./producer\";\nexport * from \"./root\";\nexport * from \"./timeline\";\nexport * from \"./track\";\nexport * from \"./video\";\n"]}
@@ -0,0 +1,23 @@
1
+ import * as z from "zod/mini";
2
+ /**
3
+ * Branded type for 8-bit unsigned integers (0-255)
4
+ */
5
+ export declare const u8Schema: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u8", "out">;
6
+ /** Branded 8-bit unsigned integer (0-255). */
7
+ export type U8 = z.infer<typeof u8Schema>;
8
+ /**
9
+ * Branded type for 53-bit unsigned integers (JavaScript's MAX_SAFE_INTEGER)
10
+ * This represents the maximum safe integer in JavaScript (2^53 - 1)
11
+ */
12
+ export declare const u53Schema: z.core.$ZodBranded<z.ZodMiniNumber<number>, "u53", "out">;
13
+ /** Branded unsigned integer up to JavaScript's MAX_SAFE_INTEGER (2^53 - 1). */
14
+ export type U53 = z.infer<typeof u53Schema>;
15
+ /**
16
+ * Convenience function to create a u8 value
17
+ */
18
+ export declare function u8(value: number): U8;
19
+ /**
20
+ * Convenience function to create a u53 value
21
+ */
22
+ export declare function u53(value: number): U53;
23
+ //# sourceMappingURL=integers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integers.d.ts","sourceRoot":"","sources":["../../src/catalog/integers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAE9B;;GAEG;AACH,eAAO,MAAM,QAAQ,0DAAqE,CAAC;AAE3F,8CAA8C;AAC9C,MAAM,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,SAAS,2DAA0F,CAAC;AAEjH,+EAA+E;AAC/E,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAE5C;;GAEG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,EAAE,CAEpC;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAEtC"}
@@ -0,0 +1,24 @@
1
+ /* @ts-self-types="./integers.d.ts" */
2
+ import * as z from "zod/mini";
3
+ /**
4
+ * Branded type for 8-bit unsigned integers (0-255)
5
+ */
6
+ export const u8Schema = z.number().check(z.int(), z.nonnegative(), z.lte(255)).brand("u8");
7
+ /**
8
+ * Branded type for 53-bit unsigned integers (JavaScript's MAX_SAFE_INTEGER)
9
+ * This represents the maximum safe integer in JavaScript (2^53 - 1)
10
+ */
11
+ export const u53Schema = z.number().check(z.int(), z.nonnegative(), z.lte(Number.MAX_SAFE_INTEGER)).brand("u53");
12
+ /**
13
+ * Convenience function to create a u8 value
14
+ */
15
+ export function u8(value) {
16
+ return u8Schema.parse(value);
17
+ }
18
+ /**
19
+ * Convenience function to create a u53 value
20
+ */
21
+ export function u53(value) {
22
+ return u53Schema.parse(value);
23
+ }
24
+ //# sourceMappingURL=integers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integers.js","sourceRoot":"","sources":["../../src/catalog/integers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAE9B;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAK3F;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAKjH;;GAEG;AACH,MAAM,UAAU,EAAE,CAAC,KAAa;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAC,KAAa;IAChC,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import * as z from \"zod/mini\";\n\n/**\n * Branded type for 8-bit unsigned integers (0-255)\n */\nexport const u8Schema = z.number().check(z.int(), z.nonnegative(), z.lte(255)).brand(\"u8\");\n\n/** Branded 8-bit unsigned integer (0-255). */\nexport type U8 = z.infer<typeof u8Schema>;\n\n/**\n * Branded type for 53-bit unsigned integers (JavaScript's MAX_SAFE_INTEGER)\n * This represents the maximum safe integer in JavaScript (2^53 - 1)\n */\nexport const u53Schema = z.number().check(z.int(), z.nonnegative(), z.lte(Number.MAX_SAFE_INTEGER)).brand(\"u53\");\n\n/** Branded unsigned integer up to JavaScript's MAX_SAFE_INTEGER (2^53 - 1). */\nexport type U53 = z.infer<typeof u53Schema>;\n\n/**\n * Convenience function to create a u8 value\n */\nexport function u8(value: number): U8 {\n\treturn u8Schema.parse(value);\n}\n\n/**\n * Convenience function to create a u53 value\n */\nexport function u53(value: number): U53 {\n\treturn u53Schema.parse(value);\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /** Delivery priority per track kind; higher is sent first. */
2
+ export declare const PRIORITY: {
3
+ readonly catalog: 100;
4
+ readonly audio: 80;
5
+ readonly video: 60;
6
+ };
7
+ //# sourceMappingURL=priority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority.d.ts","sourceRoot":"","sources":["../../src/catalog/priority.ts"],"names":[],"mappings":"AACA,8DAA8D;AAC9D,eAAO,MAAM,QAAQ;aACpB,OAAO,EAAE,GAAG;aACZ,KAAK,EAAE,EAAE;aACT,KAAK,EAAE,EAAE;CACA,CAAC"}
@@ -0,0 +1,9 @@
1
+ /* @ts-self-types="./priority.d.ts" */
2
+ // Defined in one place so the relative ordering stays consistent.
3
+ /** Delivery priority per track kind; higher is sent first. */
4
+ export const PRIORITY = {
5
+ catalog: 100,
6
+ audio: 80,
7
+ video: 60,
8
+ };
9
+ //# sourceMappingURL=priority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority.js","sourceRoot":"","sources":["../../src/catalog/priority.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,8DAA8D;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAG;IACvB,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;CACA,CAAC","sourcesContent":["// Defined in one place so the relative ordering stays consistent.\n/** Delivery priority per track kind; higher is sent first. */\nexport const PRIORITY = {\n\tcatalog: 100,\n\taudio: 80,\n\tvideo: 60,\n} as const;\n"]}