Language: Python (asyncio) Maintainer: Giovanni Marzot GitHub: gmarzot/aiomoqt Transport: gmarzot/aiopquic (Python/Cython bindings to picoquic)
Overview
Python async implementation of MOQ Transport, using aiopquic for the QUIC transport layer.
Draft Support
- Draft 14 / 16 / 18 general-purpose MOQ client + server, with ALPN-based negotiation (
moq-00for draft-14,moqt-16for draft-16,moqt-18for draft-18) - Latest release: v0.11.1 (2026-09-22 00:50 UTC) — tag
0.11.1, from PR #38 (+2,351/−333 across 45 files). The headline is relay FETCH plus namespace discovery: the gap Aman Sharma hit on Sep-17 (“your relay doesn’t handle FETCH”) and Will Law answered on Sep-18 with the design rule that a cacheless relay should issue its own upstream FETCH against the original publisher. Also in the release:PUBLISH_DONEends a subscription, not the session (withregister_publish_done_handler()/SubscribedTrack(on_done=…)); the default FETCH handler rejects withNOT_SUPPORTEDinstead of sending aFETCH_OKit never follows with a data stream (§10.13); object timestamps move to the loc-04TIMESTAMP(0x10, wall-clock µs) from the private0x20, with receivers accepting both; and--draftacceptsdraft-18/d18/moqt-18spellings. Sharma’s Sep-21 verification: “The FETCH fixes all check out, and SUBSCRIBE_NAMESPACE now delivers NAMESPACE” — with one open gap, observers never receiveNAMESPACE_DONE, on either namespace withdrawal or publisher session close. It published after the Sep-22 interop nightly started, so the matrix cannot reflect it before the Sep-23 cut. - Latest release: v0.11.0 (final, 2026-09-17) — tag
0.11.0(published Sep-17 14:13 UTC via PR #36), shipping alongside aiopquic v0.4.0 (PyPI). This is the first final 0.11.0 after a long rc chain (rc3 Sep-3 → rc6 Sep-13). Announced on#moq(Marzot, Sep-17) as “Drafts 14, 16, 18 general purpose MOQ client/server package … numerous performance improvements, conformance fixes and added media pipeline support w/ MSF/CMSF LOC/CMAF/TS.” It finally ships the long-in-flight SUBSCRIBE_OKvi64decode fix (see below) in a tagged release, plus a new media pipeline carrying LOC/CMAF/TS payloads via MSF/CMSF. Prior stable: v0.10.6 (~July 8, 2026; PyPIaiomoqt) - v0.11.0 interop, Sep-17: Steven Riedl (Pluto TV) ran the ghcr
latest(14:13Z) build through the interop-runner harness against thestitcher-moq/ moq-relay endpoints and got 6/6 on raw QUIC and 6/6 on WebTransport (probe pins draft-16;DRAFT=18also 6/6) — tests 4 and 6 pass via aiomoqt’s COMPAT path around moq-relay’s non-spec 404 (a moq-dev-side quirk, not aiomoqt). Since the nightly pullslatest, the first runner matrix with 0.11 across the board is the Sep-18 cut. Riedl also flagged an entrypoint draft-pin bug:DRAFT=draft-18(the runner-registry spelling) makesmoq_interop_clientexit 2 (invalid parse_draft_spec value: 'draft-18', no TAP) andMOQT_DRAFT=draft-18is silently ignored — onlyDRAFT=18/--draft 18work; acceptingdraft-NNwould make the runner’s injectedDRAFTsafe. Separately Aman Sharma noted aiomoqt’sersatz-relaydoesn’t handle FETCH and SUBSCRIBE_NAMESPACE may be incomplete — Marzot’s reply reiterated it is “not a real relay” (no cache; a test vehicle for exercising more APIs/scenarios), extensible on request. - draft-18 conformance now passing 12/12 (Sep-3): the aiomoqt CI conformance job (moq-test from a pinned moxygen build) reached its first green run — d16 + d18 12/12 on Sep-3, the payoff of the Sep-2/3 hackathon relay hardening.
- Relay role added (Sep-2), hardened into “ersatz-relay” (Sep-3): aiomoqt grew a relay — self-described “pseudo-relay … a vehicle for testing pub/sub flows as both client and server,” registered in the interop-runner as
aiomoqt-relay/aiomoqt-relay-quic. Its Sep-2 conformance run drove the first relay fixes (“relay dials upstream origins,” “forward the publisher’s priority through the relay,” “relay serves the bare-PUBLISH flow,” “relay forwards objects upstream to downstream,” “relay matches announced namespaces by prefix,” “never send a control message the draft doesn’t define,” “d18 LARGEST_OBJECT carries its Length field”). On Sep-3 Aman Sharma surfaced a further batch — the relay was sending the removedPUBLISH_NAMESPACE_DONE, puttingREQUEST_OK/REQUEST_ERRORon the control stream instead of the request bidi stream, doing a namespace equality check instead of prefix matching, a delivery-semantics bug (a second pub/sub run against a fresh relay delivered nothing), and not handlingTRACK_STATUS— and Marzot fixed them plus added realSUBSCRIBE_TRACKS→PUBLISHfan-out (§9.5), GOAWAY send/receive, and SETUP validation. Marzot promoted the name from “next stop ersatz-relay” to “ersatz-relay now copyrighted” while keeping the “not a real relay” disclaimer. - Interop tested against 6 relay implementations across both drafts
- draft-18 SUBSCRIBE_OK parse bug (found 2026-08-13; fixed in v0.11.0): v0.10.6 decodes the SUBSCRIBE_OK Track-Properties block with RFC 9000 varints instead of the LOC-style
vi64, so it runs off the end of the message whenever a property value is ≥ 64 (e.g.TIMESCALE=1000, encoded83 e8) — surfacing as “truncated trailing extensions block.” Root-caused by Giovanni Marzot after Steven Riedl (Pluto TV) hit it subscribing to a moq-dev relay (whose SUBSCRIBE_OK is spec-correct); the encode/decode fix shipped in aiomoqt v0.11.0 (Sep-17) alongside aiopquic v0.4.0. Workaround on v0.10.6:MOQTMessage._tolerate_trailing_extensions = Truecompletes the subscribe but skips the property. - v0.10.6 is session-fatal against moq-relay ≥ 0.14.8 (Aug-15): moq-dev’s relay got stricter at 0.14.8 (PR #2667: the session is closed on a malformed NAMESPACE), so aiomoqt v0.10.6’s draft-18 subscribe flow now fails the whole session (
err=unexpected message) where older relays warned and continued. Reported by Steven Riedl (Pluto TV), who is upgrading Pluto’s public relay to 0.14.8 — another reason to validate v0.11.0 against a current relay before release. relay_probetooling (python -m aiomoqt.tools.relay_probe --url …): reports a relay’s transport (QUIC vs H3/WT), its accepted draft set, and RTT — used Aug-14 to resolve WebTransport-path discovery forfb.mvfst.net:9448andmoqx-main.ci.openmoq.org:4433(both want/moq-relay, negotiate draft-14/16/18). Ships in the examples with v0.10.6.
Vienna Hackathon (IETF 126)
At the July-19 IETF-126 Vienna Hackathon, Giovanni Marzot ran a control-plane interop regression with aiomoqt v0.10.6 (CI run), reporting “good results” and logging the output to the ad-hoc interop wiki. Marzot also maintains the openmoq/moqx moq_decode.py decoder — used by other Hackathon participants (afrind) to debug wire-format errors — and landed a July-19 request_id cleanup (moqx PR #496) aligning it with draft-18.
Related Projects
- aiopquic - Python/Cython bindings to picoquic (shared 2026-03-23)
- Giovanni also created content for the moq-transport wiki (2026-03-31)
Related
- interop-runner - Testing framework