Skip to content

fix(publish): roll audio groups before the per-group cap on release - #8118

Merged
kixelated merged 2 commits into
releasefrom
backport/release-audio-group-cap
Nov 7, 2026
Merged

kixelated merged 2 commits into
releasefrom
backport/release-audio-group-cap

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes the release half of quest/m0/release-audio-group-cap.md, claimed by moq-dev/moq#8107.

Summary

groupDuration (shipped in @moq/publish 0.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), passed release's MAX_GROUP_FRAMES (8192) and the group aborted with GroupTooLarge, killing the rendition.

Audio.Encoder#write now counts the open group's frames and bytes and opens a new group before a write would reach Moq.Group.MAX_GROUP_FRAMES or exceed Moq.Group.MAX_GROUP_CACHE_BYTES. The groupDuration doc comment and doc/lib/js/publish.md say a group also ends at the cap.

main has no per-group cap, so there is no main change.

Public API: none. Wire: none.

Choices made without asking

  • Exact net caps, not a lower margin. 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/net so they cannot drift.
  • Byte cap covered too, not only frames: 8 channels of max-size AAC over 8192 frames can pass 32 MiB.
  • Counts tracked in the encoder. Group.Producer exposes no frame or byte count, and adding one is a public API change on a patch branch.
  • Quest bookkeeping. The code lands here on release; the claim PR moq-dev/moq#8107 on main rewrites 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.
  • No version bump (manual, at the next cut).

Validation

  • Reproduced first: both new tests threw GroupTooLarge before the fix.
  • bun test in js/publish: 168 pass, 0 fail.
  • quest gate nix develop --command just js check: pass.

Review

Codex gpt-6.1-sol, medium effort, via quest review --base origin/release, head 2da8483b00: round 1, no findings.

Head 155d8529f2: conflict-free merge of origin/release (bbecb46, touches only the Homebrew formula template); no new review round. bun test src/audio and tsc --noEmit in js/publish pass.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

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 kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Audio group roll at the net caps — #write now tracks the open group's frame and byte counts and opens a new group before a write would trip Moq.Group.MAX_GROUP_FRAMES or MAX_GROUP_CACHE_BYTES, so a long groupDuration with short frames no longer aborts the rendition with GroupTooLarge.
  • Docs — the groupDuration JSDoc and doc/lib/js/publish.md note 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.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

@kixelated
kixelated enabled auto-merge November 7, 2026 05:39
@kixelated
kixelated merged commit c4c4078 into release Nov 7, 2026
33 of 35 checks passed
@kixelated
kixelated deleted the backport/release-audio-group-cap branch November 7, 2026 05:42
kixelated added a commit to Frando/moq that referenced this pull request Nov 7, 2026
moq-dev#8107)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
kixelated added a commit to riedlse/moq that referenced this pull request Nov 8, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant