@norskvideo/moq-watch 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 (123) hide show
  1. package/README.md +143 -0
  2. package/audio/backend.d.ts +26 -0
  3. package/audio/backend.d.ts.map +1 -0
  4. package/audio/buffer.d.ts +42 -0
  5. package/audio/buffer.d.ts.map +1 -0
  6. package/audio/decoder.d.ts +32 -0
  7. package/audio/decoder.d.ts.map +1 -0
  8. package/audio/emitter.d.ts +17 -0
  9. package/audio/emitter.d.ts.map +1 -0
  10. package/audio/index.d.ts +6 -0
  11. package/audio/index.d.ts.map +1 -0
  12. package/audio/mse.d.ts +22 -0
  13. package/audio/mse.d.ts.map +1 -0
  14. package/audio/render-worklet.d.ts +2 -0
  15. package/audio/render-worklet.d.ts.map +1 -0
  16. package/audio/render.d.ts +38 -0
  17. package/audio/render.d.ts.map +1 -0
  18. package/audio/ring-buffer.d.ts +21 -0
  19. package/audio/ring-buffer.d.ts.map +1 -0
  20. package/audio/ring-buffer.test.d.ts +2 -0
  21. package/audio/ring-buffer.test.d.ts.map +1 -0
  22. package/audio/shared-ring-buffer.d.ts +62 -0
  23. package/audio/shared-ring-buffer.d.ts.map +1 -0
  24. package/audio/shared-ring-buffer.test.d.ts +2 -0
  25. package/audio/shared-ring-buffer.test.d.ts.map +1 -0
  26. package/audio/source.d.ts +34 -0
  27. package/audio/source.d.ts.map +1 -0
  28. package/backend.d.ts +65 -0
  29. package/backend.d.ts.map +1 -0
  30. package/base64.d.ts +3 -0
  31. package/base64.d.ts.map +1 -0
  32. package/broadcast-OttaL0p4.js +1701 -0
  33. package/broadcast-OttaL0p4.js.map +1 -0
  34. package/broadcast.d.ts +71 -0
  35. package/broadcast.d.ts.map +1 -0
  36. package/buffered.d.ts +19 -0
  37. package/buffered.d.ts.map +1 -0
  38. package/element.d.ts +75 -0
  39. package/element.d.ts.map +1 -0
  40. package/element.js +209 -0
  41. package/element.js.map +1 -0
  42. package/index.d.ts +14 -0
  43. package/index.d.ts.map +1 -0
  44. package/index.js +7 -0
  45. package/mse.d.ts +19 -0
  46. package/mse.d.ts.map +1 -0
  47. package/msf.d.ts +5 -0
  48. package/msf.d.ts.map +1 -0
  49. package/package.json +42 -0
  50. package/support/element.d.ts +22 -0
  51. package/support/element.d.ts.map +1 -0
  52. package/support/element.js +123 -0
  53. package/support/element.js.map +1 -0
  54. package/support/index.d.ts +29 -0
  55. package/support/index.d.ts.map +1 -0
  56. package/support/index.js +56 -0
  57. package/support/index.js.map +1 -0
  58. package/sync-D67IxmxJ.js +128 -0
  59. package/sync-D67IxmxJ.js.map +1 -0
  60. package/sync.d.ts +50 -0
  61. package/sync.d.ts.map +1 -0
  62. package/sync.test.d.ts +2 -0
  63. package/sync.test.d.ts.map +1 -0
  64. package/ui/components/buffer-control.d.ts +5 -0
  65. package/ui/components/buffer-control.d.ts.map +1 -0
  66. package/ui/components/buffering-indicator.d.ts +4 -0
  67. package/ui/components/buffering-indicator.d.ts.map +1 -0
  68. package/ui/components/button.d.ts +3 -0
  69. package/ui/components/button.d.ts.map +1 -0
  70. package/ui/components/center-play.d.ts +5 -0
  71. package/ui/components/center-play.d.ts.map +1 -0
  72. package/ui/components/control-bar.d.ts +6 -0
  73. package/ui/components/control-bar.d.ts.map +1 -0
  74. package/ui/components/fullscreen-button.d.ts +5 -0
  75. package/ui/components/fullscreen-button.d.ts.map +1 -0
  76. package/ui/components/latency.d.ts +5 -0
  77. package/ui/components/latency.d.ts.map +1 -0
  78. package/ui/components/live-badge.d.ts +9 -0
  79. package/ui/components/live-badge.d.ts.map +1 -0
  80. package/ui/components/offline-indicator.d.ts +4 -0
  81. package/ui/components/offline-indicator.d.ts.map +1 -0
  82. package/ui/components/play-pause.d.ts +5 -0
  83. package/ui/components/play-pause.d.ts.map +1 -0
  84. package/ui/components/quality.d.ts +5 -0
  85. package/ui/components/quality.d.ts.map +1 -0
  86. package/ui/components/settings-button.d.ts +5 -0
  87. package/ui/components/settings-button.d.ts.map +1 -0
  88. package/ui/components/settings-panel.d.ts +6 -0
  89. package/ui/components/settings-panel.d.ts.map +1 -0
  90. package/ui/components/unsupported-indicator.d.ts +5 -0
  91. package/ui/components/unsupported-indicator.d.ts.map +1 -0
  92. package/ui/components/volume-slider.d.ts +5 -0
  93. package/ui/components/volume-slider.d.ts.map +1 -0
  94. package/ui/element.d.ts +12 -0
  95. package/ui/element.d.ts.map +1 -0
  96. package/ui/element.js +725 -0
  97. package/ui/element.js.map +1 -0
  98. package/ui/format.d.ts +11 -0
  99. package/ui/format.d.ts.map +1 -0
  100. package/ui/fullscreen.d.ts +16 -0
  101. package/ui/fullscreen.d.ts.map +1 -0
  102. package/ui/graph.d.ts +18 -0
  103. package/ui/graph.d.ts.map +1 -0
  104. package/ui/icons.d.ts +20 -0
  105. package/ui/icons.d.ts.map +1 -0
  106. package/ui/state.d.ts +9 -0
  107. package/ui/state.d.ts.map +1 -0
  108. package/ui/stats.d.ts +5 -0
  109. package/ui/stats.d.ts.map +1 -0
  110. package/video/backend.d.ts +25 -0
  111. package/video/backend.d.ts.map +1 -0
  112. package/video/decoder.d.ts +25 -0
  113. package/video/decoder.d.ts.map +1 -0
  114. package/video/index.d.ts +6 -0
  115. package/video/index.d.ts.map +1 -0
  116. package/video/mse.d.ts +23 -0
  117. package/video/mse.d.ts.map +1 -0
  118. package/video/renderer.d.ts +36 -0
  119. package/video/renderer.d.ts.map +1 -0
  120. package/video/source.d.ts +42 -0
  121. package/video/source.d.ts.map +1 -0
  122. package/video/source.test.d.ts +2 -0
  123. package/video/source.test.d.ts.map +1 -0
package/README.md ADDED
@@ -0,0 +1,143 @@
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/watch
6
+
7
+ [![npm](https://img.shields.io/npm/v/@moq/watch)](https://www.npmjs.com/package/@moq/watch)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-ready-blue.svg)](https://www.typescriptlang.org/)
9
+
10
+ Subscribe to and render [Media over QUIC](https://moq.dev/) (MoQ) broadcasts, built on top of [@moq/hang](../hang) and [@moq/net](../lite).
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ bun add @moq/watch
16
+ # or
17
+ npm add @moq/watch
18
+ ```
19
+
20
+ ### No-build CDN usage
21
+
22
+ For quick demos or embeds where a bundler is overkill, esm.sh serves the
23
+ published npm package as a browser-ready ESM module. Bare imports like
24
+ `@moq/hang` are automatically rewritten to other esm.sh URLs. No build step or
25
+ import map required:
26
+
27
+ ```html
28
+ <script type="module">
29
+ import "https://esm.sh/@moq/watch/element";
30
+ import "https://esm.sh/@moq/watch/ui";
31
+ </script>
32
+
33
+ <moq-watch-ui>
34
+ <moq-watch url="https://relay.example.com/anon" name="room/alice.hang">
35
+ <canvas></canvas>
36
+ </moq-watch>
37
+ </moq-watch-ui>
38
+ ```
39
+
40
+ Pin a version range in the URL for production, e.g.
41
+ `https://esm.sh/@moq/watch@0.2/element`. jsDelivr's `+esm` endpoint
42
+ (`https://cdn.jsdelivr.net/npm/@moq/watch/element.js/+esm`) works the same way
43
+ if you prefer it.
44
+
45
+ For anything beyond embedding on a static page you should install the
46
+ package and use a real bundler (the examples below).
47
+
48
+ ## Web Component
49
+
50
+ The simplest way to watch a stream:
51
+
52
+ ```html
53
+ <script type="module">
54
+ import "@moq/watch/element";
55
+ </script>
56
+
57
+ <moq-watch
58
+ url="https://relay.example.com/anon"
59
+ name="room/alice.hang"
60
+ controls>
61
+ <canvas></canvas>
62
+ </moq-watch>
63
+ ```
64
+
65
+ ### Attributes
66
+
67
+ | Attribute | Type | Default | Description |
68
+ |-----------|-------------------------------------|----------|------------------------------------------|
69
+ | `url` | string | required | Relay server URL |
70
+ | `name` | string | required | Broadcast name/path |
71
+ | `paused` | boolean | false | Pause playback |
72
+ | `muted` | boolean | false | Mute audio |
73
+ | `visible` | never, distance, or always | `20%` | When to download video (see below) |
74
+ | `volume` | number | 0.5 | Audio volume (0-1) |
75
+ | `reload` | boolean | true | Wait for (re)announcement before subscribing. Defaults off for `mediaoverquic.com` relays until they support broadcast discovery. |
76
+
77
+ The `visible` attribute controls when the video track is downloaded, based on the canvas
78
+ position relative to the viewport:
79
+
80
+ - `never`: never download video.
81
+ - a distance (`0px`, `200px`, `100%`, ...): download while the canvas is within that distance
82
+ of the viewport **and** the tab is visible. `0px` means strictly on screen; a larger distance
83
+ (`20%`, the default) pre-warms the video before it scrolls into view.
84
+ - `always`: always download video, regardless of the canvas position or tab visibility.
85
+
86
+ Only the distance mode suspends video while the tab is hidden; `always` keeps downloading.
87
+
88
+ ## JavaScript API
89
+
90
+ For more control:
91
+
92
+ ```typescript
93
+ import * as Watch from "@moq/watch";
94
+
95
+ const watch = new Watch.Broadcast(connection, {
96
+ enabled: true,
97
+ name: "alice.hang",
98
+ video: { enabled: true },
99
+ audio: { enabled: true },
100
+ });
101
+
102
+ // Access the video stream
103
+ watch.video.media.subscribe((stream) => {
104
+ if (stream) {
105
+ videoElement.srcObject = stream;
106
+ }
107
+ });
108
+ ```
109
+
110
+ ## UI Web Component
111
+
112
+ `@moq/watch` includes a Web Component UI overlay (`<moq-watch-ui>`) with playback controls, volume, buffering indicator, unsupported-codec indicator, quality selector, and stats panel. It is built on top of `@moq/signals` with no framework dependency.
113
+
114
+ ```html
115
+ <script type="module">
116
+ import "@moq/watch/element";
117
+ import "@moq/watch/ui";
118
+ </script>
119
+
120
+ <moq-watch-ui>
121
+ <moq-watch url="https://relay.example.com/anon" name="room/alice.hang">
122
+ <canvas></canvas>
123
+ </moq-watch>
124
+ </moq-watch-ui>
125
+ ```
126
+
127
+ The `<moq-watch-ui>` element automatically discovers the nested `<moq-watch>` element and wires up reactive controls.
128
+
129
+ ## Features
130
+
131
+ - **WebCodecs decoding** — Hardware-accelerated video and audio decoding
132
+ - **MSE fallback** — Media Source Extensions for broader codec support
133
+ - **Reactive state** — All properties are signals from `@moq/signals`
134
+ - **Chat** — Subscribe to text chat channels
135
+ - **Location** — Peer location and window tracking
136
+ - **Quality selection** — Switch between available renditions
137
+
138
+ ## License
139
+
140
+ Licensed under either:
141
+
142
+ - Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
143
+ - MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT)
@@ -0,0 +1,26 @@
1
+ import type { Getter, Signal } from "@norskvideo/moq-signals";
2
+ import type { BufferedRanges } from "../buffered";
3
+ import type { Source } from "./source";
4
+ /** Audio-specific signals that work regardless of the backend source (MSE vs WebCodecs). */
5
+ export interface Backend {
6
+ /** The source of the audio. */
7
+ source: Source;
8
+ /** The volume of the audio, between 0 and 1. */
9
+ volume: Signal<number>;
10
+ /** Whether the audio is muted. */
11
+ muted: Signal<boolean>;
12
+ /** The stats of the audio. */
13
+ stats: Getter<Stats | undefined>;
14
+ /** Buffered time ranges for the MSE backend. */
15
+ buffered: Getter<BufferedRanges>;
16
+ /** The AudioContext used for WebCodecs playback. */
17
+ context: Getter<AudioContext | undefined>;
18
+ }
19
+ /** Audio playback statistics. */
20
+ export interface Stats {
21
+ /** Number of samples decoded. */
22
+ sampleCount: number;
23
+ /** Number of encoded bytes received. */
24
+ bytesReceived: number;
25
+ }
26
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/audio/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,4FAA4F;AAC5F,MAAM,WAAW,OAAO;IACvB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IAEf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAEjC,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAEjC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED,iCAAiC;AACjC,MAAM,WAAW,KAAK;IACrB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;CACtB"}
@@ -0,0 +1,42 @@
1
+ import { Time } from "@norskvideo/moq-net";
2
+ import { type Getter } from "@norskvideo/moq-signals";
3
+ /**
4
+ * Unified interface for the audio buffer between the main thread and the AudioWorklet.
5
+ *
6
+ * Two implementations exist:
7
+ * - `SharedAudioBuffer`: backed by SharedArrayBuffer, lock-free writes via Atomics.
8
+ * - `PostAudioBuffer`: backed by postMessage transfer (the fallback when SAB is unavailable).
9
+ *
10
+ * Use `createAudioBuffer()` to pick the right implementation automatically.
11
+ */
12
+ export interface AudioBuffer {
13
+ readonly rate: number;
14
+ readonly channels: number;
15
+ /** Insert audio samples at the given timestamp. Handles out-of-order writes. */
16
+ insert(timestamp: Time.Micro, data: Float32Array[]): void;
17
+ /** Update the target latency in samples. */
18
+ setLatency(samples: number): void;
19
+ /** Flush buffered samples and re-stall, ready to anchor the next utterance (buffered mode). */
20
+ reset(): void;
21
+ /**
22
+ * Resolve once the playhead is near enough to decode a frame at `timestamp`. In buffered mode this
23
+ * applies backpressure: it stays pending while decoding `timestamp` would run more than the latency
24
+ * floor ahead of the playhead, so the caller holds the (encoded) frame instead of decoding it too
25
+ * far ahead of the floor-sized ring. Resolves immediately when not buffered (the ring bounds itself).
26
+ */
27
+ wait(timestamp: Time.Micro): Promise<void>;
28
+ /** Current playback timestamp (derived from reader position). */
29
+ readonly timestamp: Getter<Time.Micro>;
30
+ /** Whether the buffer is stalled (waiting to fill). */
31
+ readonly stalled: Getter<boolean>;
32
+ /** Release any resources (event listeners, intervals, etc.). */
33
+ close(): void;
34
+ }
35
+ /** Returns true when SharedArrayBuffer is available and usable in the current context. */
36
+ export declare function supportsSharedArrayBuffer(): boolean;
37
+ /**
38
+ * Create the best audio buffer implementation for the current environment.
39
+ * Picks `SharedAudioBuffer` when possible, falling back to `PostAudioBuffer`.
40
+ */
41
+ export declare function createAudioBuffer(worklet: AudioWorkletNode, channels: number, rate: number, latencySamples: number, buffered?: boolean): AudioBuffer;
42
+ //# sourceMappingURL=buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../../src/audio/buffer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAU,KAAK,MAAM,EAAU,MAAM,cAAc,CAAC;AAwD3D;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,gFAAgF;IAChF,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAE1D,4CAA4C;IAC5C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC,+FAA+F;IAC/F,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;OAKG;IACH,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEvC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAElC,gEAAgE;IAChE,KAAK,IAAI,IAAI,CAAC;CACd;AAED,0FAA0F;AAC1F,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,QAAQ,UAAQ,GACd,WAAW,CAOb"}
@@ -0,0 +1,32 @@
1
+ import { Time } from "@norskvideo/moq-net";
2
+ import { type Getter, Signal } from "@norskvideo/moq-signals";
3
+ import type { BufferedRanges } from "../buffered";
4
+ import type { Source } from "./source";
5
+ export type DecoderProps = {
6
+ enabled?: boolean | Signal<boolean>;
7
+ };
8
+ export interface AudioStats {
9
+ /** Number of encoded bytes received. */
10
+ bytesReceived: number;
11
+ }
12
+ /**
13
+ * Downloads audio from a track and emits it to an AudioContext.
14
+ *
15
+ * The user is responsible for hooking up audio to speakers, an analyzer, etc.
16
+ */
17
+ export declare class Decoder {
18
+ #private;
19
+ source: Source;
20
+ enabled: Signal<boolean>;
21
+ readonly context: Getter<AudioContext | undefined>;
22
+ readonly root: Getter<AudioNode | undefined>;
23
+ readonly sampleRate: Getter<number | undefined>;
24
+ readonly stats: Getter<AudioStats | undefined>;
25
+ readonly timestamp: Getter<Time.Milli | undefined>;
26
+ readonly stalled: Getter<boolean>;
27
+ readonly buffered: Getter<BufferedRanges>;
28
+ constructor(source: Source, props?: DecoderProps);
29
+ reset(): void;
30
+ close(): void;
31
+ }
32
+ //# sourceMappingURL=decoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/audio/decoder.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,MAAM,YAAY,GAAG;IAE1B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;CACpC,CAAC;AAEF,MAAM,WAAW,UAAU;IAC1B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,OAAO;;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAGzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAAiB;IAKnE,QAAQ,CAAC,IAAI,EAAoB,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAG/D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAoB;IAGnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,CAAe;IAI7D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAmB;IAIrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAiB;IAOlD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAkB;IAuB3D,YAAY,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,EAc/C;IA+VD,KAAK,IAAI,IAAI,CAEZ;IAaD,KAAK,SAEJ;CACD"}
@@ -0,0 +1,17 @@
1
+ import { Signal } from "@norskvideo/moq-signals";
2
+ import type { Decoder } from "./decoder";
3
+ export type EmitterProps = {
4
+ volume?: number | Signal<number>;
5
+ muted?: boolean | Signal<boolean>;
6
+ paused?: boolean | Signal<boolean>;
7
+ };
8
+ export declare class Emitter {
9
+ #private;
10
+ source: Decoder;
11
+ volume: Signal<number>;
12
+ muted: Signal<boolean>;
13
+ paused: Signal<boolean>;
14
+ constructor(source: Decoder, props?: EmitterProps);
15
+ close(): void;
16
+ }
17
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/audio/emitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,MAAM,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,MAAM,MAAM,YAAY,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;AAGF,qBAAa,OAAO;;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAIvB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAUxB,YAAY,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,YAAY,EA+DhD;IAED,KAAK,SAEJ;CACD"}
@@ -0,0 +1,6 @@
1
+ export type * from "./backend";
2
+ export * from "./decoder";
3
+ export * from "./emitter";
4
+ export * from "./mse";
5
+ export * from "./source";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audio/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,WAAW,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC"}
package/audio/mse.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { type Getter, Signal } from "@norskvideo/moq-signals";
2
+ import { type BufferedRanges } from "../buffered";
3
+ import type { Muxer } from "../mse";
4
+ import type { Backend, Stats } from "./backend";
5
+ import type { Source } from "./source";
6
+ export type MseProps = {
7
+ volume?: number | Signal<number>;
8
+ muted?: boolean | Signal<boolean>;
9
+ };
10
+ export declare class Mse implements Backend {
11
+ #private;
12
+ muxer: Muxer;
13
+ source: Source;
14
+ volume: Signal<number>;
15
+ muted: Signal<boolean>;
16
+ readonly stats: Getter<Stats | undefined>;
17
+ readonly buffered: Getter<BufferedRanges>;
18
+ readonly context: Getter<AudioContext | undefined>;
19
+ constructor(muxer: Muxer, source: Source, props?: MseProps);
20
+ close(): void;
21
+ }
22
+ //# sourceMappingURL=mse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mse.d.ts","sourceRoot":"","sources":["../../src/audio/mse.ts"],"names":[],"mappings":"AAGA,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,qBAAa,GAAI,YAAW,OAAO;;IAClC,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAGvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,CAAe;IAGxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,cAAc,CAAC,CAAkB;IAG3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC,CAAmD;IAIrG,YAAY,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAUzD;IA8LD,KAAK,IAAI,IAAI,CAEZ;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=render-worklet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-worklet.d.ts","sourceRoot":"","sources":["../../src/audio/render-worklet.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import type { Time } from "@norskvideo/moq-net";
2
+ import type { SharedRingBufferInit } from "./shared-ring-buffer";
3
+ export type Message = InitShared | InitPost | Data | Latency | Reset;
4
+ export type ToMain = State;
5
+ /** Init message when SharedArrayBuffer is available. */
6
+ export interface InitShared extends SharedRingBufferInit {
7
+ type: "init-shared";
8
+ }
9
+ /** Init message for the postMessage fallback path. */
10
+ export interface InitPost {
11
+ type: "init-post";
12
+ channels: number;
13
+ rate: number;
14
+ latency: Time.Milli;
15
+ buffered: boolean;
16
+ }
17
+ /** Flush the buffer and re-stall (fallback path only; shared path resets via Atomics). */
18
+ export interface Reset {
19
+ type: "reset";
20
+ }
21
+ /** Audio samples sent via postMessage (fallback path only). */
22
+ export interface Data {
23
+ type: "data";
24
+ data: Float32Array[];
25
+ timestamp: Time.Micro;
26
+ }
27
+ /** Latency update sent via postMessage (fallback path only). */
28
+ export interface Latency {
29
+ type: "latency";
30
+ latency: Time.Milli;
31
+ }
32
+ /** State update from the worklet back to main thread (fallback path only). */
33
+ export interface State {
34
+ type: "state";
35
+ timestamp: Time.Micro;
36
+ stalled: boolean;
37
+ }
38
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/audio/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC;AACrE,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC;AAE3B,wDAAwD;AACxD,MAAM,WAAW,UAAW,SAAQ,oBAAoB;IACvD,IAAI,EAAE,aAAa,CAAC;CACpB;AAED,sDAAsD;AACtD,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;IAGpB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,0FAA0F;AAC1F,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,OAAO,CAAC;CACd;AAED,+DAA+D;AAC/D,MAAM,WAAW,IAAI;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;CACtB;AAED,gEAAgE;AAChE,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CACjB"}
@@ -0,0 +1,21 @@
1
+ import { Time } from "@norskvideo/moq-net";
2
+ export declare class AudioRingBuffer {
3
+ #private;
4
+ readonly rate: number;
5
+ readonly channels: number;
6
+ constructor(props: {
7
+ rate: number;
8
+ channels: number;
9
+ latency: Time.Milli;
10
+ buffered?: boolean;
11
+ });
12
+ get stalled(): boolean;
13
+ get timestamp(): Time.Micro;
14
+ get length(): number;
15
+ get capacity(): number;
16
+ resize(latency: Time.Milli): void;
17
+ write(timestamp: Time.Micro, data: Float32Array[]): void;
18
+ reset(): void;
19
+ read(output: Float32Array[]): number;
20
+ }
21
+ //# sourceMappingURL=ring-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../../src/audio/ring-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,qBAAa,eAAe;;IAK3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAU1B,YAAY,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACnB,EAqBA;IAMD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,CAE1B;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAgChC;IAED,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI,CA6EvD;IAGD,KAAK,IAAI,IAAI,CAKZ;IAED,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAqBnC;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ring-buffer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring-buffer.test.d.ts","sourceRoot":"","sources":["../../src/audio/ring-buffer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { Time } from "@norskvideo/moq-net";
2
+ export interface SharedRingBufferInit {
3
+ channels: number;
4
+ capacity: number;
5
+ rate: number;
6
+ samples: SharedArrayBuffer;
7
+ control: SharedArrayBuffer;
8
+ buffered: boolean;
9
+ }
10
+ export declare function allocSharedRingBuffer(channels: number, capacity: number, rate: number, buffered?: boolean): SharedRingBufferInit;
11
+ export declare class SharedRingBuffer {
12
+ #private;
13
+ readonly channels: number;
14
+ readonly capacity: number;
15
+ readonly rate: number;
16
+ readonly buffered: boolean;
17
+ readonly init: SharedRingBufferInit;
18
+ constructor(init: SharedRingBufferInit);
19
+ /**
20
+ * Insert audio samples at the given timestamp.
21
+ * Main thread only. Handles out-of-order writes, gap filling, and overflow.
22
+ */
23
+ insert(timestamp: Time.Micro, data: Float32Array[]): void;
24
+ /**
25
+ * Read audio samples into the output buffers.
26
+ * AudioWorklet only. Returns the number of samples read.
27
+ */
28
+ read(output: Float32Array[]): number;
29
+ /** Update the target latency in samples. */
30
+ setLatency(samples: number): void;
31
+ /**
32
+ * Flush buffered samples and re-stall, ready to anchor the next utterance (buffered mode).
33
+ * Main thread only. The worklet reader sees STALLED and stops until the next insert.
34
+ */
35
+ reset(): void;
36
+ /**
37
+ * Allocate a new ring with `newCapacity` samples and copy the unread window
38
+ * [READ, WRITE) plus control state into it. Used when growing capacity so
39
+ * we don't drop buffered audio. If `newCapacity` is smaller than the unread
40
+ * span, the oldest samples are truncated.
41
+ *
42
+ * Main thread only. `resize()` reads from the source `SharedRingBuffer` and
43
+ * writes into a freshly allocated buffer from `allocSharedRingBuffer`, so it
44
+ * relies on the same invariant as `insert()`: no concurrent main-thread
45
+ * writers. The AudioWorklet reader is tolerated via the CAS discipline used
46
+ * by READ/WRITE elsewhere.
47
+ */
48
+ resize(newCapacity: number): SharedRingBuffer;
49
+ /** Current playback timestamp derived from READ position. */
50
+ get timestamp(): Time.Micro;
51
+ /** Whether the buffer is stalled (waiting to fill). */
52
+ get stalled(): boolean;
53
+ /**
54
+ * Number of buffered samples (WRITE - READ).
55
+ *
56
+ * Non-atomic: WRITE and READ are loaded separately, so a concurrent
57
+ * writer/reader can make the two loads inconsistent. Intended for
58
+ * tests and diagnostics, not control-flow decisions.
59
+ */
60
+ get length(): number;
61
+ }
62
+ //# sourceMappingURL=shared-ring-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-ring-buffer.d.ts","sourceRoot":"","sources":["../../src/audio/shared-ring-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAShC,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;IAE3B,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,UAAQ,GACd,oBAAoB,CAatB;AA0BD,qBAAa,gBAAgB;;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAQpC,YAAY,IAAI,EAAE,oBAAoB,EAcrC;IAED;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI,CAqExD;IAED;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAiCnC;IAED,4CAA4C;IAC5C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhC;IAED;;;OAGG;IACH,KAAK,IAAI,IAAI,CAKZ;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CA6B5C;IAED,6DAA6D;IAC7D,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,CAG1B;IAED,uDAAuD;IACvD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;;OAMG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shared-ring-buffer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-ring-buffer.test.d.ts","sourceRoot":"","sources":["../../src/audio/shared-ring-buffer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import type * as Catalog from "@norskvideo/moq-hang/catalog";
2
+ import { type Getter, Signal } from "@norskvideo/moq-signals";
3
+ import type { Broadcast } from "../broadcast";
4
+ import type { Sync } from "../sync";
5
+ export type Target = {
6
+ name?: string;
7
+ };
8
+ /**
9
+ * A function that checks if an audio configuration is supported by the backend.
10
+ */
11
+ export type Supported = (config: Catalog.AudioConfig) => Promise<boolean>;
12
+ export type SourceProps = {
13
+ broadcast?: Broadcast | Signal<Broadcast | undefined>;
14
+ target?: Target | Signal<Target | undefined>;
15
+ supported?: Supported;
16
+ };
17
+ /**
18
+ * Source handles catalog extraction, support checking, and rendition selection
19
+ * for audio playback. It is used by both MSE and Decoder backends.
20
+ */
21
+ export declare class Source {
22
+ #private;
23
+ broadcast: Signal<Broadcast | undefined>;
24
+ target: Signal<Target | undefined>;
25
+ readonly catalog: Getter<Catalog.Audio | undefined>;
26
+ readonly available: Getter<Record<string, Catalog.AudioConfig>>;
27
+ readonly track: Signal<string | undefined>;
28
+ readonly config: Getter<Catalog.AudioConfig | undefined>;
29
+ supported: Signal<Supported | undefined>;
30
+ sync: Sync;
31
+ constructor(sync: Sync, props?: SourceProps);
32
+ close(): void;
33
+ }
34
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/audio/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAKpC,MAAM,MAAM,MAAM,GAAG;IAEpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1E,MAAM,MAAM,WAAW,GAAG;IACzB,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAGtD,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAG7C,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,qBAAa,MAAM;;IAClB,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAGpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAmB;IAGlF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,CAAe;IAGzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAgB;IAExE,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAGzC,IAAI,EAAE,IAAI,CAAC;IAIX,YAAY,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,WAAW,EAe1C;IAiFD,KAAK,IAAI,IAAI,CAEZ;CACD"}
package/backend.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ import * as Moq from "@norskvideo/moq-net";
2
+ import { Effect, Signal } from "@norskvideo/moq-signals";
3
+ import * as Audio from "./audio";
4
+ import type { Broadcast } from "./broadcast";
5
+ import type { BufferedRanges } from "./buffered";
6
+ import { type Latency, Sync } from "./sync";
7
+ import * as Video from "./video";
8
+ export interface Backend {
9
+ paused: Signal<boolean>;
10
+ video?: Video.Backend;
11
+ audio?: Audio.Backend;
12
+ latency: Signal<Latency>;
13
+ jitter: Signal<Moq.Time.Milli>;
14
+ buffered: Signal<boolean>;
15
+ reset(): void;
16
+ }
17
+ export interface MultiBackendProps {
18
+ element?: HTMLCanvasElement | HTMLVideoElement | Signal<HTMLCanvasElement | HTMLVideoElement | undefined>;
19
+ broadcast?: Broadcast | Signal<Broadcast | undefined>;
20
+ latency?: Latency | Signal<Latency>;
21
+ connection?: Signal<Moq.Connection.Established | undefined>;
22
+ paused?: boolean | Signal<boolean>;
23
+ visible?: Video.Visible | Signal<Video.Visible>;
24
+ }
25
+ declare class VideoBackend implements Video.Backend {
26
+ source: Video.Source;
27
+ stats: Signal<Video.Stats | undefined>;
28
+ stalled: Signal<boolean>;
29
+ buffered: Signal<BufferedRanges>;
30
+ timestamp: Signal<Moq.Time.Milli>;
31
+ constructor(source: Video.Source);
32
+ }
33
+ declare class AudioBackend implements Audio.Backend {
34
+ source: Audio.Source;
35
+ volume: Signal<number>;
36
+ muted: Signal<boolean>;
37
+ stats: Signal<Audio.Stats | undefined>;
38
+ buffered: Signal<BufferedRanges>;
39
+ context: Signal<AudioContext | undefined>;
40
+ constructor(source: Audio.Source);
41
+ }
42
+ /**
43
+ * A generic backend that supports either MSE or WebCodecs based on the provided element.
44
+ *
45
+ * This primarily backs the `<moq-watch>` web component, but is useful standalone.
46
+ */
47
+ export declare class MultiBackend implements Backend {
48
+ #private;
49
+ element: Signal<HTMLCanvasElement | HTMLVideoElement | undefined>;
50
+ broadcast: Signal<Broadcast | undefined>;
51
+ latency: Signal<Latency>;
52
+ jitter: Signal<Moq.Time.Milli>;
53
+ buffered: Signal<boolean>;
54
+ paused: Signal<boolean>;
55
+ visible: Signal<Video.Visible>;
56
+ video: VideoBackend;
57
+ audio: AudioBackend;
58
+ sync: Sync;
59
+ signals: Effect;
60
+ constructor(props?: MultiBackendProps);
61
+ reset(): void;
62
+ close(): void;
63
+ }
64
+ export {};
65
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
package/base64.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ /** Decode a base64 string into bytes. Throws on invalid input. */
2
+ export declare function base64ToBytes(b64: string): Uint8Array;
3
+ //# sourceMappingURL=base64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../src/base64.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKrD"}