Repository navigation
fix(publish): roll audio groups before the per-group cap on release - #8118
Conversation
A long groupDuration with short frames (60s of 2.5ms Opus) passed MAX_GROUP_FRAMES and aborted the group with GroupTooLarge. The writer now opens a new group before a write would pass the frame or byte cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 2da8483
Base: 3ea7619
No actionable findings in the reviewed changes. The writer checks the existing net limits before appending, counts the encoded timestamp header in its byte budget, and resets both counts with each new group. The boundary tests exercise the real Group producer and distinguish clean rollover from GroupTooLarge. Keeping this fix in the release audio writer avoids changing the shipped net API or importing main's unbounded-group redesign.
Verification: GitHub-only static inspection of the encoder, tests, documentation, and Group producer. I did not run Bun, build, or exercise WebCodecs in a browser. Check and the latest Release gate were still in progress when checked; the PR author's reported test results were not independently rerun.
(Written by review (OpenAI))
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Audio group roll at the net caps —
#writenow tracks the open group's frame and byte counts and opens a new group before a write would tripMoq.Group.MAX_GROUP_FRAMESorMAX_GROUP_CACHE_BYTES, so a longgroupDurationwith short frames no longer aborts the rendition withGroupTooLarge. - Docs — the
groupDurationJSDoc anddoc/lib/js/publish.mdnote that a group also ends at the per-group cap. - Tests — two regression tests (frame cap at 8192, byte cap at 32 MiB via a mutable fake chunk size) that assert the rolled group closed cleanly and the next one is still open.
The guard mirrors Group.Producer.writeFrame exactly: byte accounting is payload-only on both sides, and frames < MAX_GROUP_FRAMES before the write is equivalent to the net's total >= MAX_GROUP_FRAMES on the next one. With the two clauses neutralised I reproduced GroupTooLarge in both new tests, and bun test in js/publish passes 168/168 with a clean tsc --noEmit. The caps exist only on release (origin/main's js/net/src/group.ts has no MAX_GROUP_*), so skipping the main half matches the quest.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
moq-dev#8107) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Ships the audio group roll backport (moq-dev#8118, c4c4078), which rolls audio groups before the per-group cap. Patch level chosen by the maintainer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Fixes the
releasehalf of quest/m0/release-audio-group-cap.md, claimed by moq-dev/moq#8107.Summary
groupDuration(shipped in@moq/publish0.5.5 by moq-dev/moq#7290) packs frames until a minimum timestamp span. A long span with short frames, such as 60s of 2.5ms Opus (24,000 frames), passedrelease'sMAX_GROUP_FRAMES(8192) and the group aborted withGroupTooLarge, killing the rendition.Audio.Encoder#writenow counts the open group's frames and bytes and opens a new group before a write would reachMoq.Group.MAX_GROUP_FRAMESor exceedMoq.Group.MAX_GROUP_CACHE_BYTES. ThegroupDurationdoc comment anddoc/lib/js/publish.mdsay a group also ends at the cap.mainhas no per-group cap, so there is nomainchange.Public API: none. Wire: none.
Choices made without asking
js/json's window encoder rolls at its own 1024 (to match the Snapshot cap); audio has no such constraint, and the net check (total >= MAX_GROUP_FRAMES,cacheBytes + len > MAX_GROUP_CACHE_BYTES) is deterministic, so the encoder rolls exactly at the net limits, imported from@moq/netso they cannot drift.Group.Producerexposes no frame or byte count, and adding one is a public API change on a patch branch.release; the claim PR moq-dev/moq#8107 onmainrewrites the quest to wait on this merge and the next patch publish, matching the precedent of moq-dev/moq#7290 and moq-dev/moq#7279.Validation
GroupTooLargebefore the fix.bun testinjs/publish: 168 pass, 0 fail.quest gate nix develop --command just js check: pass.Review
Codex
gpt-6.1-sol, medium effort, viaquest review --base origin/release, head2da8483b00: round 1, no findings.Head
155d8529f2: conflict-free merge oforigin/release(bbecb46, touches only the Homebrew formula template); no new review round.bun test src/audioandtsc --noEmitinjs/publishpass.🤖 Generated with Claude Code
(Written by Claude Opus 5.5)