diff --git a/README.md b/README.md index 7b43df709d6..2465e66cb3c 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ The quickest way to see it in action (requires [Nix](https://nixos.org/download. nix develop -c just ``` -Then visit . Don't have Nix? See the [demo guide](https://doc.moq.dev/setup/) for manual setup. +It opens the watch, publish, and stats pages in your browser, or visit . Don't have Nix? See the [demo guide](https://doc.moq.dev/setup/) for manual setup. ## Architecture @@ -85,11 +85,11 @@ This repository provides both [Rust](rs) and [TypeScript](js) libraries with sim | [moq-net](rs/moq-net) | The networking layer: real-time pub/sub with built-in caching, fan-out, and prioritization. Negotiates either the `moq-lite` or `moq-transport` wire protocol. | [![docs.rs](https://docs.rs/moq-net/badge.svg)](https://docs.rs/moq-net) | | [moq-relay](rs/moq-relay) | A clusterable relay server. This relay performs fan-out connecting multiple clients and servers together. | | | [moq-auth](rs/moq-auth) | The authorization contract `moq-relay` speaks: requests, grants, leases, and the JWT that rides them. `moq auth` is the CLI. | [![docs.rs](https://docs.rs/moq-auth/badge.svg)](https://docs.rs/moq-auth) | -| [moq-tokio](rs/moq-tokio) | Opinionated helpers to configure a Quinn QUIC endpoint. It's harder than it should be. | [![docs.rs](https://docs.rs/moq-tokio/badge.svg)](https://docs.rs/moq-tokio) | +| [moq-tokio](rs/moq-tokio) | Connect and listen over QUIC, WebTransport, WebSocket, TCP/TLS, and Unix sockets, plus optional iroh and WebRTC. | [![docs.rs](https://docs.rs/moq-tokio/badge.svg)](https://docs.rs/moq-tokio) | | [moq-c](rs/moq-c) | C bindings for `moq-net`. | [![docs.rs](https://docs.rs/moq-c/badge.svg)](https://docs.rs/moq-c) | | [hang](rs/hang) | Media-specific encoding/streaming layered on top of `moq-net`. Can be used as a library. | [![docs.rs](https://docs.rs/hang/badge.svg)](https://docs.rs/hang) | | [moq-cli](rs/moq-cli) | A CLI for publishing media to MoQ relays. | | -| [moq-mux](rs/moq-mux) | Media muxers and demuxers (fMP4/CMAF, HLS) for importing content into MoQ broadcasts. | [![docs.rs](https://docs.rs/moq-mux/badge.svg)](https://docs.rs/moq-mux) | +| [moq-mux](rs/moq-mux) | Media muxers and demuxers (fMP4/CMAF, MPEG-TS, FLV, Matroska) for importing content into MoQ broadcasts. | [![docs.rs](https://docs.rs/moq-mux/badge.svg)](https://docs.rs/moq-mux) | | [moq-gst](rs/moq-gst) | A GStreamer plugin for publishing or consuming MoQ broadcasts. Not built by default; requires GStreamer dev libraries. | | ### TypeScript diff --git a/doc/bin/demo.md b/doc/bin/demo.md index 3e1b8d9436d..a2ae9ef6bc5 100644 --- a/doc/bin/demo.md +++ b/doc/bin/demo.md @@ -11,7 +11,7 @@ Each runs locally from a checkout. The web demo and MoQ Boy also live at ## Web demo ```bash -just # relay + Big Buck Bunny + the web UI at http://localhost:5173 +just # relay + Big Buck Bunny + the web UI at http://localhost:5173/watch.html ``` A Vite app in [`demo/web/`](https://github.com/moq-dev/moq/tree/main/demo/web) diff --git a/doc/bin/rtmp.md b/doc/bin/rtmp.md index 296262ebdde..df5ff22bcb4 100644 --- a/doc/bin/rtmp.md +++ b/doc/bin/rtmp.md @@ -53,5 +53,5 @@ carries the best of each. Implemented in pure Rust (no librtmp). The CLI speaks plaintext `rtmp://` only, so stream keys cross the network unencrypted. The library adds RTMPS on the same port when the embedder supplies a TLS config, and can refuse plaintext -there. FLAC enhanced-audio payloads are dropped because hang has no catalog -codec for them. MP3 works in both legacy and enhanced audio tags. +there. FLAC enhanced-audio payloads are dropped because the FLV import does not +map them. MP3 works in both legacy and enhanced audio tags. diff --git a/doc/bin/srt.md b/doc/bin/srt.md index 7f7ee1efc6a..1e0069edfc4 100644 --- a/doc/bin/srt.md +++ b/doc/bin/srt.md @@ -8,8 +8,8 @@ description: SRT contribution and playback `moq import srt` accepts SRT pushes (`--listen`) or pulls from a remote SRT source (`--connect`); `moq export srt` serves SRT to players or pushes to a remote. The payload is MPEG-TS, so the same codecs and behavior as -[`import ts`](/bin/cli) apply: H.264/H.265 video and AAC, MP2, AC-3, or E-AC-3 -audio. A damaged unit is dropped and the session stays up; video resumes at its +[`import ts`](/bin/cli) apply: H.264/H.265 video and AAC, MP2, AC-3, E-AC-3, or +Opus audio. A damaged unit is dropped and the session stays up; video resumes at its next keyframe, freezing for up to one GOP. ```bash diff --git a/doc/concept/transport.md b/doc/concept/transport.md index 001d828e1c1..cddcb32583f 100644 --- a/doc/concept/transport.md +++ b/doc/concept/transport.md @@ -42,7 +42,7 @@ connection (`wss://`) and keep whichever wins. A small multiplexer, [qmux](/draft/qmux-websocket), carries MoQ streams over the socket. It works everywhere but cannot escape TCP head-of-line blocking, so priority and resets only help once bytes leave the TCP queue. The fallback is automatic in every -client; the relay enables it with `[web.https]`. A session that lands on +client; the relay serves it on its `[web.http]` or `[web.https]` listener. A session that lands on WebSocket stays there until it ends; the next connect races again. ## Raw QUIC (native) @@ -50,8 +50,8 @@ WebSocket stays there until it ends; the next connect races again. Native clients dial the relay directly with the MoQ ALPN, skipping the HTTP/3 handshake. The URL path and `?jwt=` token travel in the MoQ `SETUP` message instead of a `CONNECT` request, so the server sees the same thing either way. -`moq-tokio` picks this automatically for `https://` URLs; use `moql://` or -`moqt://` to force it. +`moq-tokio` dials WebTransport for `https://` URLs; use `moql://` or `moqt://` +for raw QUIC. ## TCP and Unix sockets (local workers) diff --git a/doc/setup/index.md b/doc/setup/index.md index 4b8e238b267..2d2ec7dad9e 100644 --- a/doc/setup/index.md +++ b/doc/setup/index.md @@ -42,7 +42,7 @@ Windows users should run `setup.bat` first; see [Development](/setup/dev#windows 1. [moq-relay](/bin/relay/) on `localhost:4443` with a generated certificate and anonymous access. 2. [moq-cli](/bin/cli) publishing Big Buck Bunny through the relay. -3. The [web demo](/bin/demo) at [localhost:5173](http://localhost:5173), where you can watch the stream or publish your camera. +3. The [web demo](/bin/demo) at [localhost:5173/watch.html](http://localhost:5173/watch.html), where you can watch the stream or publish your camera. ## Skip the relay diff --git a/quest/m1/README.md b/quest/m1/README.md index f92c42aec43..ba973768704 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -127,7 +127,6 @@ lands before the cut. - [Test cost audit](/quest/m1/audit-test-cost.md) - the slowest, flakiest, and least valuable tests are fixed, deleted, or planned - [Interop report](/quest/m1/interop-report.md) - nightly Interop results publish as a color-coded matrix on the Pages site instead of only in logs - [CI workflow audit](/quest/m1/audit-ci.md) - every workflow and job gives a signal someone sees, at a cost that signal justifies, or is fixed, moved, or deleted -- [Documentation audit](/quest/m1/audit-docs.md) - stale pages, examples, links, and undocumented exports are fixed or planned - [Artifact size audit](/quest/m1/audit-size.md) - binary, FFI, WASM, and bundle growth since the m0 run is explained, fixed, or planned ## Related diff --git a/quest/m1/audit-docs.md b/quest/m1/audit-docs.md deleted file mode 100644 index 5cb22af97eb..00000000000 --- a/quest/m1/audit-docs.md +++ /dev/null @@ -1,56 +0,0 @@ -# [M] Documentation audit - -## Goal - -Docs match the code: stale pages, broken examples, broken links, and -undocumented exported symbols are fixed or planned. - -## Plan - -Recurs once per major release (decided 2026-10-19). The PR that finishes -this run also adds the next one with the same file name at the end of the next -milestone's `Required` (m0 to m1, m1 to m2). The successor keeps the Goal -and this paragraph; the rest of its Plan is rewritten with what this run -learned: baselines, results, and what to check first. A successor placed in m2 -also lists the [release cut](/quest/m2/release/cut.md) under `Required`, so it -waits for the release in flight to ship. Only `/quest-delete` ends the -recurrence. Fixes land in the run's PR, one commit each, rather than as follow-ups. -Only a change that needs a maintainer decision (public API, scope) or is -independently landable and too large to review alongside the rest becomes a -follow-up through `/quest-plan`. - -Follow `doc/AGENTS.md` for what belongs in `doc/`. The m0 run (2026-10-19) -fixed stale codec, driver, auth, snapshot, Go wrapper, and stats-example -claims, documented every public item in hang, moq-archive, moq-auth, -moq-relay, and moq-nvenc, and filled the core JS packages' gaps. Start by -comparing against these baselines: - -- Rust: 26 crates set `#![warn(missing_docs)]`. Count the rest with - `cargo rustdoc -p --lib --all-features -- -W missing_docs`; only - `--all-features` reaches feature-gated items, which is how the m0 run found - moq-auth's undocumented server refusals, and `just rs wasm` reaches - wasm-only items such as kio's `MaybeSend`. `moq-mux`, `moq-ffi`, and `moq-c` - have follow-ups. `moq-video`, `moq-audio`, and `moq-sock` are documented on - Linux but stay unlinted: they gate public items on macOS, Windows, and - Android, and the dev shell has no std for those targets, so a lint could - only be verified in the merge queue's platform jobs. `moq-gst` cannot lint - because `gst::plugin_define!` emits undocumented public items. `moq-v4l` - is a fork of the `v4l` crate with 222 undocumented hand-written items beside - its generated `sys` bindings; decide whether a fork earns docs before - writing them. `libmoq` and the `moq-native` tombstone export nothing. -- JS: every published package's build runs `js/common/docs.ts`, which fails - on an undocumented export or public class member, so check only that its - exemptions (private, protected, symbol brands, and custom element reactions) - still hold up and that docs say something. -- Links: GET (not HEAD) every external URL in `doc/` with a browser user - agent; 262 answered except npmjs.com package pages, which refuse - non-browser clients (check `registry.npmjs.org/` instead), and - placeholder hosts. crates.io answers 200 to such a GET. -- CLI: all complete shell examples parse with `--help` appended against a - build with `capture,play,transcode,iroh,openh264`, which unknown flags fail - but bad values do not. `gst-inspect-1.0` of a debug `moq-gst` build lists - every element and pad property `doc/bin/gstreamer.md` names. -- Cross-Package Sync: walked from the 2026-10-16 release cut (`d0b086e71b`) - through `9b90cdd569`. Walk the next run from there. The table's Go row - and `rs/moq-ffi/AGENTS.md` name `go/wrapper/moq`, which does not exist; - the wrapper is `go/wrapper/*.go` and its subpackages. diff --git a/quest/m2/README.md b/quest/m2/README.md index 7f161f908cd..c60745359a2 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -187,3 +187,4 @@ ranked just below deterministic TS legs, which it requires. - [FromStr parsers](/quest/m2/from-str-trait.md) - hang, moq-auth, and moq-msf implement `FromStr` instead of inherent `from_str` - [Drop dead items](/quest/m2/drop-dead-items.md) - the audit's uncalled public items and test helpers are removed - [Test coverage audit](/quest/m2/audit-test-coverage.md) - repeat the coverage audit against the m1 baselines after the next release ships +- [Documentation audit](/quest/m2/audit-docs.md) - repeat the docs audit after the release ships, against the m1 baselines diff --git a/quest/m2/audit-docs.md b/quest/m2/audit-docs.md new file mode 100644 index 00000000000..eb79cf76ac0 --- /dev/null +++ b/quest/m2/audit-docs.md @@ -0,0 +1,70 @@ +# [M] Documentation audit + +## Goal + +Docs match the code: stale pages, broken examples, broken links, and +undocumented exported symbols are fixed or planned. + +## Plan + +Recurs once per major release (decided 2026-10-19). The PR that finishes +this run also adds the next one with the same file name at the end of the next +milestone's `Required` (m0 to m1, m1 to m2). The successor keeps the Goal +and this paragraph; the rest of its Plan is rewritten with what this run +learned: baselines, results, and what to check first. A successor placed in m2 +also lists the [release cut](/quest/m2/release/cut.md) under `Required`, so it +waits for the release in flight to ship. Only `/quest-delete` ends the +recurrence. Fixes land in the run's PR, one commit each, rather than as follow-ups. +Only a change that needs a maintainer decision (public API, scope) or is +independently landable and too large to review alongside the rest becomes a +follow-up through `/quest-plan`. + +Follow `doc/AGENTS.md` for what belongs in `doc/`. The docs site deploys from +`release`, so a page describing an unreleased package (such as `@moq/video`, +first published by the release cut) is expected to 404 on its registry until +then. The m1 run (2026-10-21) found the stale claims in pages no PR had touched +for a while: the root `README.md` crate table, `doc/concept/transport.md`, and +the codec lists in `doc/bin/rtmp.md` and `srt.md`. Read those kinds of pages +claim by claim against the code first; the pages recent PRs edit are the +freshest. Baselines: + +- Rust: 28 crates set `#![warn(missing_docs)]`; m1 added `moq-shaper` and + `moq-wasm`. Count the rest with + `cargo rustdoc -p --lib --all-features -- -W missing_docs`, and + `moq-wasm` with `--target wasm32-unknown-unknown`, since it is empty on + native. `moq-auth` is ambiguous with its crates.io copy, so pass its + `path+file://` spec. Every linted crate was clean with all features. + `moq-audio`, `moq-video`, and `moq-sock` were also clean on Linux but stay + unlinted for their macOS, Windows, and Android items. `moq-gst` has 3 items + from `gst::plugin_define!`. `moq-v4l` reports 3108, nearly all its generated + `sys` bindings; whether the fork earns docs is still undecided. `moq-mux`, + `moq-ffi`, and `moq-c` had follow-ups in flight + ([docs-mux](https://github.com/moq-dev/moq/pull/6088), + [docs-bindings](https://github.com/moq-dev/moq/pull/6091)); check that they + landed and set the lint. +- JS: since [docs-js](https://github.com/moq-dev/moq/pull/6163), every + published package's build runs `js/common/docs.ts`, which fails on an + undocumented export or public class member, so check only that its + exemptions (private, protected, symbol brands, and custom element reactions) + still hold up and that docs say something. +- Links: GET (not HEAD) every external URL in `doc/` with a browser user + agent. 316 URLs: all answered except placeholder and local hosts, relay + URLs that only speak MoQ, npmjs.com and w3.org pages that refuse + non-browser clients, and the unreleased items above. Check npm packages on + `registry.npmjs.org/` and crates on the crates.io API, since + crates.io pages answer 200 to anything. `README.md`'s `moq-c` badge waits on + the crate's first publish. +- CLI: all 68 shell invocations in `doc/`, `README.md`, and + `rs/moq-cli/README.md` parse with `--help` appended against a build with + `capture,play,transcode,iroh,openh264`, after substituting a URL for the + elided `moq ...` connect. Unknown flags fail but bad values do not. + `gst-inspect-1.0` of a debug `moq-gst` build lists every element and pad + property `doc/bin/gstreamer.md` names. +- Cross-Package Sync: walked from `9b90cdd569` through `7d2a91fe66`. Walk the + next run from there. Go has no `Client` failure accessor because `Dial` + returns only once connected; the maintainer chose to leave that until a Go + caller needs it, so it is not a gap. + +## Required + +- [Release cut](/quest/m2/release/cut.md) - the release in flight ships before this run starts diff --git a/rs/moq-c/src/api.rs b/rs/moq-c/src/api.rs index 0ae309ac25d..42216348884 100644 --- a/rs/moq-c/src/api.rs +++ b/rs/moq-c/src/api.rs @@ -594,8 +594,8 @@ pub struct moq_subscription { /// The spans of the track to deliver, or NULL for everything `max_delay_us` still /// considers fresh. A non-NULL pointer with `ranges_len` 0 asks for nothing. /// - /// A request to the publisher, aggregated across every subscriber. Reads start at the - /// lowest group a range starts at, and stop past the last absolute end. + /// A request to the publisher, aggregated across every subscriber, and this + /// subscription's read filter: it reads only the groups its own ranges cover. pub ranges: *const moq_range, pub ranges_len: usize, diff --git a/rs/moq-shaper/src/lib.rs b/rs/moq-shaper/src/lib.rs index b7933e45555..1c1c28ce0fa 100644 --- a/rs/moq-shaper/src/lib.rs +++ b/rs/moq-shaper/src/lib.rs @@ -18,6 +18,8 @@ //! model that keeps the order, one link shared by every client, batches, steps, //! and named profiles loaded as a [`Preset`]. The README says why each exists. +#![warn(missing_docs)] + use std::{ cmp::Reverse, collections::{BTreeMap, BinaryHeap, HashMap, hash_map}, diff --git a/rs/moq-wasm/src/lib.rs b/rs/moq-wasm/src/lib.rs index 63c2172567d..89877491265 100644 --- a/rs/moq-wasm/src/lib.rs +++ b/rs/moq-wasm/src/lib.rs @@ -20,6 +20,7 @@ // Browser-only crate. Empty on native so `cargo check --workspace` stays green. #![cfg(target_arch = "wasm32")] +#![warn(missing_docs)] use std::cell::RefCell; use std::pin::pin; @@ -218,7 +219,7 @@ pub struct Track { #[wasm_bindgen] impl Track { - /// Receive the next group in arrival order, or `null` when the track ends. + /// Receive the next group in arrival order, or `undefined` when the track ends. #[wasm_bindgen(js_name = recvGroup, unchecked_return_type = "Promise")] pub fn recv_group(&self) -> Promise { let cell = self.inner.clone(); @@ -254,12 +255,13 @@ pub struct Group { #[wasm_bindgen] impl Group { + /// The group's sequence number within its track. #[wasm_bindgen(getter)] pub fn sequence(&self) -> u64 { self.sequence } - /// Read the next frame in the group, or `null` at the end of the group. + /// Read the next frame in the group, or `undefined` at the end of the group. #[wasm_bindgen(js_name = readFrame, unchecked_return_type = "Promise")] pub fn read_frame(&self) -> Promise { let cell = self.inner.clone();