@moq/watch
Subscribe to and render MoQ broadcasts. Provides both a JavaScript API and a <moq-watch> Web Component, plus an optional <moq-watch-ui> overlay.
Installation
bun add @moq/watch
# or
npm add @moq/watchNo-build CDN usage
For quick demos or single-page embeds where a bundler is overkill, load the package straight from jsDelivr with the +esm endpoint. jsDelivr transforms the published file and rewrites bare imports (like @moq/hang, @moq/net) to other +esm URLs, so it loads in the browser with no import map or local build step:
<script type="module">
import "https://cdn.jsdelivr.net/npm/@moq/watch/element.js/+esm";
import "https://cdn.jsdelivr.net/npm/@moq/watch/ui/index.js/+esm";
</script>
<moq-watch-ui>
<moq-watch url="https://relay.example.com/anon" name="room/alice.hang">
<canvas></canvas>
</moq-watch>
</moq-watch-ui>Pin a version range in the URL for production, e.g. https://cdn.jsdelivr.net/npm/@moq/watch@0.2/element.js/+esm. esm.sh (https://esm.sh/@moq/watch/element) works the same way if you prefer it.
For anything beyond embedding on a static page, install the package and use a real bundler (the examples below).
Web Component
<script type="module">
import "@moq/watch/element";
</script>
<moq-watch
url="https://relay.example.com/anon"
name="room/alice.hang"
controls>
<canvas></canvas>
</moq-watch>Attributes:
url(required): Relay server URLname(required): Broadcast namecontrols: Show playback controls (boolean)paused: Pause playback (boolean)muted: Mute audio (boolean)volume: Audio volume (0 to 1, default: 1)catalog-format: Catalog format. One of"hang","msf"(see MSF), or"manual"(supply the catalog yourself). When omitted, the format is auto-detected from the broadcastnameextension (.hangor.msf), falling back to"hang".
Catalog Formats
@moq/watch can consume either the default hang catalog or MSF (MoQ Streaming Format). The format is detected from the broadcast name extension by default. room/alice.hang uses hang, room/alice.msf uses MSF. Set catalog-format explicitly to override:
<moq-watch
url="https://relay.example.com/anon"
name="room/alice.hang"
catalog-format="msf">
<canvas></canvas>
</moq-watch>import * as Watch from "@moq/watch";
const broadcast = new Watch.Broadcast({
connection,
enabled: true,
name: "alice.hang",
catalogFormat: "msf",
});
// or toggle at runtime
broadcast.catalogFormat.set("msf");Manual catalogs
Use catalog-format="manual" (or catalogFormat: "manual") to skip the catalog track entirely and supply a Catalog.Root directly. The connection and broadcast name are still required, since they're used to subscribe to the media tracks named by the catalog. Update the catalog at any time by writing to the signal:
import * as Watch from "@moq/watch";
const broadcast = new Watch.Broadcast({
connection,
enabled: true,
name: "alice.hang",
catalogFormat: "manual",
catalog: {
video: { renditions: { hd: { codec: "vp09.00.10.08", container: { kind: "legacy" } } } },
},
});
// Replace at runtime
broadcast.catalog.set(nextCatalog);The web component exposes the same field as a JS property:
const el = document.querySelector("moq-watch")!;
el.catalogFormat = "manual";
el.catalog = myCatalog;Switching
catalogFormatbetween"manual"and a fetched format ("hang"/"msf") tears down the previous fetch loop, which clearscatalog. Set the catalog after switching to"manual", not before.
UI Overlay
Import @moq/watch/ui for a Web Component overlay with buffering indicator, stats panel, and playback controls:
<script type="module">
import "@moq/watch/element";
import "@moq/watch/ui";
</script>
<moq-watch-ui>
<moq-watch
url="https://relay.example.com/anon"
name="room/alice.hang">
<canvas></canvas>
</moq-watch>
</moq-watch-ui>The <moq-watch-ui> element automatically discovers the nested <moq-watch> and wires up reactive controls.
JavaScript API
import * as Watch from "@moq/watch";
const broadcast = new Watch.Broadcast({
connection,
enabled: true,
name: "alice.hang",
reload: true,
});Related Packages
- @moq/publish: Publish media to MoQ broadcasts
- @moq/hang: Core media library (catalog, container, support)
- @moq/net: Core pub/sub transport protocol