Skip to content
Merged
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
1 change: 0 additions & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ moves what remains of them once their claims merge.
- [Stream credit by priority](/quest/m1/stream-credit/README.md) - every stream opens through one priority entry point, and a higher-priority group takes over or resets a lower one when credit runs out
- [Audio jitter target](/quest/m1/audio-jitter-target/README.md) - the playout target is default in both languages; audio that slows down and catches up around it in every player, graded in that direction, and a native trace replay remain
- [Buffered playback subscribes in ascending order](/quest/m1/buffered-ascending.md) - a buffered `<moq-watch>` asks for the oldest group first, so a voice reply's opening arrives first, and audio's head hold shrinks to the floor
- [Push-to-talk's press-to-audible latency fits a budget on the defaults](/quest/m1/push-to-talk-latency.md) - press to audible on the browser defaults, excluding device output, stays under a kixtop-measured budget that `just test push-to-talk` enforces
- [Lifecycles are explicit state](/quest/m1/explicit-state/README.md) - every lifecycle the 2026-11-07 audit found implicit is one enum or union, fixing the bugs in the 11 lifecycles it redesigns, with review and agent rules against new ones
- [Track drop runs are forgotten below the floor](/quest/m1/drop-runs-prune.md) - a track's dropped-group record stays proportional to its window in Rust and JS
- [A macOS camera delivers frames the renderer imports](/quest/m1/camera-nv12-macos.md) - AVFoundation capture asks for NV12, so a camera whose native format is `2vuy` reaches the renderer
Expand Down
12 changes: 5 additions & 7 deletions quest/m1/audio-jitter-target/grading.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ before the model lands, `test/audio-quality` grades:
regression.
- Dropped audio is the player's own count (`trimmed_ms`, `player_skips`).
Speeding up is not a skip.
- No row's budget is fixed at zero underruns or zero stalls. Push-to-talk's
own zero gate, in `ptt-analyze.ts`, goes with
[Push-to-talk latency](/quest/m1/push-to-talk-latency.md), not here.
- No row's budget is fixed at zero underruns or zero stalls.
- A congestion row, where the path stalls for longer than the target and
then delivers the backlog, reports the audio dropped and how long audio
takes to return to the clock.
Expand Down Expand Up @@ -45,10 +43,10 @@ The gates the audit of `main` found pushing the wrong way (2026-11-09,
`discarded_ms`).
- The 24 browser and native rows cap underruns with no ceiling on lag. Native
settled 60 to 88 ms behind its clock without failing one.
- `test/audio-quality/clients/js/ptt-analyze.ts` fails on any underrun or
stall. [Push-to-talk latency](/quest/m1/push-to-talk-latency.md) owns that
change in
[moq-dev/moq#8364](https://github.com/moq-dev/moq/pull/8364); leave it there.
- `test/audio-quality/clients/js/ptt-analyze.ts` failed on any underrun or
stall. [moq-dev/moq#8364](https://github.com/moq-dev/moq/pull/8364) made it
report the counts without gating them (maintainer, /quest-unblock,
2026-11-09), leaving their judgment to this quest.
- The unit tests that pin the old rule belong to the model quest, which
rewrites them with the behavior.

Expand Down
104 changes: 0 additions & 104 deletions quest/m1/push-to-talk-latency.md

This file was deleted.

29 changes: 15 additions & 14 deletions test/audio-quality/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,11 @@ just test push-to-talk
```

This separate, roughly nine-minute run drives the shipped publish and watch elements in one Chromium
page, and the native `moq play` as a second listener. A constant tone loops through the fake microphone, encoded as 128 kbit/s Opus with 60 ms
frames. A release mutes the publisher, which sends nothing until the next press while its rendition
stays enabled, so the listener keeps its subscription and plays comfort noise in between. The
listener holds a fixed 300 ms delay. After warmup and a mute, it measures 22 presses,
page, and the native `moq play` as a second listener. Both elements keep their defaults: Opus with
20 ms frames, and `delay: "auto"`. A constant tone loops through the fake microphone. A release
mutes the publisher, which sends nothing until the next press while its rendition stays enabled,
so the listener keeps its subscription and plays comfort noise in between. After warmup and a
mute, it measures 22 presses,
alternating two and three seconds: the first after the warmup's five-second mute, seven with no
intervening wait, seven after five seconds, and seven after sixty seconds. Both elements reach a
local relay directly over WebTransport, with no shaping, loss, or queueing, so every millisecond
Expand All @@ -141,13 +142,13 @@ measured belongs to the media pipeline rather than the path.
The native listener, `moq play --video off --delay 300ms --metrics native.ndjson`, joins on its own
WebTransport session to the same relay while the publisher talks, plays into a private null sink
([`../lib/pulse.py`](../lib/pulse.py)) as the [native rows](#native-rows) do, and must exit cleanly
on Ctrl-C. It is held to the epic's correctness checks, not its latency budget. Its metrics add what
on Ctrl-C. It is held to the same correctness checks as the browser. Its metrics add what
a mute needs: `utterances`, the media timestamp each resume after a declared silence starts from,
and `comfort`, the device time filled with comfort noise. Each press must resume on its head frame's
timestamp, so a lost head (which would resume one frame later) fails. The native clock is placed on
the page's by those resumes, each less its head's container write. Each separated press's mute,
from its release to the next press, must play comfort noise, and from the first press on the
speaker must report no gap or stall. Each press in `summary.json` carries its `native` result
from its release to the next press, must play comfort noise. Its gaps and stalls from the first
press on are counted and reported. Each press in `summary.json` carries its `native` result
beside the browser's, and `native` sums them.

`presses.json` records captured chunks at each press, WebCodecs encoder and decoder inputs and
Expand All @@ -161,18 +162,18 @@ later onset can belong to the preceding utterance. Their audible latency is alwa
separated presses have an identifiable onset.

`summary.json` matches inputs, outputs, writes, and arrivals by media timestamp, so a late arrival
is still attributed to its utterance. The command checks pipeline completeness, not the epic's
latency verdict. It refuses missing encoder inputs, a head that never reaches the listener or never
decodes, submitted frames that never encode or reach the container, written frames that never reach
is still attributed to its utterance. The command checks pipeline completeness and reports latency,
underruns, and stalls without gating them; the [audio grading](../../quest/m1/audio-jitter-target/grading.md)
judges those. It refuses missing encoder inputs,
a head that never reaches the listener or never decodes, submitted frames that never encode or reach the container, written frames that never reach
the listener, reopened capture, a new encoder (a probe or a rebuilt codec) or subscription, a mute
that disables or drops the rendition, any underrun or stall across the presses, and separated
that disables or drops the rendition, and separated
utterances with no audible output. It also fails on a broken driver or invalid capture.

The latency goal is at most 300 ms of playout added on top of one-way delivery. For each separated
press, `delivery` is the slowest of the utterance's frames that arrived before its onset, measured
For each separated press, `delivery` is the slowest of the utterance's frames that arrived before its onset, measured
from that frame's first sample (its media offset after the press). `playout` is what remains of the
render onset after the press and that delivery, and `output` is the projected device output after
that onset. `path` follows the head frame from the press to projected output in parts that sum to
that onset. `onset` is the press to the render onset, everything but the device's own output. `path` follows the head frame from the press to projected output in parts that sum to
it: `capture` (worklet delivery and framing, after the media the frame still needed),
`packetization` (that media, placed on the media clock by the newest chunk captured before the
press), `encode` (codec and container write), `network` (write to arrival, through the relay),
Expand Down
Loading