Merge main into dev#1950
Conversation
…#1903) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…pport (#1902) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…#1905) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…nt-tls-* flags consistent (#1901) Co-authored-by: Claude <noreply@anthropic.com>
…ds (#1908) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…enchmark) (#1912) Co-authored-by: Claude <noreply@anthropic.com>
…r::request_broadcast (#1913) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
#1914) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…xport) (#1915) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
…ks) (#1918) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Luke Curley <luke.curley@discordapp.com>
…1858) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…updates (#1832) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…1942) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Luke Curley <kixelated@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Replace the consume-side-only catalog::Filter with one selection type that reads the same at both ends of the pipeline. - New moq_mux::select module: Broadcast/Video/Audio fluent builders (default selects nothing; opt a role in, narrow by name/codec, empty field = any). - catalog::Select replaces Filter/FilterVideo/FilterAudio; Stream::filter() -> Stream::select(selection). The adapter is immutable, dropping the old reactive set-mid-stream machinery. - fmp4::Import::with_select restricts which roles are published (new() unchanged, so existing callers still import everything). - moq-hls uses it on both ends: per-rendition export selects only its own axis, and import publishes master-playlist variants video-only beside a separate audio rendition (the track-selection half of #1940). Breaking moq-mux change, targeting main during the pre-semver-bump window. The discontinuity-sequence change from #1940 is intentionally left for a separate PR.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Careful merge: several dev-only features had been backported to main against main's older moq-net API, so the same code exists on both sides in two API shapes. Throughout, dev's newer API is the source of truth; main's genuine post-backport fixes are ported onto it, and main's old-API shapes are dropped. Genuine main fixes ported (translated to dev's API): - moq-mux #1923: AAC BitReader parser rewrite; H.264/H.265 IDR first-slice AU split; fMP4 MissingSampleDuration guard; container poll_aborted (tell a relay eviction from a real decode error); producer backfills every batched sample's duration; MSF AAC SBR/PS trailing-bytes acceptance. - moq-mux #1933: fMP4 zero-duration handling (decode/import/export + infer_missing_durations), with the fallback expressed at the frames' own timescale (dev's Timestamp is multi-scale). - moq-mux #1941: opus encode() returns Result instead of panicking on multichannel (+ mkv::Error::Opus ripple). - moq-mux #1923 catalog Filter/Target: end-with-upstream EOF fix. - moq-srt #1922: negative-pacing offsets (reordered B-frames pace before the anchor); bin derives the HTTP sidecar bind from the real listener. - moq-rtmp: reject a publish cleanly when the broadcast path is unavailable (before acking the client); RTMPS flags gated behind noq/quinn. - moq-ffi: publish_media gains container support (whole-buffer path), re-expressed in dev's reserve_track/MediaDecoder shape. - moq-relay: main's #1902 client-TLS verification (tls.rs) + HTTPS cert arrays (#1932) + the web-embedding routes()/serve() test. - moq-gst: reject multichannel Opus. - Dependency bumps from main's cargo/bun groups (tower-http 0.7, etc.); moq-flate crate added as a workspace member; moq-json adopts moq-flate + main's compressed delta budgeting. kio: dev (#1779) and main (#1913) both added an identical Consumer::write; kept one. dev already had OriginProducer::dynamic and the untyped catalog sections (#1886 dev port), so main's re-introductions were dropped as duplicates. Public-API / scope decisions (deferred as owed follow-ups, documented here): - moq-mux select::Broadcast reshape (68c9ebd/#1944): NOT adopted. main's reshape drops dev's Target (resolution/bitrate ABR) capability that moq-cli depends on, so dev's Filter+Target is kept. Re-port the import-side with_select ergonomics later if wanted. - moq-rtc #1931 session runner: NOT ported. dev's moq-rtc has diverged well past main (whip/whep accept, shared-UDP mux, production hardening); the #1931 API reshape should be re-applied against dev's shape in a follow-up. - moq-hls #1945 (discontinuity sequence through fMP4): deferred. dev's hls import predates main's select-coupled shape; re-port the core moq_sequence/discontinuity logic against dev's importer later. - Rust compressed-catalog (#1904, catalog.json.z / HangZ): deferred on the Rust side (the JS @moq/flate + hangz path is kept). hang::Catalog::compressed_track and the CatalogFormat::HangZ consumer wiring are owed. - moq-relay #1901 (reuse client TLS for outbound auth HTTP): deferred. tls.rs carries #1902, but auth.init keeps dev's 0-arg shape. - moq-json telemetry example removed (main-only, written against main's net API); re-add against dev's API later. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3bVtLrzn4Q82tChYu9EJZ
The moq-cli `hls import` subcommand (main's #1939) auto-merged into the merge using main's old API: `moq_net::Broadcast::new()` and a bool-returning `publish_broadcast` wrapped in `ensure!`. On dev, `Broadcast` is `BroadcastInfo` and `publish_broadcast` returns `Result<OriginPublish>`, so hold the guard via `?` (matching client.rs/server.rs). Also use the canonical `with_publisher`/ `with_subscriber` names instead of the deprecated `with_publish`/`with_consume` aliases. CI caught this; the crate isn't locally buildable here because its optional moq-video dep forces resolving a network-blocked git dependency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3bVtLrzn4Q82tChYu9EJZ
There was a problem hiding this comment.
Sorry @kixelated, your pull request is larger than the review limit of 150000 diff characters
The merged `hls export` subcommand (main's #1939) uses `moq_hls::Server`, which is gated behind moq-hls's `server` feature. The workspace moq-hls dep is `default-features = false`, so the dev-side `moq-hls = { workspace = true }` left it off. Enable `features = ["server"]` to match main. dev's moq-hls API (`export::Config{part_target,window}`, `Server::new(OriginConsumer, Config)`, `router()`) already matches the call site. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3bVtLrzn4Q82tChYu9EJZ
CI statusCheck is green (full cargo build + clippy + tests across the workspace, including
Smoke is red, but it's pre-existing dev debt, not a merge regression. The cross-language interop matrix is green on the diagonal (
These clients track main's API (which is why nightly Smoke on Recommend tracking the 🤖 Generated with Claude Code Generated by Claude Code |
Summary
Merges
mainintodev. The hard part: several dev-only features had been backported tomainagainst main's older moq-net API, so the same code exists on both sides in two API shapes. Throughout this merge, dev's newer API is the source of truth; main's genuine post-backport fixes are ported onto it, and main's old-API shapes are dropped.Genuine main fixes ported (translated to dev's API)
BitReaderparser rewrite; H.264/H.265 IDR first-slice access-unit split; fMP4MissingSampleDurationguard; containerpoll_aborted(distinguishes a relay eviction from a real decode error); producer backfills every batched sample's duration; MSF AAC SBR/PS trailing-byte acceptance; catalogFilter/Targetend-with-upstream EOF fix.infer_missing_durations, with the fallback expressed at the frames' own timescale (dev'sTimestampis multi-scale, unlike main's fixed-microsecond one).opus::Config::encode()returnsResultinstead of panicking on multichannel (+mkv::Error::Opusripple).servebinary derives the HTTP sidecar bind from the real listener.noq/quinn.publish_mediagains whole-buffer container support, re-expressed in dev'sreserve_track/MediaDecodershape.tls.rs) + HTTPS cert arrays ([codex] support relay HTTPS cert arrays #1932) + the web-embeddingroutes()/serve()test.moq-flate(Rust) /@moq/flate(JS) extraction + main's compressed delta budgeting + drain-to-latest backlog collapse; netGroupgainstryReadFrame/tryReadFrameSequence/readable/done; watch/publish gain thehangz(catalog.json.z) compressed catalog.tower-http0.7).Clean-but-broken auto-merges fixed (a naive merge would miss these)
kio: dev (feat(moq-net): request_broadcast returns Unroutable when no route exists #1779) and main (feat(moq-net): add OriginProducer::dynamic + infallible OriginConsumer::request_broadcast #1913) both added an identicalConsumer::write— kept one.hang:compressed_track()used main'smoq_net::Track; reshaped to dev'sTrackInfo.moq-relay: restored theAuthTokenimport dropped by the auto-merge; reverted the feat(moq-relay): reuse client TLS for outbound auth HTTP; make --client-tls-* flags consistent #1901auth.init(tls)call to dev's 0-arg shape.Resultchange rippled into the flv tests (now.encode().unwrap()).Decisions deferred as owed follow-ups (documented in the merge commit)
select::Broadcastreshape (68c9ebd/moq-mux: drop redundant non_exhaustive on select builders #1944): not adopted — it drops dev'sTarget(resolution/bitrate ABR) capability that moq-cli depends on, so dev'sFilter+Targetis kept.HangZ): deferred on the Rust side (the JS@moq/flate+hangzpath is kept).tls.rscarries feat(moq-native): unified client TLS verification + quiche backend support #1902 butauth.initkeeps dev's shape.Test plan
cargo build+cargo testfor every crate touched by the merge:moq-mux(308),moq-json(50),moq-flate(7),hang(16), plusmoq-net/moq-srt/moq-relay/moq-rtmp/moq-rtc/moq-nativecompiling. All green.tsc --noEmit+ Biome clean;bun testfor net (194), json (43), flate (9), msf (7), watch (78), publish (5), hang (34). All green.cargo fmtclean; no conflict markers anywhere.nvidia-video-codec-sdkgit dep behind its egress policy, nor build the GStreamer system dep, somoq-video/moq-boy/moq-cli/libmoq/moq-gstwere validated by compile-of-touched-code only).🤖 Generated with Claude Code
https://claude.ai/code/session_01R3bVtLrzn4Q82tChYu9EJZ
Generated by Claude Code