Summary
The browser subscriber cells (* -> js-vite, * -> js-esbuild, * -> js-jsdelivr) fail the media smoke with decoded 0 frames. This is not a client bug — it's a headless-Chromium codec limitation — plus one latent driver bug that would block the cell from ever passing even once the codec issue is resolved.
Root cause: headless Chromium encodes H.264 but can't decode it
Confirmed by isolating the direction:
- The browser publishes H.264 fine —
js-vite -> go, js-vite -> kotlin, js-vite -> c all pass. So WebCodecs H.264 encode works (Chromium bundles OpenH264 for encode).
- The browser can't decode —
js-vite -> js-vite (browser→browser) also produces decoded 0 frames, and so does python -> js-vite from a known-good publisher.
That asymmetry is the well-known Chromium behavior: WebCodecs H.264 decode needs platform/proprietary decoders that the headless runner lacks, while encode does not. The decode happens entirely inside the published <moq-watch> (@moq/watch) element; the smoke page code (clients/js/jsdelivr/setup.js) is minimal and correct — it just declares <moq-watch url name> with a canvas.
clients/js/driver.ts launches channel: "chromium" (full Chromium), headless: true.
Options to actually make the cell pass (harness decision)
- Publish a codec headless Chromium can decode — VP8 / VP9 / AV1 instead of H.264 for the browser-subscriber path. Cleanest if the publishers/importers support it.
- Run headed Chromium in CI (e.g. via
xvfb), if that gives H.264 decode.
- Accept the limitation and exclude browser variants from the subscriber set (keep them as publishers only, which is their reliable role today), documenting why.
Prerequisite bug regardless of the above
clients/js/driver.ts reads the decoded-frame count via w.backend?.video?.stats?.peek()?.frameCount, but @moq/watch 0.4.0 moved the decoder off backend — the element now exposes video: Video.Decoder directly. So the accessor should be:
w?.video?.stats?.peek()?.frameCount ?? 0
Until that's fixed the driver reads 0 even if decode works, so it must land as part of (or before) whatever codec fix is chosen.
Context
Discovered while porting the non-browser clients to the current published APIs (#21, #22, #23 for Go/Kotlin/Swift/Python/native-JS). Those are all fixed and green; the browser-subscriber cell is the remaining red on the media matrix (alongside c-pkgconfig, which is fixed upstream by moq-dev/moq#2502 pending a libmoq release).
(written by Opus 4.8)
Summary
The browser subscriber cells (
* -> js-vite,* -> js-esbuild,* -> js-jsdelivr) fail the media smoke withdecoded 0 frames. This is not a client bug — it's a headless-Chromium codec limitation — plus one latent driver bug that would block the cell from ever passing even once the codec issue is resolved.Root cause: headless Chromium encodes H.264 but can't decode it
Confirmed by isolating the direction:
js-vite -> go,js-vite -> kotlin,js-vite -> call pass. So WebCodecs H.264 encode works (Chromium bundles OpenH264 for encode).js-vite -> js-vite(browser→browser) also producesdecoded 0 frames, and so doespython -> js-vitefrom a known-good publisher.That asymmetry is the well-known Chromium behavior: WebCodecs H.264 decode needs platform/proprietary decoders that the headless runner lacks, while encode does not. The decode happens entirely inside the published
<moq-watch>(@moq/watch) element; the smoke page code (clients/js/jsdelivr/setup.js) is minimal and correct — it just declares<moq-watch url name>with a canvas.clients/js/driver.tslauncheschannel: "chromium"(full Chromium),headless: true.Options to actually make the cell pass (harness decision)
xvfb), if that gives H.264 decode.Prerequisite bug regardless of the above
clients/js/driver.tsreads the decoded-frame count viaw.backend?.video?.stats?.peek()?.frameCount, but@moq/watch 0.4.0moved the decoder offbackend— the element now exposesvideo: Video.Decoderdirectly. So the accessor should be:Until that's fixed the driver reads
0even if decode works, so it must land as part of (or before) whatever codec fix is chosen.Context
Discovered while porting the non-browser clients to the current published APIs (#21, #22, #23 for Go/Kotlin/Swift/Python/native-JS). Those are all fixed and green; the browser-subscriber cell is the remaining red on the media matrix (alongside
c-pkgconfig, which is fixed upstream by moq-dev/moq#2502 pending a libmoq release).(written by Opus 4.8)