zebra-spaces: deploy split outbound telemetry per kind
This commit is contained in:
parent
50452361ae
commit
9f9dc91f7f
1 changed files with 32 additions and 23 deletions
|
|
@ -3921,10 +3921,13 @@ async function dumpTelemetry(){
|
|||
} catch(e){ parts.push('stats.err=' + e.message); }
|
||||
}
|
||||
/* publisher-side stats — what we are actually emitting on the wire.
|
||||
* Catches publisher stalls (X11 compositor blocking the audio thread
|
||||
* during a window wiggle is a real one). gap = now - lastPacketSent
|
||||
* — a gap > frame-interval is a wire stall. rtt is the most recent
|
||||
* round-trip from remote-inbound-rtp (the SFU's view of our sender). */
|
||||
* One line per kind so screen-audio shows up independently of
|
||||
* screen-video (earlier collapse hid scr.send.aud entirely under
|
||||
* scr.send.vid). Critical for diagnosing whether Firefox
|
||||
* getDisplayMedia couples its audio + video source producers under
|
||||
* X11 contention. gap = now - lastPacketSent — a gap > frame-
|
||||
* interval is a wire stall. rtt is the most recent round-trip from
|
||||
* remote-inbound-rtp (the SFU's view of our sender). */
|
||||
const pubPCs = [
|
||||
['mic.send', sfuPubPC],
|
||||
['cam.send', sfuCameraPC],
|
||||
|
|
@ -3936,29 +3939,35 @@ async function dumpTelemetry(){
|
|||
try {
|
||||
const stats = await pc.getStats(null);
|
||||
const nowMs = Date.now();
|
||||
let out = null, remoteIn = null;
|
||||
/* keyed by ssrc so audio + video each get a slot; remote-inbound
|
||||
* pairs back via .ssrc on remote-inbound-rtp → ssrc on outbound. */
|
||||
const outsBySSRC = new Map();
|
||||
const remoteInsBySSRC = new Map();
|
||||
stats.forEach(r => {
|
||||
if (r.type === 'outbound-rtp' && (r.kind === 'audio' || r.kind === 'video')){
|
||||
if (!out || (r.packetsSent|0) > (out.packetsSent|0)) out = r;
|
||||
outsBySSRC.set(r.ssrc, r);
|
||||
}
|
||||
if (r.type === 'remote-inbound-rtp') {
|
||||
if (!remoteIn || (r.packetsLost|0) > (remoteIn.packetsLost|0)) remoteIn = r;
|
||||
if (r.type === 'remote-inbound-rtp' && typeof r.ssrc !== 'undefined') {
|
||||
remoteInsBySSRC.set(r.ssrc, r);
|
||||
}
|
||||
});
|
||||
if (!out) continue;
|
||||
const gap = out.lastPacketSentTimestamp
|
||||
? ((nowMs - out.lastPacketSentTimestamp) / 1000).toFixed(1) + 's'
|
||||
: '?';
|
||||
let s = label + ' pkt=' + (out.packetsSent|0) +
|
||||
' bytes=' + (out.bytesSent|0) +
|
||||
' gap=' + gap;
|
||||
if (out.kind === 'video') s += ' frames=' + (out.framesEncoded|0);
|
||||
if (remoteIn) {
|
||||
s += ' rtt=' + ((remoteIn.roundTripTime||0).toFixed(3)) +
|
||||
' rlost=' + (remoteIn.packetsLost|0) +
|
||||
' rjit=' + ((remoteIn.jitter||0).toFixed(4));
|
||||
for (const out of outsBySSRC.values()){
|
||||
const gap = out.lastPacketSentTimestamp
|
||||
? ((nowMs - out.lastPacketSentTimestamp) / 1000).toFixed(1) + 's'
|
||||
: '?';
|
||||
const kindLabel = out.kind === 'audio' ? '.aud' : '.vid';
|
||||
let s = label + kindLabel + ' pkt=' + (out.packetsSent|0) +
|
||||
' bytes=' + (out.bytesSent|0) +
|
||||
' gap=' + gap;
|
||||
if (out.kind === 'video') s += ' frames=' + (out.framesEncoded|0);
|
||||
const remoteIn = remoteInsBySSRC.get(out.ssrc);
|
||||
if (remoteIn) {
|
||||
s += ' rtt=' + ((remoteIn.roundTripTime||0).toFixed(3)) +
|
||||
' rlost=' + (remoteIn.packetsLost|0) +
|
||||
' rjit=' + ((remoteIn.jitter||0).toFixed(4));
|
||||
}
|
||||
parts.push(s);
|
||||
}
|
||||
parts.push(s);
|
||||
} catch(_){}
|
||||
}
|
||||
/* every <audio> element in the room — both the WebRTC remoteAudio
|
||||
|
|
@ -5941,8 +5950,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
|||
|
||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">a120f5b4723d88b8f6d4518fa647e390</span><br>
|
||||
sha256 <span class="stamp-sha">82d23c2333f6d6ab0f3c2149725d274a44807ec0a878ebf1ddb59cf07c095197</span><br>
|
||||
md5 <span class="stamp-md5">e3c7120739d2e4ef52d4f95860be5eaf</span><br>
|
||||
sha256 <span class="stamp-sha">b4416e44b5dca523fe5c9f32160d8f4d219c585b02d90e84e8d8129646ae27c6</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue