Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The project contains multiple layers of protocols:
4. **hang** - Media-specific encoding/decoding on top of `moq-lite`. Contains:
- catalog: a JSON track containing a description of other tracks and their properties (for WebCodecs).
- container: each frame consists of a timestamp and codec bitstream
- hang-ui: Solid.js Web Components for media playback/publishing UI
- watch/publish: dedicated packages for subscribing/publishing with optional SolidJS UI overlays
5. **application** - Users building on top of `moq-lite` or `hang`

Key architectural rule: The CDN/relay does not know anything about media. Anything in the `moq` layer should be generic, using rules on the wire on how to deliver content.
Expand All @@ -56,8 +56,10 @@ Key architectural rule: The CDN/relay does not know anything about media. Anythi
signals/ # Reactive signals library (published as @moq/signals)
token/ # JWT token generation (published as @moq/token)
clock/ # Clock example (published as @moq/clock)
hang/ # Media layer (published as @moq/hang)
hang-ui/ # Web Components UI (published as @moq/hang-ui)
hang/ # Core media layer: catalog, container, support (published as @moq/hang)
ui-core/ # Shared UI components (published as @moq/ui-core)
watch/ # Watch/subscribe to streams + UI (published as @moq/watch)
publish/ # Publish media to streams + UI (published as @moq/publish)
hang-demo/ # Demo applications

/doc/ # Documentation site (VitePress, deployed via Cloudflare)
Expand All @@ -77,7 +79,7 @@ Key architectural rule: The CDN/relay does not know anything about media. Anythi
- **Common**: Use `just` for common development tasks
- **Rust**: Use `cargo` for Rust-specific operations
- **Formatting/Linting**: Biome for JS/TS formatting and linting
- **UI**: Solid.js for Web Components in `hang-ui`
- **UI**: Solid.js for Web Components in `@moq/watch/ui` and `@moq/publish/ui`
- **Builds**: Nix flake for reproducible builds (optional)

## Testing Approach
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,11 @@ This repository provides both [Rust](/rs) and [TypeScript](/js) libraries with s
|------------------------------------------|--------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
| **[@moq/lite](js/lite)** | The core pub/sub transport protocol. Intended for browsers, but can be run server-side with a WebTransport polyfill. | [![npm](https://img.shields.io/npm/v/@moq/lite)](https://www.npmjs.com/package/@moq/lite) |
| **[@moq/token](js/token)** | Authentication library & CLI for JS/TS environments (see [Authentication](doc/concept/authentication.md)) | [![npm](https://img.shields.io/npm/v/@moq/token)](https://www.npmjs.com/package/@moq/token) |
| **[@moq/hang](js/hang)** | Media-specific encoding/streaming layered on top of `moq-lite`. Provides both a Javascript API and Web Components. | [![npm](https://img.shields.io/npm/v/@moq/hang)](https://www.npmjs.com/package/@moq/hang) |
| **[@moq/hang](js/hang)** | Core media library: catalog, container, and support. Shared by `@moq/watch` and `@moq/publish`. | [![npm](https://img.shields.io/npm/v/@moq/hang)](https://www.npmjs.com/package/@moq/hang) |
| **[@moq/hang-demo](js/hang-demo)** | Examples using `@moq/hang`. | |
| **[@moq/hang-ui](js/hang-ui)**. | UI Components that interact with the Hang Web Components using SolidJS. | [![npm](https://img.shields.io/npm/v/@moq/hang-ui)](https://www.npmjs.com/package/@moq/hang-ui) |
| **[@moq/watch](js/watch)** | Subscribe to and render MoQ broadcasts (Web Component + JS API). | [![npm](https://img.shields.io/npm/v/@moq/watch)](https://www.npmjs.com/package/@moq/watch) |
| **[@moq/publish](js/publish)** | Publish media to MoQ broadcasts (Web Component + JS API). | [![npm](https://img.shields.io/npm/v/@moq/publish)](https://www.npmjs.com/package/@moq/publish) |
| **[@moq/ui-core](js/ui-core)** | Shared UI components (Button, Icon, Stats, CSS theme) used by `@moq/watch/ui` and `@moq/publish/ui`. | [![npm](https://img.shields.io/npm/v/@moq/ui-core)](https://www.npmjs.com/package/@moq/ui-core) |


## Documentation
Expand Down
275 changes: 205 additions & 70 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion doc/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ export default defineConfig({
{ text: "Publish", link: "/js/@moq/hang/publish" },
],
},
{ text: "@moq/hang-ui", link: "/js/@moq/hang-ui" },
{ text: "@moq/watch", link: "/js/@moq/watch" },
{ text: "@moq/publish", link: "/js/@moq/publish" },
{ text: "@moq/ui-core", link: "/js/@moq/ui-core" },
{ text: "@moq/token", link: "/js/@moq/token" },
{ text: "@moq/signals", link: "/js/@moq/signals" },
{ text: "@moq/web-transport-ws", link: "/js/@moq/web-transport-ws" },
Expand Down
3 changes: 2 additions & 1 deletion doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,6 @@ Or run on [native](/js/env/native) with polyfills via Node/Bun/Deno.
Some highlights:
- [@moq/lite](/js/@moq/lite) - Performs the core asynchronous networking.
- [@moq/hang](/js/@moq/hang/) - Performs any media stuff: capture, encode, transmux, decode, render.
- [@moq/hang-ui](/js/@moq/hang-ui) - A simple web UI for those too lazy to vibe code one.
- [@moq/watch](/js/@moq/watch) - Subscribe to and render MoQ broadcasts.
- [@moq/publish](/js/@moq/publish) - Publish media to MoQ broadcasts.
- [...and more](/js/)
68 changes: 0 additions & 68 deletions doc/js/@moq/hang-ui.md

This file was deleted.

198 changes: 27 additions & 171 deletions doc/js/@moq/hang/index.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
title: "@moq/hang"
description: Media library with Web Components
description: Core media library (catalog, container, support)
---

# @moq/hang

[![npm](https://img.shields.io/npm/v/@moq/hang)](https://www.npmjs.com/package/@moq/hang)
[![TypeScript](https://img.shields.io/badge/TypeScript-ready-blue.svg)](https://www.typescriptlang.org/)

High-level media library for real-time streaming using [Media over QUIC](https://moq.dev), built on top of [@moq/lite](/js/@moq/lite).
Core media library for [Media over QUIC](https://moq.dev), built on top of [@moq/lite](/js/@moq/lite). Provides shared primitives used by [`@moq/watch`](/js/@moq/watch) and [`@moq/publish`](/js/@moq/publish).

## Overview

`@moq/hang` provides:

- **Web Components** - Easiest way to add MoQ to your page
- **JavaScript API** - Advanced control for custom applications
- **WebCodecs integration** - Hardware-accelerated encoding/decoding
- **Reactive state** - Built on `@moq/signals`
- **Catalog** - JSON track describing other tracks and their codec properties (audio, video, chat, location, etc.)
- **Container** - Media framing in two formats: CMAF (fMP4) and Legacy (varint-timestamp + raw codec bitstream)
- **Support** - Browser capability detection and `<hang-support>` Web Component
- **Utilities** - Hex encoding, Opus audio polyfill (libav), latency computation, browser detection workarounds

## Installation

Expand All @@ -28,194 +28,50 @@ npm add @moq/hang
pnpm add @moq/hang
```

## Web Components
## Web Component

The fastest way to add MoQ to your web page. See [Web Components](/js/env/web) for full details.
### `<hang-support>`

### Publishing
Display browser support information:

```html
<script type="module">
import "@moq/hang/publish/element";
import "@moq/hang/support/element";
</script>

<hang-publish
url="https://relay.example.com/anon"
path="room/alice"
audio video controls>
<!-- Optional: preview -->
<video muted autoplay></video>
</hang-publish>
```

[Learn more about publishing](/js/@moq/hang/publish)

### Watching

```html
<script type="module">
import "@moq/hang/watch/element";
</script>

<hang-watch
url="https://relay.example.com/anon"
path="room/alice"
controls>
<!-- Optional: canvas for video -->
<canvas></canvas>
</hang-watch>
<hang-support mode="publish" show="partial"></hang-support>
```

## JavaScript API

For advanced use cases:

```typescript
import * as Hang from "@moq/hang";

// Create connection
const connection = new Hang.Connection("https://relay.example.com/anon");

// Publishing media
const publish = new Hang.Publish.Broadcast(connection, {
enabled: true,
name: "alice",
video: { enabled: true, device: "camera" },
audio: { enabled: true },
});

// Subscribing to media
const watch = new Hang.Watch.Broadcast(connection, {
enabled: true,
name: "alice",
video: { enabled: true },
audio: { enabled: true },
});

// Everything is reactive
publish.name.set("bob");
watch.volume.set(0.8);
```

## Features

### Real-time Latency

Uses WebTransport and WebCodecs for sub-second latency:

```typescript
const watch = new Hang.Watch.Broadcast(connection, {
name: "live-stream",
// Latency optimizations
video: { enabled: true },
});
```

### Device Selection

Choose camera or screen:

```typescript
const publish = new Hang.Publish.Broadcast(connection, {
name: "my-stream",
video: {
enabled: true,
device: "camera", // or "screen"
},
});

// Switch devices
publish.video.device.set("screen");
```

### Quality Control
// Catalog — describes tracks and their codec properties
import * as Catalog from "@moq/hang/catalog";

Control encoding quality:
// Container — media framing (CMAF and Legacy formats)
import * as Container from "@moq/hang/container";

```typescript
const publish = new Hang.Publish.Broadcast(connection, {
name: "my-stream",
video: {
enabled: true,
bitrate: 2_500_000, // 2.5 Mbps
framerate: 30,
},
});
// CMAF (fMP4) and Legacy (varint-timestamp + raw bitstream) are both available:
// Container.Cmaf — createVideoInitSegment, createAudioInitSegment, encodeDataSegment, decodeDataSegment, etc.
// Container.Legacy — Producer / Consumer classes
```

### Playback Controls
For watching and publishing, use the dedicated packages:

```typescript
const watch = new Hang.Watch.Broadcast(connection, {
name: "stream",
});

// Pause/resume
watch.paused.set(true);
watch.paused.set(false);

// Volume
watch.muted.set(false);
watch.volume.set(0.8);
```

## Reactive State

Everything uses signals from `@moq/signals`:

```typescript
import { react } from "@moq/signals/react";

const publish = document.querySelector("hang-publish") as HangPublish;

// Convert to React signal
const videoSource = react(publish.video.media);

useEffect(() => {
previewVideo.srcObject = videoSource();
}, [videoSource]);
import * as Watch from "@moq/watch";
import * as Publish from "@moq/publish";
```

## Supported Codecs

**Video:**
- H.264 (AVC) - Best compatibility
- H.265 (HEVC) - Better compression
- VP8 / VP9 - Open codec
- AV1 - Latest, best compression

**Audio:**
- Opus - Best for voice/music
- AAC - Good compatibility

Codec selection is automatic based on browser support.

## Browser Support

Requires:
- **WebTransport** - Chrome 97+, Edge 97+
- **WebCodecs** - Same browsers
- **WebAudio** - All modern browsers

## Examples

Check out [hang-demo](https://github.com/moq-dev/moq/tree/main/js/hang-demo) for:

- Video conferencing
- Screen sharing
- Chat integration
- Quality selection UI

[View more examples](https://github.com/moq-dev/moq/tree/main/js)

## Framework Integration

Works with any framework:
## Related Packages

- **React** - Via `@moq/signals/react`
- **SolidJS** - Via `@moq/signals/solid` or `@moq/hang-ui`
- **Vue** - Via `@moq/signals/vue`
- **Vanilla JS** - Direct Web Components
- **[@moq/watch](/js/@moq/watch)** — Subscribe to and render MoQ broadcasts
- **[@moq/publish](/js/@moq/publish)** — Publish media to MoQ broadcasts
- **[@moq/ui-core](/js/@moq/ui-core)** — Shared UI components
- **[@moq/lite](/js/@moq/lite)** — Core pub/sub transport protocol
- **[@moq/signals](/js/@moq/signals)** — Reactive signals library

## Protocol Specification

Expand Down
Loading
Loading