@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.
- package/README.md +65 -0
- package/catalog/audio.d.ts +139 -0
- package/catalog/audio.d.ts.map +1 -0
- package/catalog/audio.js +55 -0
- package/catalog/audio.js.map +1 -0
- package/catalog/consumer.d.ts +34 -0
- package/catalog/consumer.d.ts.map +1 -0
- package/catalog/consumer.js +30 -0
- package/catalog/consumer.js.map +1 -0
- package/catalog/container.d.ts +24 -0
- package/catalog/container.d.ts.map +1 -0
- package/catalog/container.js +30 -0
- package/catalog/container.js.map +1 -0
- package/catalog/format.d.ts +13 -0
- package/catalog/format.d.ts.map +1 -0
- package/catalog/format.js +24 -0
- package/catalog/format.js.map +1 -0
- package/catalog/index.d.ts +18 -0
- package/catalog/index.d.ts.map +1 -0
- package/catalog/index.js +19 -0
- package/catalog/index.js.map +1 -0
- package/catalog/integers.d.ts +23 -0
- package/catalog/integers.d.ts.map +1 -0
- package/catalog/integers.js +24 -0
- package/catalog/integers.js.map +1 -0
- package/catalog/priority.d.ts +7 -0
- package/catalog/priority.d.ts.map +1 -0
- package/catalog/priority.js +9 -0
- package/catalog/priority.js.map +1 -0
- package/catalog/producer.d.ts +31 -0
- package/catalog/producer.d.ts.map +1 -0
- package/catalog/producer.js +25 -0
- package/catalog/producer.js.map +1 -0
- package/catalog/root.d.ts +252 -0
- package/catalog/root.d.ts.map +1 -0
- package/catalog/root.js +17 -0
- package/catalog/root.js.map +1 -0
- package/catalog/root.test.d.ts +2 -0
- package/catalog/root.test.d.ts.map +1 -0
- package/catalog/root.test.js +20 -0
- package/catalog/root.test.js.map +1 -0
- package/catalog/timeline.d.ts +26 -0
- package/catalog/timeline.d.ts.map +1 -0
- package/catalog/timeline.js +33 -0
- package/catalog/timeline.js.map +1 -0
- package/catalog/track.d.ts +8 -0
- package/catalog/track.d.ts.map +1 -0
- package/catalog/track.js +7 -0
- package/catalog/track.js.map +1 -0
- package/catalog/video.d.ts +171 -0
- package/catalog/video.d.ts.map +1 -0
- package/catalog/video.js +87 -0
- package/catalog/video.js.map +1 -0
- package/container/cmaf/decode.d.ts +68 -0
- package/container/cmaf/decode.d.ts.map +1 -0
- package/container/cmaf/decode.js +303 -0
- package/container/cmaf/decode.js.map +1 -0
- package/container/cmaf/encode.d.ts +51 -0
- package/container/cmaf/encode.d.ts.map +1 -0
- package/container/cmaf/encode.js +834 -0
- package/container/cmaf/encode.js.map +1 -0
- package/container/cmaf/format.d.ts +12 -0
- package/container/cmaf/format.d.ts.map +1 -0
- package/container/cmaf/format.js +19 -0
- package/container/cmaf/format.js.map +1 -0
- package/container/cmaf/index.d.ts +9 -0
- package/container/cmaf/index.d.ts.map +1 -0
- package/container/cmaf/index.js +10 -0
- package/container/cmaf/index.js.map +1 -0
- package/container/consumer.d.ts +41 -0
- package/container/consumer.d.ts.map +1 -0
- package/container/consumer.js +424 -0
- package/container/consumer.js.map +1 -0
- package/container/consumer.test.d.ts +2 -0
- package/container/consumer.test.d.ts.map +1 -0
- package/container/consumer.test.js +396 -0
- package/container/consumer.test.js.map +1 -0
- package/container/format.d.ts +12 -0
- package/container/format.d.ts.map +1 -0
- package/container/format.js +3 -0
- package/container/format.js.map +1 -0
- package/container/index.d.ts +14 -0
- package/container/index.d.ts.map +1 -0
- package/container/index.js +18 -0
- package/container/index.js.map +1 -0
- package/container/legacy.d.ts +39 -0
- package/container/legacy.d.ts.map +1 -0
- package/container/legacy.js +53 -0
- package/container/legacy.js.map +1 -0
- package/container/timeline.d.ts +67 -0
- package/container/timeline.d.ts.map +1 -0
- package/container/timeline.js +87 -0
- package/container/timeline.js.map +1 -0
- package/container/types.d.ts +22 -0
- package/container/types.d.ts.map +1 -0
- package/container/types.js +22 -0
- package/container/types.js.map +1 -0
- package/index.d.ts +13 -0
- package/index.d.ts.map +1 -0
- package/index.js +18 -0
- package/index.js.map +1 -0
- package/package.json +37 -0
- package/util/aac.d.ts +8 -0
- package/util/aac.d.ts.map +1 -0
- package/util/aac.js +57 -0
- package/util/aac.js.map +1 -0
- package/util/aac.test.d.ts +2 -0
- package/util/aac.test.d.ts.map +1 -0
- package/util/aac.test.js +34 -0
- package/util/aac.test.js.map +1 -0
- package/util/hacks.d.ts +5 -0
- package/util/hacks.d.ts.map +1 -0
- package/util/hacks.js +6 -0
- package/util/hacks.js.map +1 -0
- package/util/hex.d.ts +5 -0
- package/util/hex.d.ts.map +1 -0
- package/util/hex.js +18 -0
- package/util/hex.js.map +1 -0
- package/util/index.d.ts +12 -0
- package/util/index.d.ts.map +1 -0
- package/util/index.js +18 -0
- package/util/index.js.map +1 -0
- package/util/latency.d.ts +38 -0
- package/util/latency.d.ts.map +1 -0
- package/util/latency.js +49 -0
- package/util/latency.js.map +1 -0
- package/util/libav.d.ts +3 -0
- package/util/libav.d.ts.map +1 -0
- package/util/libav.js +26 -0
- 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
|
+
[](https://www.npmjs.com/package/@moq/hang)
|
|
8
|
+
[](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"}
|
package/catalog/audio.js
ADDED
|
@@ -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"}
|
package/catalog/index.js
ADDED
|
@@ -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 @@
|
|
|
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"]}
|