Repository navigation
telemetry/v2: VoiceChunk as Envelope.voice = 4 - #16
Merged
Merged
Conversation
Per-player voice for telemetry v2: one speaker's consecutive Opus packets per chunk (speaker_slot, first_sequence, timestamp_offset_ms on the capture's time base, repeated opus). Its own Envelope member, not an EchoEvent or a Frame field: voice records arrive 1.9x as often as the server's frame records and about 9x as often as 30 Hz telemetry frames, so inside frames they would bloat every frame and the footer's event index. Additive: buf breaking passes against main. Producer: nevr-spectator (EchoTools/nevr-server-rs, design docs/design/nevr-spectator.md §3). Consumer: the local monitor. Co-Authored-By: nevr-spectator <agents@sprock.io> Co-Authored-By: Andrew Bates <a@sprock.io>
The consumer's ask: voice at a slot hand-over must not land on the wrong player when the roster lags. The voice header carries the slot's generation; telemetry v2's roster carried none, so a chunk could only be matched by slot. Now (slot, generation) names one occupant on both sides. Same counter, measured: in one 4v4 production match's server-to-client decode, every slot that has both an entrant state (genidx at +0x64) and voice has equal values, 6 of 6 (slots 1,2,4,6,8 at 0, slot 5 at 1; slot 5 rules out a voice generation that is always 0); the stat updates' [u16 slot][u16 generation] agree on all 9 slots. Additive: breaking-gate OK. Co-Authored-By: nevr-spectator <agents@sprock.io> Co-Authored-By: Andrew Bates <a@sprock.io>
On a pull_request run the checkout has origin/main but no local refs/heads/main, and the gate's `.git#branch=main` target is a file:// clone that only sees local heads, so it failed closed with "couldn't find remote ref main" (run 39023658105) on every PR. Main's own runs never hit it because there main is the checked-out branch. Make the local branch from origin/<base_ref> first, and name the target by base_ref too. scripts/breaking-gate.sh is untouched, so it still fails closed when the clone or the check cannot run. Reproduced in a clone with no local main: the gate fails with the CI's exact message, and passes after `git branch --force main origin/main`. Co-Authored-By: nevr-spectator <agents@sprock.io> Co-Authored-By: Andrew Bates <a@sprock.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds per-player voice to telemetry v2, plus the slot generation that ties a voice chunk to its player.
What:
telemetry/v2/voice.proto:VoiceChunk { speaker_slot, first_sequence, timestamp_offset_ms, repeated bytes opus, generation }.Envelope.voice = 4.PlayerInfo.generation = 7andPlayerJoined.generation = 7.Why its own Envelope member:
SR15NetUserVoipEvent: a 6-byte header (slot, generation, sequence), then one 20 ms, 48 kHz mono Opus packet. That layout holds on all 15,486 server-to-client voice records of one 4v4 production match. Mean payload is 46.1 B, about 16 kbit/s per talking speaker.EchoArenaFrame.eventsthey would bloat every frame and the footer's event index. As their own envelopes, a reader that does not want voice skips them.Why generation: at a slot hand-over, voice must not land on the wrong player when the roster lags.
(slot, generation)names one occupant on both sides.[u16 slot][u16 generation]agree on all 9 slots.Compatibility: additive.
./scripts/breaking-gate.sh --target '.git#branch=main'reports OK.buf format,buf lintandbuf buildexit 0.Producer: nevr-spectator (EchoTools/nevr-server-rs,
docs/design/nevr-spectator.md§3). Consumer: the local monitor.