@moq/lite
A TypeScript implementation of Media over QUIC providing real-time data delivery in web browsers. Implements the moq-lite specification.
Overview
@moq/lite is the browser equivalent of the Rust moq-lite crate, providing the core networking layer for MoQ. For higher-level media functionality, use @moq/hang.
Installation
bun add @moq/lite
# or
npm add @moq/lite
pnpm add @moq/lite
yarn add @moq/liteQuick Start
Basic Connection
import * as Moq from "@moq/lite";
// Connect to a MoQ relay server
const connection = await Moq.Connection.connect(
new URL("https://relay.example.com/anon")
);
console.log("Connected to MoQ relay!");Publishing Data
import * as Moq from "@moq/lite";
const connection = await Moq.Connection.connect(
new URL("https://relay.example.com/anon")
);
// Create a broadcast
const broadcast = new Moq.Broadcast();
// Subscribe to a track (creates it for writing)
const track = broadcast.subscribe("chat", 0);
// Send data in groups
const group = track.appendGroup();
group.writeString("Hello, MoQ!");
group.close();
// Publish to the relay
connection.publish("my-broadcast", broadcast);Subscribing to Data
import * as Moq from "@moq/lite";
const connection = await Moq.Connection.connect(
new URL("https://relay.example.com/anon")
);
// Subscribe to a broadcast
const broadcast = connection.consume("my-broadcast");
// Wait for a track request
const request = await broadcast.requested();
if (request) {
const track = request.track;
// Read data as it arrives
for (;;) {
const group = await track.nextGroup();
if (!group) break;
for (;;) {
const frame = await group.readString();
if (!frame) break;
console.log("Received:", frame);
}
}
}Stream Discovery
import * as Moq from "@moq/lite";
const connection = await Moq.Connection.connect(
new URL("https://relay.example.com/anon")
);
// Discover broadcasts announced by the server
const announced = connection.announced();
for (;;) {
const entry = await announced.next();
if (!entry) break;
console.log("Broadcast:", entry.path, entry.active ? "online" : "offline");
if (entry.active) {
// Subscribe to the broadcast
const broadcast = connection.consume(entry.path);
// ... handle the broadcast
}
}Core Concepts
Broadcasts
A collection of related tracks:
const broadcast = new Moq.Broadcast();Tracks
Named streams within a broadcast, created via subscribe:
const track = broadcast.subscribe("video", 0);Groups
Collections of frames (usually aligned with keyframes):
const group = track.appendGroup();
group.writeFrame(frameData);
group.close();Frames
Individual data chunks:
// Write raw bytes
group.writeFrame(new Uint8Array([1, 2, 3]));
// Write string (convenience method)
group.writeString("Hello!");Advanced Usage
Authentication
Pass JWT tokens via query parameters:
const connection = await Moq.Connection.connect(
new URL(`https://relay.example.com/room/123?jwt=${token}`)
);See Authentication guide for details.
Priority
Set priority when subscribing to a track:
const track = broadcast.subscribe("video", 10); // Higher priorityRunning Server-Side
@moq/lite can also run server-side using a WebTransport polyfill:
import { WebTransport, quicheLoaded } from "@fails-components/webtransport";
globalThis.WebTransport = WebTransport;
import * as Moq from "@moq/lite";
await quicheLoaded;
const connection = await Moq.Connection.connect(
new URL("https://relay.example.com/anon")
);
// Same API as browserTypeScript Support
Full TypeScript support with type definitions:
import type { Broadcast, Track } from "@moq/lite";
const broadcast: Broadcast = new Moq.Broadcast();
const track: Track = broadcast.subscribe("video", 0);Browser Compatibility
Requires WebTransport support:
- Chrome 97+
- Edge 97+
- Brave (recent versions)
Firefox and Safari support is experimental or planned.
Examples
For more examples, see:
Protocol Specification
See the moq-lite specification for protocol details.
Next Steps
- Build media apps with @moq/hang
- Learn about Web Components
- View code examples
- Read the Concepts guide